e781423d621c888bfbcfab74512d797385606aa1dvlierop/**
e781423d621c888bfbcfab74512d797385606aa1dvlierop * \file src/snapped-curve.cpp
bf1d02bbf9f93b5d10304fd4f70f367d430c750eJon A. Cruz * SnappedCurve class.
e781423d621c888bfbcfab74512d797385606aa1dvlierop *
e781423d621c888bfbcfab74512d797385606aa1dvlierop * Authors:
e781423d621c888bfbcfab74512d797385606aa1dvlierop * Diederik van Lierop <mail@diedenrezi.nl>
e781423d621c888bfbcfab74512d797385606aa1dvlierop *
e781423d621c888bfbcfab74512d797385606aa1dvlierop * Released under GNU GPL, read the file 'COPYING' for more information.
e781423d621c888bfbcfab74512d797385606aa1dvlierop */
e781423d621c888bfbcfab74512d797385606aa1dvlierop
e781423d621c888bfbcfab74512d797385606aa1dvlierop#include "snapped-curve.h"
e781423d621c888bfbcfab74512d797385606aa1dvlierop#include <2geom/crossing.h>
e781423d621c888bfbcfab74512d797385606aa1dvlierop#include <2geom/path-intersection.h>
e781423d621c888bfbcfab74512d797385606aa1dvlierop
f8526e9e32507aa02ffdb5fd9f3ee99393ec9afdDiederik van LieropInkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, Geom::Point const &tangent, int num_path, int num_segm, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, long source_num, SnapTargetType target, Geom::OptRect target_bbox)
e781423d621c888bfbcfab74512d797385606aa1dvlierop{
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop _num_path = num_path;
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop _num_segm = num_segm;
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop _distance = snapped_distance;
55dd1351535fdbc7d4087cef62b2c3f59de8726edvlierop _tolerance = std::max(snapped_tolerance, 1.0);
e781423d621c888bfbcfab74512d797385606aa1dvlierop _always_snap = always_snap;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _curve = curve;
cd8e8082c747cc529d5bf595b4102e88224a1811Krzysztof Kosiński _second_distance = Geom::infinity();
55dd1351535fdbc7d4087cef62b2c3f59de8726edvlierop _second_tolerance = 1;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _second_always_snap = false;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _point = snapped_point;
f8526e9e32507aa02ffdb5fd9f3ee99393ec9afdDiederik van Lierop _tangent = tangent;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _at_intersection = false;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _fully_constrained = fully_constrained;
771d00baf3d15209a77dce026f7ef45a78365e62dvlierop _source = source;
1aa821e67cb9667c99920eadec0f58532f73652cDiederik van Lierop _source_num = source_num;
995ec331afc69a2e82dac045e5f8749a4bc6d65edvlierop _target = target;
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop _target_bbox = target_bbox;
e781423d621c888bfbcfab74512d797385606aa1dvlierop}
e781423d621c888bfbcfab74512d797385606aa1dvlierop
71c8857afc501c5e737bce6022fd9ac810d94c05dvlieropInkscape::SnappedCurve::SnappedCurve()
e781423d621c888bfbcfab74512d797385606aa1dvlierop{
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop _num_path = 0;
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop _num_segm = 0;
cd8e8082c747cc529d5bf595b4102e88224a1811Krzysztof Kosiński _distance = Geom::infinity();
55dd1351535fdbc7d4087cef62b2c3f59de8726edvlierop _tolerance = 1;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _always_snap = false;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _curve = NULL;
cd8e8082c747cc529d5bf595b4102e88224a1811Krzysztof Kosiński _second_distance = Geom::infinity();
55dd1351535fdbc7d4087cef62b2c3f59de8726edvlierop _second_tolerance = 1;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _second_always_snap = false;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _point = Geom::Point(0,0);
f8526e9e32507aa02ffdb5fd9f3ee99393ec9afdDiederik van Lierop _tangent = Geom::Point(0,0);
e781423d621c888bfbcfab74512d797385606aa1dvlierop _at_intersection = false;
e781423d621c888bfbcfab74512d797385606aa1dvlierop _fully_constrained = false;
771d00baf3d15209a77dce026f7ef45a78365e62dvlierop _source = SNAPSOURCE_UNDEFINED;
c13adc1aa8f34445131579baa56299b360480b5eDiederik van Lierop _source_num = -1;
995ec331afc69a2e82dac045e5f8749a4bc6d65edvlierop _target = SNAPTARGET_UNDEFINED;
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop _target_bbox = Geom::OptRect();
e781423d621c888bfbcfab74512d797385606aa1dvlierop}
e781423d621c888bfbcfab74512d797385606aa1dvlierop
e781423d621c888bfbcfab74512d797385606aa1dvlieropInkscape::SnappedCurve::~SnappedCurve()
e781423d621c888bfbcfab74512d797385606aa1dvlierop{
e781423d621c888bfbcfab74512d797385606aa1dvlierop}
e781423d621c888bfbcfab74512d797385606aa1dvlierop
d37634d73670180f99a3e0ea583621373d90ec4fJohan EngelenInkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Affine dt2doc) const
e781423d621c888bfbcfab74512d797385606aa1dvlierop{
e781423d621c888bfbcfab74512d797385606aa1dvlierop // Calculate the intersections of two curves, which are both within snapping range, and
e781423d621c888bfbcfab74512d797385606aa1dvlierop // return only the closest intersection
e781423d621c888bfbcfab74512d797385606aa1dvlierop // The point of intersection should be considered for snapping, but might be outside the snapping range
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // PS: We need p (the location of the mouse pointer) to find out which intersection is the
e781423d621c888bfbcfab74512d797385606aa1dvlierop // closest, as there might be multiple intersections of two curves
e781423d621c888bfbcfab74512d797385606aa1dvlierop Geom::Crossings cs = crossings(*(this->_curve), *(curve._curve));
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop
e781423d621c888bfbcfab74512d797385606aa1dvlierop if (cs.size() > 0) {
e781423d621c888bfbcfab74512d797385606aa1dvlierop // There might be multiple intersections: find the closest
cd8e8082c747cc529d5bf595b4102e88224a1811Krzysztof Kosiński Geom::Coord best_dist = Geom::infinity();
cd8e8082c747cc529d5bf595b4102e88224a1811Krzysztof Kosiński Geom::Point best_p = Geom::Point(Geom::infinity(), Geom::infinity());
3399ca485d7be1a359184150f602213481a00004Kris for (Geom::Crossings::const_iterator i = cs.begin(); i != cs.end(); ++i) {
e781423d621c888bfbcfab74512d797385606aa1dvlierop Geom::Point p_ix = this->_curve->pointAt((*i).ta);
e781423d621c888bfbcfab74512d797385606aa1dvlierop Geom::Coord dist = Geom::distance(p_ix, p);
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop // Test if we have two segments (curves) from the same path..
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop if (this->_num_path == curve._num_path) {
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop // Never try to intersect a segment with itself
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop if (this->_num_segm == curve._num_segm) continue;
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop // Two subsequent segments (curves) in a path will have a common node; this node is not considered to be an intersection
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop if (this->_num_segm == curve._num_segm + 1 && (*i).ta == 0 && (*i).tb == 1) continue;
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop if (this->_num_segm + 1 == curve._num_segm && (*i).ta == 1 && (*i).tb == 0) continue;
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop }
5b4319e0715220ba39530755e9d971cbf7fee47fDiederik van Lierop
e781423d621c888bfbcfab74512d797385606aa1dvlierop if (dist < best_dist) {
e781423d621c888bfbcfab74512d797385606aa1dvlierop best_dist = dist;
e781423d621c888bfbcfab74512d797385606aa1dvlierop best_p = p_ix;
e781423d621c888bfbcfab74512d797385606aa1dvlierop }
e781423d621c888bfbcfab74512d797385606aa1dvlierop }
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop // Now we've found the closest intersection, return it as a SnappedPoint
55dd1351535fdbc7d4087cef62b2c3f59de8726edvlierop bool const use_this_as_primary = _distance < curve.getSnapDistance();
e781423d621c888bfbcfab74512d797385606aa1dvlierop Inkscape::SnappedCurve const *primaryC = use_this_as_primary ? this : &curve;
e781423d621c888bfbcfab74512d797385606aa1dvlierop Inkscape::SnappedCurve const *secondaryC = use_this_as_primary ? &curve : this;
11614aeee42f0b626bd7e3f929d9119c59f7c3bddvlierop
11614aeee42f0b626bd7e3f929d9119c59f7c3bddvlierop // The intersection should in fact be returned in desktop coordinates
11614aeee42f0b626bd7e3f929d9119c59f7c3bddvlierop best_p = best_p * dt2doc;
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(best_p - this->getPoint()) : Geom::L2(best_p - curve.getPoint());
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(best_p - curve.getPoint()) : Geom::L2(best_p - this->getPoint());
e781423d621c888bfbcfab74512d797385606aa1dvlierop // TODO: Investigate whether it is possible to use document coordinates everywhere
e781423d621c888bfbcfab74512d797385606aa1dvlierop // in the snapper code. Only the mouse position should be in desktop coordinates, I guess.
e781423d621c888bfbcfab74512d797385606aa1dvlierop // All paths are already in document coords and we are certainly not going to change THAT.
7958bbff516df35ec85075ab114769c23cb3669dDiederik van Lierop return SnappedPoint(best_p, Inkscape::SNAPSOURCE_UNDEFINED, primaryC->getSourceNum(), Inkscape::SNAPTARGET_PATH_INTERSECTION, primaryDist, primaryC->getTolerance(), primaryC->getAlwaysSnap(), true, false, true,
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop secondaryDist, secondaryC->getTolerance(), secondaryC->getAlwaysSnap());
e781423d621c888bfbcfab74512d797385606aa1dvlierop }
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop
e781423d621c888bfbcfab74512d797385606aa1dvlierop // No intersection
cd8e8082c747cc529d5bf595b4102e88224a1811Krzysztof Kosiński return SnappedPoint(Geom::Point(Geom::infinity(), Geom::infinity()), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, Geom::infinity(), 0, false, false, false, false, Geom::infinity(), 0, false);
e781423d621c888bfbcfab74512d797385606aa1dvlierop}
e781423d621c888bfbcfab74512d797385606aa1dvlierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van LieropInkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedLine const &line, Geom::Point const &p, Geom::Affine dt2doc) const
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop{
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // Calculate the intersections of a curve with a line, which are both within snapping range, and
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // return only the closest intersection
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // The point of intersection should be considered for snapping, but might be outside the snapping range
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // PS: We need p (the location of the mouse pointer) to find out which intersection is the
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // closest, as there might be multiple intersections of a single curve with a line
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // 1) get a Geom::Line object from the SnappedLine
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // 2) convert to document coordinates (line and p are in desktop coordinates, but the curves are in document coordinate)
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // 3) create a Geom::LineSegment (i.e. a curve), because we cannot use a Geom::Line for calculating intersections
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // (for this we will create a 2e6 pixels long linesegment, with t running from -1e6 to 1e6; this should be long
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // enough for any practical purpose)
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::LineSegment line_segm = line.getLine().transformed(dt2doc).segment(-1e6, 1e6); //
77ca6e8215c0710fe9233ee899e673604e045549Campbell Barton const Geom::Curve *line_as_curve = dynamic_cast<Geom::Curve const*>(&line_segm);
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::Crossings cs = crossings(*(this->_curve), *line_as_curve);
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop if (cs.size() > 0) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // There might be multiple intersections: find the closest
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::Coord best_dist = Geom::infinity();
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::Point best_p = Geom::Point(Geom::infinity(), Geom::infinity());
3399ca485d7be1a359184150f602213481a00004Kris for (Geom::Crossings::const_iterator i = cs.begin(); i != cs.end(); ++i) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::Point p_ix = this->_curve->pointAt((*i).ta);
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::Coord dist = Geom::distance(p_ix, p);
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop if (dist < best_dist) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop best_dist = dist;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop best_p = p_ix;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // The intersection should in fact be returned in desktop coordinates
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop best_p = best_p * dt2doc;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // Now we've found the closest intersection, return it as a SnappedPoint
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop if (_distance < line.getSnapDistance()) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // curve is the closest, so this is our primary snap target
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop return SnappedPoint(best_p, Inkscape::SNAPSOURCE_UNDEFINED, this->getSourceNum(), Inkscape::SNAPTARGET_PATH_GUIDE_INTERSECTION,
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::L2(best_p - this->getPoint()), this->getTolerance(), this->getAlwaysSnap(), true, false, true,
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::L2(best_p - line.getPoint()), line.getTolerance(), line.getAlwaysSnap());
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop } else {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop return SnappedPoint(best_p, Inkscape::SNAPSOURCE_UNDEFINED, line.getSourceNum(), Inkscape::SNAPTARGET_PATH_GUIDE_INTERSECTION,
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::L2(best_p - line.getPoint()), line.getTolerance(), line.getAlwaysSnap(), true, false, true,
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Geom::L2(best_p - this->getPoint()), this->getTolerance(), this->getAlwaysSnap());
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // No intersection
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop return SnappedPoint(Geom::Point(Geom::infinity(), Geom::infinity()), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, Geom::infinity(), 0, false, false, false, false, Geom::infinity(), 0, false);
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop}
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
e781423d621c888bfbcfab74512d797385606aa1dvlierop// search for the closest snapped line
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lieropbool getClosestCurve(std::list<Inkscape::SnappedCurve> const &list, Inkscape::SnappedCurve &result, bool exclude_paths)
e781423d621c888bfbcfab74512d797385606aa1dvlierop{
e781423d621c888bfbcfab74512d797385606aa1dvlierop bool success = false;
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop
3399ca485d7be1a359184150f602213481a00004Kris for (std::list<Inkscape::SnappedCurve>::const_iterator i = list.begin(); i != list.end(); ++i) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop if (exclude_paths && ((*i).getTarget() == Inkscape::SNAPTARGET_PATH)) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop continue;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
55dd1351535fdbc7d4087cef62b2c3f59de8726edvlierop if ((i == list.begin()) || (*i).getSnapDistance() < result.getSnapDistance()) {
e781423d621c888bfbcfab74512d797385606aa1dvlierop result = *i;
e781423d621c888bfbcfab74512d797385606aa1dvlierop success = true;
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop }
e781423d621c888bfbcfab74512d797385606aa1dvlierop }
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop return success;
e781423d621c888bfbcfab74512d797385606aa1dvlierop}
e781423d621c888bfbcfab74512d797385606aa1dvlierop
e781423d621c888bfbcfab74512d797385606aa1dvlierop// search for the closest intersection of two snapped curves, which are both member of the same collection
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelenbool getClosestIntersectionCS(std::list<Inkscape::SnappedCurve> const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Affine dt2doc)
e781423d621c888bfbcfab74512d797385606aa1dvlierop{
e781423d621c888bfbcfab74512d797385606aa1dvlierop bool success = false;
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop
3399ca485d7be1a359184150f602213481a00004Kris for (std::list<Inkscape::SnappedCurve>::const_iterator i = list.begin(); i != list.end(); ++i) {
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop if ((*i).getTarget() != Inkscape::SNAPTARGET_BBOX_EDGE) { // We don't support snapping to intersections of bboxes,
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop // as this would require two bboxes two be flashed in the snap indicator
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop std::list<Inkscape::SnappedCurve>::const_iterator j = i;
3399ca485d7be1a359184150f602213481a00004Kris ++j;
3399ca485d7be1a359184150f602213481a00004Kris for (; j != list.end(); ++j) {
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop if ((*j).getTarget() != Inkscape::SNAPTARGET_BBOX_EDGE) { // We don't support snapping to intersections of bboxes
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop Inkscape::SnappedPoint sp = (*i).intersect(*j, p, dt2doc);
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop if (sp.getAtIntersection()) {
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop // if it's the first point
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop bool const c1 = !success;
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop // or, if it's closer
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop bool const c2 = sp.getSnapDistance() < result.getSnapDistance();
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop // or, if it's just as close then look at the other distance
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop // (only relevant for snapped points which are at an intersection)
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop bool const c3 = (sp.getSnapDistance() == result.getSnapDistance()) && (sp.getSecondSnapDistance() < result.getSecondSnapDistance());
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop // then prefer this point over the previous one
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop if (c1 || c2 || c3) {
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop result = sp;
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop success = true;
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop }
4c8b4484d62b2a47d96b62a8dff90e2b9124edcaDiederik van Lierop }
e781423d621c888bfbcfab74512d797385606aa1dvlierop }
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop }
e781423d621c888bfbcfab74512d797385606aa1dvlierop }
e781423d621c888bfbcfab74512d797385606aa1dvlierop }
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop
71c8857afc501c5e737bce6022fd9ac810d94c05dvlierop return success;
e781423d621c888bfbcfab74512d797385606aa1dvlierop}
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop// search for the closest intersection of two snapped curves, which are member of two different collections
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lieropbool getClosestIntersectionCL(std::list<Inkscape::SnappedCurve> const &curve_list, std::list<Inkscape::SnappedLine> const &line_list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Affine dt2doc)
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop{
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop bool success = false;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
3399ca485d7be1a359184150f602213481a00004Kris for (std::list<Inkscape::SnappedCurve>::const_iterator i = curve_list.begin(); i != curve_list.end(); ++i) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop if ((*i).getTarget() != Inkscape::SNAPTARGET_BBOX_EDGE) { // We don't support snapping to intersections of bboxes,
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // as this would require two bboxes two be flashed in the snap indicator
3399ca485d7be1a359184150f602213481a00004Kris for (std::list<Inkscape::SnappedLine>::const_iterator j = line_list.begin(); j != line_list.end(); ++j) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop if ((*j).getTarget() != Inkscape::SNAPTARGET_BBOX_EDGE) { // We don't support snapping to intersections of bboxes
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop Inkscape::SnappedPoint sp = (*i).intersect(*j, p, dt2doc);
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop if (sp.getAtIntersection()) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // if it's the first point
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop bool const c1 = !success;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // or, if it's closer
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop bool const c2 = sp.getSnapDistance() < result.getSnapDistance();
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // or, if it's just as close then look at the other distance
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // (only relevant for snapped points which are at an intersection)
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop bool const c3 = (sp.getSnapDistance() == result.getSnapDistance()) && (sp.getSecondSnapDistance() < result.getSecondSnapDistance());
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop // then prefer this point over the previous one
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop if (c1 || c2 || c3) {
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop result = sp;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop success = true;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop }
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop return success;
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop}
dc29d5aae9784dc2344623e55b5f921e0d7cf488Diederik van Lierop
e781423d621c888bfbcfab74512d797385606aa1dvlierop/*
e781423d621c888bfbcfab74512d797385606aa1dvlierop Local Variables:
e781423d621c888bfbcfab74512d797385606aa1dvlierop mode:c++
e781423d621c888bfbcfab74512d797385606aa1dvlierop c-file-style:"stroustrup"
e781423d621c888bfbcfab74512d797385606aa1dvlierop c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
e781423d621c888bfbcfab74512d797385606aa1dvlierop indent-tabs-mode:nil
e781423d621c888bfbcfab74512d797385606aa1dvlierop fill-column:99
e781423d621c888bfbcfab74512d797385606aa1dvlierop End:
e781423d621c888bfbcfab74512d797385606aa1dvlierop*/
e781423d621c888bfbcfab74512d797385606aa1dvlierop// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :