From: Diederik van Lierop Date: Sat, 8 May 2010 21:27:22 +0000 (+0200) Subject: Fix bounding box snapping (LP562205, comment 6, issue II) X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=7958bbff516df35ec85075ab114769c23cb3669d;p=inkscape.git Fix bounding box snapping (LP562205, comment 6, issue II) --- diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index cf2883116..37469fa73 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -794,9 +794,9 @@ void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Poin sc.grid_lines.push_back(dummy); } -void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const +void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const { - SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); sc.points.push_back(dummy); } diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h index 4b1cd4834..58185e2e6 100644 --- a/src/display/canvas-axonomgrid.h +++ b/src/display/canvas-axonomgrid.h @@ -79,7 +79,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; CanvasAxonomGrid *grid; }; diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 3532c504a..a79a6b610 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -1030,9 +1030,9 @@ void CanvasXYGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point co sc.grid_lines.push_back(dummy); } -void CanvasXYGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const +void CanvasXYGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const { - SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); sc.points.push_back(dummy); } diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index daf28c15c..a11d77d1d 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -167,7 +167,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; CanvasXYGrid *grid; }; diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 9796fc5da..11de93d68 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -665,7 +665,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp s.setTransformation(s.getPoint() - p); sc.points.push_back(s); } else { - Inkscape::SnappedPoint dummy(p + *snap_vector, Inkscape::SNAPSOURCE_OTHER_HANDLE, 0, Inkscape::SNAPTARGET_CONSTRAINED_ANGLE, Geom::L2(*snap_vector), 10000, true, false); + Inkscape::SnappedPoint dummy(p + *snap_vector, Inkscape::SNAPSOURCE_OTHER_HANDLE, 0, Inkscape::SNAPTARGET_CONSTRAINED_ANGLE, Geom::L2(*snap_vector), 10000, true, true, false); dummy.setTransformation(*snap_vector); sc.points.push_back(dummy); } diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp index 9121e3ee2..4f70521e0 100644 --- a/src/guide-snapper.cpp +++ b/src/guide-snapper.cpp @@ -74,16 +74,16 @@ void Inkscape::GuideSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point sc.guide_lines.push_back(dummy); } -void Inkscape::GuideSnapper::_addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const +void Inkscape::GuideSnapper::_addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const { - SnappedPoint dummy = SnappedPoint(origin, source, source_num, Inkscape::SNAPTARGET_GUIDE_ORIGIN, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint dummy = SnappedPoint(origin, source, source_num, Inkscape::SNAPTARGET_GUIDE_ORIGIN, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); sc.points.push_back(dummy); } -void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const +void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const { - SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GUIDE, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GUIDE, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), constrained_snap, true); sc.points.push_back(dummy); } diff --git a/src/guide-snapper.h b/src/guide-snapper.h index 5adac6e22..5de1b56a4 100644 --- a/src/guide-snapper.h +++ b/src/guide-snapper.h @@ -35,8 +35,8 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const; - void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; + void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; }; } diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index f2f025332..fc40643c8 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -50,7 +50,7 @@ void Inkscape::LineSnapper::freeSnap(SnappedConstraints &sc, // discern between grids and guides here Geom::Coord const dist_p1 = Geom::L2(p1 - p.getPoint()); if (dist_p1 < getSnapperTolerance()) { - _addSnappedLinesOrigin(sc, p1, dist_p1, p.getSourceType(), p.getSourceNum()); + _addSnappedLinesOrigin(sc, p1, dist_p1, p.getSourceType(), p.getSourceNum(), false); // Only relevant for guides; grids don't have an origin per line // Therefore _addSnappedLinesOrigin() will only be implemented for guides } @@ -104,13 +104,13 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, // This snappoint is therefore fully constrained, so there's no need // to look for additional intersections; just return the snapped point // and forget about the line - _addSnappedPoint(sc, t, dist, p.getSourceType(), p.getSourceNum()); + _addSnappedPoint(sc, t, dist, p.getSourceType(), p.getSourceNum(), true); // For any line that's within range, we will also look at it's "point on line" p1. For guides // this point coincides with its origin; for grids this is of no use, but we cannot // discern between grids and guides here Geom::Coord const dist_p1 = Geom::L2(p1 - p.getPoint()); if (dist_p1 < getSnapperTolerance()) { - _addSnappedLinesOrigin(sc, p1, dist_p1, p.getSourceType(), p.getSourceNum()); + _addSnappedLinesOrigin(sc, p1, dist_p1, p.getSourceType(), p.getSourceNum(), true); // Only relevant for guides; grids don't have an origin per line // Therefore _addSnappedLinesOrigin() will only be implemented for guides } @@ -122,7 +122,7 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, // Will only be overridden in the guide-snapper class, because grid lines don't have an origin; the // grid-snapper classes will use this default empty method -void Inkscape::LineSnapper::_addSnappedLinesOrigin(SnappedConstraints &/*sc*/, Geom::Point const /*origin*/, Geom::Coord const /*snapped_distance*/, SnapSourceType const &/*source_type*/, long /*source_num*/) const +void Inkscape::LineSnapper::_addSnappedLinesOrigin(SnappedConstraints &/*sc*/, Geom::Point const /*origin*/, Geom::Coord const /*snapped_distance*/, SnapSourceType const &/*source_type*/, long /*source_num*/, bool /*constrained_snap*/) const { } diff --git a/src/line-snapper.h b/src/line-snapper.h index 429139421..1aa3526cc 100644 --- a/src/line-snapper.h +++ b/src/line-snapper.h @@ -52,9 +52,9 @@ private: virtual void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const = 0; // Will only be implemented for guide lines, because grid lines don't have an origin - virtual void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; + virtual void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const; - virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const = 0; + virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, bool constrained_snap) const = 0; }; } diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 77449ddc3..536affb82 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -265,7 +265,7 @@ void Inkscape::ObjectSnapper::_snapNodes(SnappedConstraints &sc, for (std::vector::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) { Geom::Coord dist = Geom::L2((*k).getPoint() - p.getPoint()); if (dist < getSnapperTolerance() && dist < s.getSnapDistance()) { - s = SnappedPoint((*k).getPoint(), p.getSourceType(), p.getSourceNum(), (*k).getTargetType(), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, (*k).getTargetBBox()); + s = SnappedPoint((*k).getPoint(), p.getSourceType(), p.getSourceNum(), (*k).getTargetType(), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, true, (*k).getTargetBBox()); success = true; } } @@ -299,7 +299,7 @@ void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &s Geom::Coord dist = Geom::L2((*k).getPoint() - p_proj); // distance from node to the guide Geom::Coord dist2 = Geom::L2(p - p_proj); // distance from projection of node on the guide, to the mouse location if ((dist < tol && dist2 < tol) || getSnapperAlwaysSnap()) { - s = SnappedPoint((*k).getPoint(), SNAPSOURCE_GUIDE, 0, (*k).getTargetType(), dist, tol, getSnapperAlwaysSnap(), true, (*k).getTargetBBox()); + s = SnappedPoint((*k).getPoint(), SNAPSOURCE_GUIDE, 0, (*k).getTargetType(), dist, tol, getSnapperAlwaysSnap(), false, true, (*k).getTargetBBox()); sc.points.push_back(s); } } diff --git a/src/snap.cpp b/src/snap.cpp index 8704ce3bb..c47f93ff1 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -201,7 +201,7 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapCandidatePoint const Geom::OptRect const &bbox_to_snap) const { if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false); } SnappedConstraints sc; @@ -365,7 +365,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint // First project the mouse pointer onto the constraint Geom::Point pp = constraint.projection(p.getPoint()); - Inkscape::SnappedPoint no_snap = Inkscape::SnappedPoint(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_CONSTRAINT, Geom::L2(pp - p.getPoint()), 0, false, false); + Inkscape::SnappedPoint no_snap = Inkscape::SnappedPoint(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_CONSTRAINT, Geom::L2(pp - p.getPoint()), 0, false, true, false); if (!someSnapperMightSnap()) { // Always return point on constraint @@ -648,7 +648,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // the origin of the scaling, then it will scale purely in X or Y // We can therefore only calculate the scaling in this direction // and the scaling factor for the other direction should remain - // untouched (unless scaling is uniform ofcourse) + // untouched (unless scaling is uniform of course) for (int index = 0; index < 2; index++) { if (fabs(b[index]) > 1e-6) { // if SCALING CAN occur in this direction if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-12) { // if SNAPPING DID occur in this direction @@ -697,9 +697,6 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( g_assert_not_reached(); } - // When scaling, we're considering the best transformation in each direction separately. We will have a metric in each - // direction, whereas for all other transformation we only a single one-dimensional metric. That's why we need to handle - // the scaling metric differently if (best_snapped_point.isOtherSnapBetter(snapped_point, true)) { best_transformation = result; best_snapped_point = snapped_point; diff --git a/src/snapped-curve.cpp b/src/snapped-curve.cpp index d4ef0a83f..e7df3cfad 100644 --- a/src/snapped-curve.cpp +++ b/src/snapped-curve.cpp @@ -87,12 +87,12 @@ Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &cur // TODO: Investigate whether it is possible to use document coordinates everywhere // in the snapper code. Only the mouse position should be in desktop coordinates, I guess. // All paths are already in document coords and we are certainly not going to change THAT. - return SnappedPoint(best_p, Inkscape::SNAPSOURCE_UNDEFINED, primaryC->getSourceNum(), Inkscape::SNAPTARGET_PATH_INTERSECTION, primaryDist, primaryC->getTolerance(), primaryC->getAlwaysSnap(), true, true, + return SnappedPoint(best_p, Inkscape::SNAPSOURCE_UNDEFINED, primaryC->getSourceNum(), Inkscape::SNAPTARGET_PATH_INTERSECTION, primaryDist, primaryC->getTolerance(), primaryC->getAlwaysSnap(), true, false, true, secondaryDist, secondaryC->getTolerance(), secondaryC->getAlwaysSnap()); } // No intersection - return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, false, NR_HUGE, 0, false); } // search for the closest snapped line diff --git a/src/snapped-line.cpp b/src/snapped-line.cpp index 9dde22a4e..da17ff81a 100644 --- a/src/snapped-line.cpp +++ b/src/snapped-line.cpp @@ -80,12 +80,12 @@ Inkscape::SnappedPoint Inkscape::SnappedLineSegment::intersect(SnappedLineSegmen Inkscape::SnappedLineSegment const *secondarySLS = use_this_as_primary ? &line : this; Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(inters_pt - this->getPoint()) : Geom::L2(inters_pt - line.getPoint()); Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(inters_pt - line.getPoint()) : Geom::L2(inters_pt - this->getPoint()); - return SnappedPoint(inters_pt, SNAPSOURCE_UNDEFINED, primarySLS->getSourceNum(), SNAPTARGET_PATH_INTERSECTION, primaryDist, primarySLS->getTolerance(), primarySLS->getAlwaysSnap(), true, true, + return SnappedPoint(inters_pt, SNAPSOURCE_UNDEFINED, primarySLS->getSourceNum(), SNAPTARGET_PATH_INTERSECTION, primaryDist, primarySLS->getTolerance(), primarySLS->getAlwaysSnap(), true, false, true, secondaryDist, secondarySLS->getTolerance(), secondarySLS->getAlwaysSnap()); } // No intersection - return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, false, NR_HUGE, 0, false); }; @@ -161,14 +161,14 @@ Inkscape::SnappedPoint Inkscape::SnappedLine::intersect(SnappedLine const &line) Inkscape::SnappedLine const *secondarySL = use_this_as_primary ? &line : this; Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(inters_pt - this->getPoint()) : Geom::L2(inters_pt - line.getPoint()); Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(inters_pt - line.getPoint()) : Geom::L2(inters_pt - this->getPoint()); - return SnappedPoint(inters_pt, Inkscape::SNAPSOURCE_UNDEFINED, primarySL->getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, primaryDist, primarySL->getTolerance(), primarySL->getAlwaysSnap(), true, true, + return SnappedPoint(inters_pt, Inkscape::SNAPSOURCE_UNDEFINED, primarySL->getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, primaryDist, primarySL->getTolerance(), primarySL->getAlwaysSnap(), true, false, true, secondaryDist, secondarySL->getTolerance(), secondarySL->getAlwaysSnap()); // The type of the snap target is yet undefined, as we cannot tell whether // we're snapping to grid or the guide lines; must be set by on a higher level } // No intersection - return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, false, NR_HUGE, 0, false); } // search for the closest snapped line segment diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp index 508ec8f62..352f2dd1e 100644 --- a/src/snapped-point.cpp +++ b/src/snapped-point.cpp @@ -14,11 +14,12 @@ #include "preferences.h" // overloaded constructor -Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained, Geom::OptRect target_bbox) +Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &constrained_snap, bool const &fully_constrained, Geom::OptRect target_bbox) : _point(p), _source(source), _source_num(source_num), _target(target), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a), _target_bbox(target_bbox) { // tolerance should never be smaller than 1 px, as it is used for normalization in isOtherSnapBetter. We don't want a division by zero. _at_intersection = false; + _constrained_snap = constrained_snap; _fully_constrained = fully_constrained; _second_distance = NR_HUGE; _second_tolerance = 1; @@ -27,13 +28,14 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const _pointer_distance = NR_HUGE; } -Inkscape::SnappedPoint::SnappedPoint(Inkscape::SnapCandidatePoint const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained) +Inkscape::SnappedPoint::SnappedPoint(Inkscape::SnapCandidatePoint const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &constrained_snap, bool const &fully_constrained) : _target(target), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a) { _point = p.getPoint(); _source = p.getSourceType(); _source_num = p.getSourceNum(); _at_intersection = false; + _constrained_snap = constrained_snap; _fully_constrained = fully_constrained; _second_distance = NR_HUGE; _second_tolerance = 1; @@ -44,8 +46,8 @@ Inkscape::SnappedPoint::SnappedPoint(Inkscape::SnapCandidatePoint const &p, Snap } -Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2) - : _point(p), _source(source), _source_num(source_num), _target(target), _at_intersection(at_intersection), _fully_constrained(fully_constrained), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a), +Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &constrained_snap, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2) + : _point(p), _source(source), _source_num(source_num), _target(target), _at_intersection(at_intersection), _constrained_snap(constrained_snap), _fully_constrained(fully_constrained), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a), _second_distance(d2), _second_tolerance(std::max(t2,1.0)), _second_always_snap(a2) { // tolerance should never be smaller than 1 px, as it is used for normalization in @@ -62,6 +64,7 @@ Inkscape::SnappedPoint::SnappedPoint() _source_num = 0, _target = SNAPTARGET_UNDEFINED, _at_intersection = false; + _constrained_snap = false; _fully_constrained = false; _distance = NR_HUGE; _tolerance = 1; @@ -155,7 +158,8 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth // however be very large. To compare these in a fair way, we will have to normalize these metrics first // The closest pointer distance will be normalized to 1.0; the other one will be > 1.0 // The snap distance will be normalized to 1.0 if it's equal to the snapper tolerance - double const norm_p = std::min(dist_pointer_this, dist_pointer_other); + double const norm_p = std::min(dist_pointer_this, dist_pointer_other) + 1; + // make sure norm_p is never too close to zero (e.g. when snapping the bbox-corner that was grabbed), by incr. with 1 double const norm_t_other = std::min(50.0, other_one.getTolerance()); double const norm_t_this = std::min(50.0, getTolerance()); dist_other = w * dist_pointer_other / norm_p + (1-w) * dist_other / norm_t_other; @@ -180,9 +184,9 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth // But in no case fall back from a snapper with "always snap" on to one with "always snap" off bool c2n = !other_one.getAlwaysSnap() && getAlwaysSnap(); // or, if we have a fully constrained snappoint (e.g. to a node or an intersection), while the previous one was only partly constrained (e.g. to a line) - bool c3 = other_one.getFullyConstrained() && !getFullyConstrained(); + bool c3 = (other_one.getFullyConstrained() && !other_one.getConstrainedSnap()) && !getFullyConstrained(); // Do not consider constrained snaps here, because these will always be fully constrained anyway // But in no case fall back; (has less priority than c3n, so it is allowed to fall back when c3 is true, see below) - bool c3n = !other_one.getFullyConstrained() && getFullyConstrained(); + bool c3n = !other_one.getFullyConstrained() && (getFullyConstrained() && !getConstrainedSnap()); // When both are fully constrained AND coincident, then prefer nodes over intersections bool d = other_one.getFullyConstrained() && getFullyConstrained() && (Geom::L2(other_one.getPoint() - getPoint()) < 1e-9); @@ -192,7 +196,7 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth // or, if it's just as close then consider the second distance bool c5a = (dist_other == dist_this); - bool c5b = other_one.getSecondSnapDistance() < getSecondSnapDistance(); + bool c5b = (other_one.getSecondSnapDistance() < getSecondSnapDistance()) && (getSecondSnapDistance() < NR_HUGE); // std::cout << other_one.getPoint() << " (Other one, dist = " << dist_other << ") vs. " << getPoint() << " (this one, dist = " << dist_this << ") ---> "; // std::cout << "c1 = " << c1 << " | c2 = " << c2 << " | c2n = " << c2n << " | c3 = " << c3 << " | c3n = " << c3n << " | c4 = " << c4 << " | c4n = " << c4n << " | c5a = " << c5a << " | c5b = " << c5b << std::endl; diff --git a/src/snapped-point.h b/src/snapped-point.h index 10d36f57e..05e954e1e 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -28,9 +28,9 @@ class SnappedPoint public: SnappedPoint(); SnappedPoint(Geom::Point const &p); - SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2); - SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained, Geom::OptRect target_bbox = Geom::OptRect()); - SnappedPoint(SnapCandidatePoint const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained); + SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &constrained_snap, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2); + SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &constrained_snap, bool const &fully_constrained, Geom::OptRect target_bbox = Geom::OptRect()); + SnappedPoint(SnapCandidatePoint const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &constrained_snap, bool const &fully_constrained); ~SnappedPoint(); Geom::Coord getSnapDistance() const {return _distance;} @@ -61,6 +61,7 @@ public: bool getAtIntersection() const {return _at_intersection;} bool getFullyConstrained() const {return _fully_constrained;} + bool getConstrainedSnap() const {return _constrained_snap;} bool getSnapped() const {return _distance < NR_HUGE;} Geom::Point getTransformation() const {return _transformation;} void setTransformation(Geom::Point const t) {_transformation = t;} @@ -97,6 +98,7 @@ protected: long _source_num; // Sequence number of the source point that snapped, if that point is part of a set of points. (starting at zero) SnapTargetType _target; // Describes to what we've snapped to bool _at_intersection; // If true, the snapped point is at an intersection + bool _constrained_snap; // If true, then the snapped point was found when looking for a constrained snap bool _fully_constrained; // When snapping for example to a node, then the snap will be "fully constrained". // When snapping to a line however, the snap is only partly constrained (i.e. only in one dimension)