From 1feb29aa4b344392000609e310433015454bd626 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Fri, 1 Jan 2010 21:06:51 +0100 Subject: Refactor snapping of gradient handles; now behaves like all other snapping, i.e. no more snapping to imaginary infinite lines along the bounding box Fixed bugs: - https://launchpad.net/bugs/371001 (bzr r8932) --- src/snap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 2e38e4f14..bf4c928ad 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -433,7 +433,7 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, 0, Geom::OptRect(), NULL, NULL); + (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), NULL, NULL); } // Snap to intersections of curves, but not to the curves themselves! (see _snapTranslatingGuideToNodes in object-snapper.cpp) @@ -472,14 +472,14 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) SnappedConstraints sc; Inkscape::Snapper::ConstraintLine cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line)); if (object.ThisSnapperMightSnap()) { - object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, 0, Geom::OptRect(), cl, NULL); + object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), cl, NULL); } // Snap to guides & grid lines SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, 0, Geom::OptRect(), cl, NULL); + (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), cl, NULL); } Inkscape::SnappedPoint const s = findBestSnap(p, source_type, sc, false); -- cgit v1.2.3 From e8f4c644181a8a68e2c33e1783f77a400dc1a29f Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 9 Jan 2010 22:14:38 +0100 Subject: Refactoring the snapping API (making it easier to maintain and understand for the devs) (bzr r8960) --- src/snap.cpp | 187 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 94 insertions(+), 93 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index bf4c928ad..970f29ece 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -13,7 +13,7 @@ * * Copyright (C) 2006-2007 Johan Engelen * Copyrigth (C) 2004 Nathan Hurst - * Copyright (C) 1999-2009 Authors + * Copyright (C) 1999-2010 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -158,24 +158,25 @@ bool SnapManager::gridSnapperMightSnap() const * because the original position should not be touched, then freeSnap() should be * called instead. * - * PS: SnapManager::setup() must have been called before calling this method, + * PS: + * 1) SnapManager::setup() must have been called before calling this method, * but only once for a set of points + * 2) Only to be used when a single source point is to be snapped; it assumes + * that source_num = 0, which is inefficient when snapping sets our source points * * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred * \param source_type Detailed description of the source type, will be used by the snap indicator - * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, Geom::Point &p, Inkscape::SnapSourceType const source_type, - long source_num, Geom::OptRect const &bbox_to_snap) const { - //TODO: PointType and source_type are somewhat redundant; can't we get rid of the point_type parameter? - Inkscape::SnappedPoint const s = freeSnap(point_type, p, source_type, source_num, bbox_to_snap); + //TODO: SnapCandidatePoint and point_type are somewhat redundant; can't we get rid of the point_type parameter? + Inkscape::SnappedPoint const s = freeSnap(point_type, Inkscape::SnapCandidatePoint(p, source_type), bbox_to_snap); s.getPoint(p); } @@ -192,22 +193,18 @@ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point * but only once for a set of points * * \param point_type Category of points to which the source point belongs: node, guide or bounding box - * \param p Current position of the snap source - * \param source_type Detailed description of the source type, will be used by the snap indicator - * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero + * \param p Source point to be snapped * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics */ -Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::SnapSourceType const &source_type, - long source_num, +Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointType const point_type, + Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap) const { if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, source_type, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } std::vector *items_to_ignore; @@ -224,14 +221,14 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, point_type, p, source_type, source_num, bbox_to_snap, items_to_ignore, _unselected_nodes); + (*i)->freeSnap(sc, point_type, p, bbox_to_snap, items_to_ignore, _unselected_nodes); } if (_item_to_ignore) { delete items_to_ignore; } - return findBestSnap(p, source_type, sc, false); + return findBestSnap(p, sc, false); } /** @@ -280,9 +277,9 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const Geom::Point const t_offset = t + grid->origin; SnappedConstraints sc; // Only the first three parameters are being used for grid snappers - snapper->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_NODE, t_offset, Inkscape::SNAPSOURCE_UNDEFINED, 0, Geom::OptRect(), NULL, NULL); + snapper->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_UNDEFINED),Geom::OptRect(), NULL, NULL); // Find the best snap for this grid, including intersections of the grid-lines - Inkscape::SnappedPoint s = findBestSnap(t_offset, Inkscape::SNAPSOURCE_UNDEFINED, sc, false); + Inkscape::SnappedPoint s = findBestSnap(Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_UNDEFINED), sc, false); if (s.getSnapped() && (s.getSnapDistance() < nearest_distance)) { // use getSnapDistance() instead of getWeightedDistance() here because the pointer's position // doesn't tell us anything about which node to snap @@ -316,14 +313,17 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const * because the original position should not be touched, then constrainedSnap() should * be called instead. * - * PS: SnapManager::setup() must have been called before calling this method, + * PS: + * 1) SnapManager::setup() must have been called before calling this method, * but only once for a set of points + * 2) Only to be used when a single source point is to be snapped; it assumes + * that source_num = 0, which is inefficient when snapping sets our source points + * * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred * \param source_type Detailed description of the source type, will be used by the snap indicator * \param constraint The direction or line along which snapping must occur - * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ @@ -331,10 +331,9 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp Geom::Point &p, Inkscape::SnapSourceType const source_type, Inkscape::Snapper::ConstraintLine const &constraint, - long source_num, Geom::OptRect const &bbox_to_snap) const { - Inkscape::SnappedPoint const s = constrainedSnap(point_type, p, source_type, constraint, source_num, bbox_to_snap); + Inkscape::SnappedPoint const s = constrainedSnap(point_type, Inkscape::SnapCandidatePoint(p, source_type, 0), constraint, bbox_to_snap); s.getPoint(p); } @@ -350,22 +349,18 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp * but only once for a set of points * * \param point_type Category of points to which the source point belongs: node, guide or bounding box - * \param p Current position of the snap source - * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param p Source point to be snapped * \param constraint The direction or line along which snapping must occur - * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ -Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::SnapSourceType const &source_type, +Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::PointType const point_type, + Inkscape::SnapCandidatePoint const &p, Inkscape::Snapper::ConstraintLine const &constraint, - long source_num, Geom::OptRect const &bbox_to_snap) const { if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, source_type, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } std::vector *items_to_ignore; @@ -380,20 +375,21 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P // First project the mouse pointer onto the constraint - Geom::Point pp = constraint.projection(p); + Geom::Point pp = constraint.projection(p.getPoint()); // Then try to snap the projected point + Inkscape::SnapCandidatePoint candidate(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, Geom::Rect()); SnappedConstraints sc; SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, point_type, pp, source_type, source_num, bbox_to_snap, constraint, items_to_ignore); + (*i)->constrainedSnap(sc, point_type, candidate, bbox_to_snap, constraint, items_to_ignore); } if (_item_to_ignore) { delete items_to_ignore; } - return findBestSnap(pp, source_type, sc, true); + return findBestSnap(candidate, sc, true); } /** @@ -418,9 +414,9 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, return; } - Inkscape::SnapSourceType source_type = Inkscape::SNAPSOURCE_GUIDE_ORIGIN; + Inkscape::SnapCandidatePoint candidate(p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN); if (drag_type == SP_DRAG_ROTATE) { - source_type = Inkscape::SNAPSOURCE_GUIDE; + candidate = Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_GUIDE); } // Snap to nodes @@ -433,11 +429,11 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), NULL, NULL); + (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), NULL, NULL); } // Snap to intersections of curves, but not to the curves themselves! (see _snapTranslatingGuideToNodes in object-snapper.cpp) - Inkscape::SnappedPoint const s = findBestSnap(p, source_type, sc, false, true); + Inkscape::SnappedPoint const s = findBestSnap(candidate, sc, false, true); s.getPoint(p); } @@ -466,23 +462,23 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) return; } - Inkscape::SnapSourceType source_type = Inkscape::SNAPSOURCE_GUIDE_ORIGIN; + Inkscape::SnapCandidatePoint candidate(p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN, Inkscape::SNAPTARGET_UNDEFINED); // Snap to nodes or paths SnappedConstraints sc; Inkscape::Snapper::ConstraintLine cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line)); if (object.ThisSnapperMightSnap()) { - object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), cl, NULL); + object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), cl, NULL); } // Snap to guides & grid lines SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), cl, NULL); + (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), cl, NULL); } - Inkscape::SnappedPoint const s = findBestSnap(p, source_type, sc, false); + Inkscape::SnappedPoint const s = findBestSnap(candidate, sc, false); s.getPoint(p); } @@ -514,7 +510,7 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) Inkscape::SnappedPoint SnapManager::_snapTransformed( Inkscape::SnapPreferences::PointType type, - std::vector > const &points, + std::vector const &points, Geom::Point const &pointer, bool constrained, Inkscape::Snapper::ConstraintLine const &constraint, @@ -533,13 +529,14 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( ** Also used to globally disable all snapping */ if (someSnapperMightSnap() == false) { - return Inkscape::SnappedPoint(); + return Inkscape::SnappedPoint(pointer); } - std::vector > transformed_points; + std::vector transformed_points; Geom::Rect bbox; - for (std::vector >::const_iterator i = points.begin(); i != points.end(); i++) { + long source_num = 0; + for (std::vector::const_iterator i = points.begin(); i != points.end(); i++) { /* Work out the transformed version of this point */ Geom::Point transformed = _transformPoint(*i, transformation_type, transformation, origin, dim, uniform); @@ -551,7 +548,8 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( bbox.expandTo(transformed); } - transformed_points.push_back(std::make_pair(transformed, (*i).second)); + transformed_points.push_back(Inkscape::SnapCandidatePoint(transformed, (*i).getSourceType(), source_num)); + source_num++; } /* The current best transformation */ @@ -565,16 +563,16 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( g_assert(best_snapped_point.getAlwaysSnap() == false); // Check initialization of snapped point g_assert(best_snapped_point.getAtIntersection() == false); - std::vector >::const_iterator j = transformed_points.begin(); - long source_num = 0; + std::vector::const_iterator j = transformed_points.begin(); + // std::cout << std::endl; - for (std::vector >::const_iterator i = points.begin(); i != points.end(); i++) { + for (std::vector::const_iterator i = points.begin(); i != points.end(); i++) { /* Snap it */ Inkscape::SnappedPoint snapped_point; Inkscape::Snapper::ConstraintLine dedicated_constraint = constraint; - Geom::Point const b = ((*i).first - origin); // vector to original point + Geom::Point const b = ((*i).getPoint() - origin); // vector to original point if (constrained) { if ((transformation_type == SCALE || transformation_type == STRETCH) && uniform) { @@ -583,18 +581,18 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // calculate that line here dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, b); } else if (transformation_type == STRETCH) { // when non-uniform stretching { - dedicated_constraint = Inkscape::Snapper::ConstraintLine((*i).first, component_vectors[dim]); + dedicated_constraint = Inkscape::Snapper::ConstraintLine((*i).getPoint(), component_vectors[dim]); } else if (transformation_type == TRANSLATION) { // When doing a constrained translation, all points will move in the same direction, i.e. // either horizontally or vertically. The lines along which they move are therefore all // parallel, but might not be colinear. Therefore we will have to set the point through // which the constraint-line runs here, for each point individually. - dedicated_constraint.setPoint((*i).first); + dedicated_constraint.setPoint((*i).getPoint()); } // else: leave the original constraint, e.g. for skewing if (transformation_type == SCALE && !uniform) { g_warning("Non-uniform constrained scaling is not supported!"); } - snapped_point = constrainedSnap(type, (*j).first, static_cast((*j).second), dedicated_constraint, source_num, bbox); + snapped_point = constrainedSnap(type, *j, dedicated_constraint, bbox); } else { bool const c1 = fabs(b[Geom::X]) < 1e-6; bool const c2 = fabs(b[Geom::Y]) < 1e-6; @@ -603,13 +601,13 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // move in that specific direction; therefore it should only snap in that direction, otherwise // we will get snapped points with an invalid transformation dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, component_vectors[c1]); - snapped_point = constrainedSnap(type, (*j).first, static_cast((*j).second), dedicated_constraint, source_num, bbox); + snapped_point = constrainedSnap(type, *j, dedicated_constraint, bbox); } else { - snapped_point = freeSnap(type, (*j).first, static_cast((*j).second), source_num, bbox); + snapped_point = freeSnap(type, *j, bbox); } } // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl; - snapped_point.setPointerDistance(Geom::L2(pointer - (*i).first)); + snapped_point.setPointerDistance(Geom::L2(pointer - (*i).getPoint())); Geom::Point result; Geom::Point scale_metric(NR_HUGE, NR_HUGE); @@ -623,7 +621,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( switch (transformation_type) { case TRANSLATION: - result = snapped_point.getPoint() - (*i).first; + result = snapped_point.getPoint() - (*i).getPoint(); /* Consider the case in which a box is almost aligned with a grid in both * horizontal and vertical directions. The distance to the intersection of * the grid lines will always be larger then the distance to a single grid @@ -673,7 +671,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( snapped_point.setSecondSnapDistance(NR_HUGE); break; case SKEW: - result[0] = (snapped_point.getPoint()[dim] - ((*i).first)[dim]) / (((*i).first)[1 - dim] - origin[1 - dim]); // skew factor + result[0] = (snapped_point.getPoint()[dim] - ((*i).getPoint())[dim]) / (((*i).getPoint())[1 - dim] - origin[1 - dim]); // skew factor result[1] = transformation[1]; // scale factor // Store the metric for this transformation as a virtual distance snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); @@ -716,7 +714,6 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( } j++; - source_num++; } Geom::Coord best_metric; @@ -755,12 +752,13 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( */ Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::SnapPreferences::PointType point_type, - std::vector > const &p, + std::vector const &p, Geom::Point const &pointer, Geom::Point const &tr) const { if (p.size() == 1) { - _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); @@ -778,13 +776,14 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::SnapPreference */ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::SnapPreferences::PointType point_type, - std::vector > const &p, + std::vector const &p, Geom::Point const &pointer, Inkscape::Snapper::ConstraintLine const &constraint, Geom::Point const &tr) const { if (p.size() == 1) { - _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, true, constraint, TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); @@ -803,13 +802,14 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::SnapPre */ Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::SnapPreferences::PointType point_type, - std::vector > const &p, + std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, Geom::Point const &o) const { if (p.size() == 1) { - _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); @@ -828,14 +828,15 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::SnapPreferences::Poi */ Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferences::PointType point_type, - std::vector > const &p, + std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, Geom::Point const &o) const { // When constrained scaling, only uniform scaling is supported. if (p.size() == 1) { - _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); @@ -855,7 +856,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferenc */ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPreferences::PointType point_type, - std::vector > const &p, + std::vector const &p, Geom::Point const &pointer, Geom::Coord const &s, Geom::Point const &o, @@ -863,7 +864,8 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPrefere bool u) const { if (p.size() == 1) { - _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), STRETCH, Geom::Point(s, s), o, d, u), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), STRETCH, Geom::Point(s, s), o, d, u); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), STRETCH, Geom::Point(s, s), o, d, u); @@ -883,7 +885,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPrefere */ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreferences::PointType point_type, - std::vector > const &p, + std::vector const &p, Geom::Point const &pointer, Inkscape::Snapper::ConstraintLine const &constraint, Geom::Point const &s, @@ -900,7 +902,8 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference g_assert(!(point_type & Inkscape::SnapPreferences::SNAPPOINT_BBOX)); if (p.size() == 1) { - _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), SKEW, s, o, d, false), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), SKEW, s, o, d, false); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, true, constraint, SKEW, s, o, d, false); @@ -910,17 +913,15 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference * \brief Given a set of possible snap targets, find the best target (which is not necessarily * also the nearest target), and show the snap indicator if requested * - * \param p Current position of the snap source - * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param p Source point to be snapped * \param sc A structure holding all snap targets that have been found so far * \param constrained True if the snap is constrained, e.g. for stretching or for purely horizontal translation. - * \param noCurves If true, then do consider snapping to intersections of curves, but not to the curves themself + * \param noCurves If true, then do consider snapping to intersections of curves, but not to the curves themselves * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics */ -Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, - Inkscape::SnapSourceType const source_type, - SnappedConstraints &sc, +Inkscape::SnappedPoint SnapManager::findBestSnap(Inkscape::SnapCandidatePoint const &p, + SnappedConstraints const &sc, bool constrained, bool noCurves) const { @@ -954,8 +955,8 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, if (snapprefs.getSnapIntersectionCS()) { // search for the closest snapped intersection of curves Inkscape::SnappedPoint closestCurvesIntersection; - if (getClosestIntersectionCS(sc.curves, p, closestCurvesIntersection, _desktop->dt2doc())) { - closestCurvesIntersection.setSource(source_type); + if (getClosestIntersectionCS(sc.curves, p.getPoint(), closestCurvesIntersection, _desktop->dt2doc())) { + closestCurvesIntersection.setSource(p.getSourceType()); sp_list.push_back(closestCurvesIntersection); } } @@ -982,7 +983,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, // search for the closest snapped intersection of grid lines Inkscape::SnappedPoint closestGridPoint; if (getClosestIntersectionSL(sc.grid_lines, closestGridPoint)) { - closestGridPoint.setSource(source_type); + closestGridPoint.setSource(p.getSourceType()); closestGridPoint.setTarget(Inkscape::SNAPTARGET_GRID_INTERSECTION); sp_list.push_back(closestGridPoint); } @@ -990,7 +991,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, // search for the closest snapped intersection of guide lines Inkscape::SnappedPoint closestGuidePoint; if (getClosestIntersectionSL(sc.guide_lines, closestGuidePoint)) { - closestGuidePoint.setSource(source_type); + closestGuidePoint.setSource(p.getSourceType()); closestGuidePoint.setTarget(Inkscape::SNAPTARGET_GUIDE_INTERSECTION); sp_list.push_back(closestGuidePoint); } @@ -999,7 +1000,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, if (snapprefs.getSnapIntersectionGG()) { Inkscape::SnappedPoint closestGridGuidePoint; if (getClosestIntersectionSL(sc.grid_lines, sc.guide_lines, closestGridGuidePoint)) { - closestGridGuidePoint.setSource(source_type); + closestGridGuidePoint.setSource(p.getSourceType()); closestGridGuidePoint.setTarget(Inkscape::SNAPTARGET_GRID_GUIDE_INTERSECTION); sp_list.push_back(closestGridGuidePoint); } @@ -1007,11 +1008,11 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, } // now let's see which snapped point gets a thumbs up - Inkscape::SnappedPoint bestSnappedPoint = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_UNDEFINED, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + Inkscape::SnappedPoint bestSnappedPoint(p.getPoint()); // std::cout << "Finding the best snap..." << std::endl; for (std::list::const_iterator i = sp_list.begin(); i != sp_list.end(); i++) { // first find out if this snapped point is within snapping range - // std::cout << "sp = " << from_2geom((*i).getPoint()); + // std::cout << "sp = " << (*i).getPoint() << " | source = " << (*i).getSource() << " | target = " << (*i).getTarget(); if ((*i).getSnapDistance() <= (*i).getTolerance()) { // if it's the first point, or if it is closer than the best snapped point so far if (i == sp_list.begin() || bestSnappedPoint.isOtherSnapBetter(*i, false)) { @@ -1054,7 +1055,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem const *item_to_ignore, - std::vector > *unselected_nodes, + std::vector *unselected_nodes, SPGuide *guide_to_ignore) { g_assert(desktop != NULL); @@ -1085,7 +1086,7 @@ void SnapManager::setup(SPDesktop const *desktop, void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, - std::vector > *unselected_nodes, + std::vector *unselected_nodes, SPGuide *guide_to_ignore) { g_assert(desktop != NULL); @@ -1114,7 +1115,7 @@ SPDocument *SnapManager::getDocument() const * \return The position of the point after transformation */ -Geom::Point SnapManager::_transformPoint(std::pair const &p, +Geom::Point SnapManager::_transformPoint(Inkscape::SnapCandidatePoint const &p, Transformation const transformation_type, Geom::Point const &transformation, Geom::Point const &origin, @@ -1125,10 +1126,10 @@ Geom::Point SnapManager::_transformPoint(std::pair const &p, Geom::Point transformed; switch (transformation_type) { case TRANSLATION: - transformed = p.first + transformation; + transformed = p.getPoint() + transformation; break; case SCALE: - transformed = (p.first - origin) * Geom::Scale(transformation[Geom::X], transformation[Geom::Y]) + origin; + transformed = (p.getPoint() - origin) * Geom::Scale(transformation[Geom::X], transformation[Geom::Y]) + origin; break; case STRETCH: { @@ -1139,15 +1140,15 @@ Geom::Point SnapManager::_transformPoint(std::pair const &p, s[dim] = transformation[dim]; s[1 - dim] = 1; } - transformed = ((p.first - origin) * s) + origin; + transformed = ((p.getPoint() - origin) * s) + origin; break; } case SKEW: // Apply the skew factor - transformed[dim] = (p.first)[dim] + transformation[0] * ((p.first)[1 - dim] - origin[1 - dim]); + transformed[dim] = (p.getPoint())[dim] + transformation[0] * ((p.getPoint())[1 - dim] - origin[1 - dim]); // While skewing, mirroring and scaling (by integer multiples) in the opposite direction is also allowed. // Apply that scale factor here - transformed[1-dim] = (p.first - origin)[1 - dim] * transformation[1] + origin[1 - dim]; + transformed[1-dim] = (p.getPoint() - origin)[1 - dim] * transformation[1] + origin[1 - dim]; break; default: g_assert_not_reached(); @@ -1163,7 +1164,7 @@ Geom::Point SnapManager::_transformPoint(std::pair const &p, * \param p The transformed position of the source point, paired with an identifier of the type of the snap source. */ -void SnapManager::_displaySnapsource(Inkscape::SnapPreferences::PointType point_type, std::pair const &p) const { +void SnapManager::_displaySnapsource(Inkscape::SnapPreferences::PointType point_type, Inkscape::SnapCandidatePoint const &p) const { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/options/snapclosestonly/value")) { -- cgit v1.2.3 From b52865a71a9f83da9719a3ec5f50a4a2cd7cdace Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 10 Jan 2010 01:46:28 +0100 Subject: * Implement node snapping. * Fix minor bug in linear grow. * Add --fixes. * Move some node selection-related functions to ControlPointSelection. Fixed bugs: - https://launchpad.net/bugs/170561 - https://launchpad.net/bugs/171893 - https://launchpad.net/bugs/182585 - https://launchpad.net/bugs/446773 (bzr r8846.2.9) --- src/snap.cpp | 81 +++++++++++++++++++++--------------------------------------- 1 file changed, 28 insertions(+), 53 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 545607889..558f61814 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -30,6 +30,7 @@ #include "inkscape.h" #include "desktop.h" +#include "selection.h" #include "sp-guide.h" #include "preferences.h" #include "event-context.h" @@ -206,29 +207,15 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp bool first_point, Geom::OptRect const &bbox_to_snap) const { - if (!someSnapperMightSnap()) { + if (!someSnapperMightSnap()) { return Inkscape::SnappedPoint(p, source_type, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } - std::vector *items_to_ignore; - if (_item_to_ignore) { // If we have only a single item to ignore - // then build a list containing this single item; - // This single-item list will prevail over any other _items_to_ignore list, should that exist - items_to_ignore = new std::vector; - items_to_ignore->push_back(_item_to_ignore); - } else { - items_to_ignore = _items_to_ignore; - } - SnappedConstraints sc; SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, point_type, p, source_type, first_point, bbox_to_snap, items_to_ignore, _unselected_nodes); - } - - if (_item_to_ignore) { - delete items_to_ignore; + (*i)->freeSnap(sc, point_type, p, source_type, first_point, bbox_to_snap, &_items_to_ignore, _unselected_nodes); } return findBestSnap(p, source_type, sc, false); @@ -368,17 +355,6 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P return Inkscape::SnappedPoint(p, source_type, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } - std::vector *items_to_ignore; - if (_item_to_ignore) { // If we have only a single item to ignore - // then build a list containing this single item; - // This single-item list will prevail over any other _items_to_ignore list, should that exist - items_to_ignore = new std::vector; - items_to_ignore->push_back(_item_to_ignore); - } else { - items_to_ignore = _items_to_ignore; - } - - // First project the mouse pointer onto the constraint Geom::Point pp = constraint.projection(p); // Then try to snap the projected point @@ -386,11 +362,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P SnappedConstraints sc; SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, point_type, pp, source_type, first_point, bbox_to_snap, constraint, items_to_ignore); - } - - if (_item_to_ignore) { - delete items_to_ignore; + (*i)->constrainedSnap(sc, point_type, pp, source_type, first_point, bbox_to_snap, constraint, &_items_to_ignore); } return findBestSnap(pp, source_type, sc, true); @@ -1033,22 +1005,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, return bestSnappedPoint; } -/** - * \brief Prepare the snap manager for the actual snapping, which includes building a list of snap targets - * to ignore and toggling the snap indicator - * - * There are two overloaded setup() methods, of which this one only allows for a single item to be ignored - * whereas the other one will take a list of items to ignore - * - * \param desktop Reference to the desktop to which this snap manager is attached - * \param snapindicator If true then a snap indicator will be displayed automatically (when enabled in the preferences) - * \param item_to_ignore This item will not be snapped to, e.g. the item that is currently being dragged. This avoids "self-snapping" - * \param unselected_nodes Stationary nodes of the path that is currently being edited in the node tool and - * that can be snapped too. Nodes not in this list will not be snapped to, to avoid "self-snapping". Of each - * unselected node both the position (Geom::Point) and the type (Inkscape::SnapTargetType) will be stored - * \param guide_to_ignore Guide that is currently being dragged and should not be snapped to - */ - +/// Convenience shortcut when there is only one item to ignore void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem const *item_to_ignore, @@ -1056,8 +1013,8 @@ void SnapManager::setup(SPDesktop const *desktop, SPGuide *guide_to_ignore) { g_assert(desktop != NULL); - _item_to_ignore = item_to_ignore; - _items_to_ignore = NULL; + _items_to_ignore.clear(); + _items_to_ignore.push_back(item_to_ignore); _desktop = desktop; _snapindicator = snapindicator; _unselected_nodes = unselected_nodes; @@ -1082,17 +1039,35 @@ void SnapManager::setup(SPDesktop const *desktop, void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, - std::vector &items_to_ignore, + std::vector const &items_to_ignore, std::vector > *unselected_nodes, SPGuide *guide_to_ignore) { g_assert(desktop != NULL); - _item_to_ignore = NULL; - _items_to_ignore = &items_to_ignore; + _items_to_ignore = items_to_ignore; + _desktop = desktop; + _snapindicator = snapindicator; + _unselected_nodes = unselected_nodes; + _guide_to_ignore = guide_to_ignore; +} + +/// Setup, taking the list of items to ignore from the desktop's selection. +void SnapManager::setupIgnoreSelection(SPDesktop const *desktop, + bool snapindicator, + std::vector > *unselected_nodes, + SPGuide *guide_to_ignore) +{ _desktop = desktop; _snapindicator = snapindicator; _unselected_nodes = unselected_nodes; _guide_to_ignore = guide_to_ignore; + _items_to_ignore.clear(); + + Inkscape::Selection *sel = _desktop->selection; + GSList const *items = sel->itemList(); + for (GSList *i = const_cast(items); i; i = i->next) { + _items_to_ignore.push_back(static_cast(i->data)); + } } SPDocument *SnapManager::getDocument() const -- cgit v1.2.3 From 996749d3aa59a5fe800cb41c74f2fa9d4e753e38 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Thu, 21 Jan 2010 20:39:43 +0100 Subject: Make snapping while scaling behave similar to other transformations, which makes it more intuitive. (bzr r9011) --- src/snap.cpp | 45 ++++++++++++++------------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index c39cd9e04..705e90470 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -582,7 +582,6 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( snapped_point.setPointerDistance(Geom::L2(pointer - (*i).getPoint())); Geom::Point result; - Geom::Point scale_metric(NR_HUGE, NR_HUGE); if (snapped_point.getSnapped()) { /* We snapped. Find the transformation that describes where the snapped point has @@ -623,8 +622,17 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // if scaling didn't occur in the other direction } } + if (uniform) { + if (fabs(result[0]) < fabs(result[1])) { + result[1] = result[0]; + } else { + result[0] = result[1]; + } + } // Compare the resulting scaling with the desired scaling - scale_metric = result - transformation; // One or both of its components might be NR_HUGE + Geom::Point scale_metric = Geom::abs(result - transformation); // One or both of its components might be NR_HUGE + snapped_point.setSnapDistance(std::min(scale_metric[0], scale_metric[1])); + snapped_point.setSecondSnapDistance(std::max(scale_metric[0], scale_metric[1])); break; } case STRETCH: @@ -656,32 +664,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // 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 (transformation_type == SCALE) { - for (int index = 0; index < 2; index++) { - if (fabs(scale_metric[index]) < fabs(best_scale_metric[index])) { - best_transformation[index] = result[index]; - best_scale_metric[index] = fabs(scale_metric[index]); - // When scaling, we're considering the best transformation in each direction separately - // Therefore two different snapped points might together make a single best transformation - // We will however return only a single snapped point (e.g. to display the snapping indicator) - best_snapped_point = snapped_point; - // std::cout << "SEL "; - } // else { std::cout << " ";} - } - if (uniform) { - if (best_scale_metric[0] < best_scale_metric[1]) { - best_transformation[1] = best_transformation[0]; - best_scale_metric[1] = best_scale_metric[0]; - } else { - best_transformation[0] = best_transformation[1]; - best_scale_metric[0] = best_scale_metric[1]; - } - } - } else { // For all transformations other than scaling - if (best_snapped_point.isOtherSnapBetter(snapped_point, true)) { - best_transformation = result; - best_snapped_point = snapped_point; - } + if (best_snapped_point.isOtherSnapBetter(snapped_point, true)) { + best_transformation = result; + best_snapped_point = snapped_point; } } @@ -700,11 +685,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( } } } - best_metric = std::min(best_scale_metric[0], best_scale_metric[1]); - } else { // For all transformations other than scaling - best_metric = best_snapped_point.getSnapDistance(); } + best_metric = best_snapped_point.getSnapDistance(); best_snapped_point.setTransformation(best_transformation); // Using " < 1e6" instead of " < NR_HUGE" for catching some rounding errors // These rounding errors might be caused by NRRects, see bug #1584301 -- cgit v1.2.3 From c4aa590bedcf358acf15bdf0d8134ae99e3be167 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 23 Jan 2010 14:36:56 +0100 Subject: Remove redundancy from snapping API (type of snapsource no longer has to be specified explicitly) (bzr r9014) --- src/snap.cpp | 94 ++++++++++++++++++++++++++---------------------------------- 1 file changed, 40 insertions(+), 54 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 705e90470..4727c7b3e 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -165,19 +165,17 @@ bool SnapManager::gridSnapperMightSnap() const * 2) Only to be used when a single source point is to be snapped; it assumes * that source_num = 0, which is inefficient when snapping sets our source points * - * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred * \param source_type Detailed description of the source type, will be used by the snap indicator * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ -void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, - Geom::Point &p, +void SnapManager::freeSnapReturnByRef(Geom::Point &p, Inkscape::SnapSourceType const source_type, Geom::OptRect const &bbox_to_snap) const { //TODO: SnapCandidatePoint and point_type are somewhat redundant; can't we get rid of the point_type parameter? - Inkscape::SnappedPoint const s = freeSnap(point_type, Inkscape::SnapCandidatePoint(p, source_type), bbox_to_snap); + Inkscape::SnappedPoint const s = freeSnap(Inkscape::SnapCandidatePoint(p, source_type), bbox_to_snap); s.getPoint(p); } @@ -193,15 +191,13 @@ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point * PS: SnapManager::setup() must have been called before calling this method, * but only once for a set of points * - * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Source point to be snapped * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics */ -Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointType const point_type, - Inkscape::SnapCandidatePoint const &p, +Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap) const { if (!someSnapperMightSnap()) { @@ -212,7 +208,7 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, point_type, p, bbox_to_snap, &_items_to_ignore, _unselected_nodes); + (*i)->freeSnap(sc, p, bbox_to_snap, &_items_to_ignore, _unselected_nodes); } return findBestSnap(p, sc, false); @@ -264,7 +260,7 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const Geom::Point const t_offset = t + grid->origin; SnappedConstraints sc; // Only the first three parameters are being used for grid snappers - snapper->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_UNDEFINED),Geom::OptRect(), NULL, NULL); + snapper->freeSnap(sc, Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_UNDEFINED),Geom::OptRect(), NULL, NULL); // Find the best snap for this grid, including intersections of the grid-lines Inkscape::SnappedPoint s = findBestSnap(Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_UNDEFINED), sc, false); if (s.getSnapped() && (s.getSnapDistance() < nearest_distance)) { @@ -307,20 +303,18 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const * that source_num = 0, which is inefficient when snapping sets our source points * - * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred * \param source_type Detailed description of the source type, will be used by the snap indicator * \param constraint The direction or line along which snapping must occur * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ -void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, - Geom::Point &p, +void SnapManager::constrainedSnapReturnByRef(Geom::Point &p, Inkscape::SnapSourceType const source_type, Inkscape::Snapper::ConstraintLine const &constraint, Geom::OptRect const &bbox_to_snap) const { - Inkscape::SnappedPoint const s = constrainedSnap(point_type, Inkscape::SnapCandidatePoint(p, source_type, 0), constraint, bbox_to_snap); + Inkscape::SnappedPoint const s = constrainedSnap(Inkscape::SnapCandidatePoint(p, source_type, 0), constraint, bbox_to_snap); s.getPoint(p); } @@ -335,14 +329,12 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp * PS: SnapManager::setup() must have been called before calling this method, * but only once for a set of points * - * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Source point to be snapped * \param constraint The direction or line along which snapping must occur * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ -Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::PointType const point_type, - Inkscape::SnapCandidatePoint const &p, +Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint const &p, Inkscape::Snapper::ConstraintLine const &constraint, Geom::OptRect const &bbox_to_snap) const { @@ -358,7 +350,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P SnappedConstraints sc; SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, point_type, candidate, bbox_to_snap, constraint, &_items_to_ignore); + (*i)->constrainedSnap(sc, candidate, bbox_to_snap, constraint, &_items_to_ignore); } return findBestSnap(candidate, sc, true); @@ -401,7 +393,7 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), NULL, NULL); + (*i)->freeSnap(sc, candidate, Geom::OptRect(), NULL, NULL); } // Snap to intersections of curves, but not to the curves themselves! (see _snapTranslatingGuideToNodes in object-snapper.cpp) @@ -440,14 +432,14 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) SnappedConstraints sc; Inkscape::Snapper::ConstraintLine cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line)); if (object.ThisSnapperMightSnap()) { - object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), cl, NULL); + object.constrainedSnap(sc, candidate, Geom::OptRect(), cl, NULL); } // Snap to guides & grid lines SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), cl, NULL); + (*i)->constrainedSnap(sc, candidate, Geom::OptRect(), cl, NULL); } Inkscape::SnappedPoint const s = findBestSnap(candidate, sc, false); @@ -467,7 +459,6 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) * some metrics to quantify the snap "distance", and see if it's better than the * previous snap. Finally, the best ("nearest") snap from all these points is returned. * - * \param type Category of points to which the source point belongs: node or bounding box. * \param points Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). * \param constrained true if the snap is constrained, e.g. for stretching or for purely horizontal translation. @@ -481,7 +472,6 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) */ Inkscape::SnappedPoint SnapManager::_snapTransformed( - Inkscape::SnapPreferences::PointType type, std::vector const &points, Geom::Point const &pointer, bool constrained, @@ -564,7 +554,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( if (transformation_type == SCALE && !uniform) { g_warning("Non-uniform constrained scaling is not supported!"); } - snapped_point = constrainedSnap(type, *j, dedicated_constraint, bbox); + snapped_point = constrainedSnap(*j, dedicated_constraint, bbox); } else { bool const c1 = fabs(b[Geom::X]) < 1e-6; bool const c2 = fabs(b[Geom::Y]) < 1e-6; @@ -573,9 +563,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // move in that specific direction; therefore it should only snap in that direction, otherwise // we will get snapped points with an invalid transformation dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, component_vectors[c1]); - snapped_point = constrainedSnap(type, *j, dedicated_constraint, bbox); + snapped_point = constrainedSnap(*j, dedicated_constraint, bbox); } else { - snapped_point = freeSnap(type, *j, bbox); + snapped_point = freeSnap(*j, bbox); } } // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl; @@ -699,24 +689,22 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( /** * \brief Apply a translation to a set of points and try to snap freely in 2 degrees-of-freedom * - * \param point_type Category of points to which the source point belongs: node or bounding box. * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). * \param tr Proposed translation; the final translation can only be calculated after snapping has occurred * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ -Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, +Inkscape::SnappedPoint SnapManager::freeSnapTranslation(std::vector const &p, Geom::Point const &pointer, Geom::Point const &tr) const { if (p.size() == 1) { Geom::Point pt = _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); - _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); + _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } - return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + return _snapTransformed(p, pointer, false, Geom::Point(0,0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); } /** @@ -730,18 +718,17 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::SnapPreference * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ -Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, +Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(std::vector const &p, Geom::Point const &pointer, Inkscape::Snapper::ConstraintLine const &constraint, Geom::Point const &tr) const { if (p.size() == 1) { Geom::Point pt = _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); - _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); + _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } - return _snapTransformed(point_type, p, pointer, true, constraint, TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + return _snapTransformed(p, pointer, true, constraint, TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); } @@ -756,18 +743,17 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::SnapPre * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ -Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, +Inkscape::SnappedPoint SnapManager::freeSnapScale(std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, Geom::Point const &o) const { if (p.size() == 1) { Geom::Point pt = _transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); - _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); + _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } - return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); + return _snapTransformed(p, pointer, false, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); } @@ -782,8 +768,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::SnapPreferences::Poi * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ -Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, +Inkscape::SnappedPoint SnapManager::constrainedSnapScale(std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, Geom::Point const &o) const @@ -791,10 +776,10 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferenc // When constrained scaling, only uniform scaling is supported. if (p.size() == 1) { Geom::Point pt = _transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); - _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); + _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } - return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); + return _snapTransformed(p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); } /** @@ -810,8 +795,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferenc * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ -Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, +Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(std::vector const &p, Geom::Point const &pointer, Geom::Coord const &s, Geom::Point const &o, @@ -820,10 +804,10 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPrefere { if (p.size() == 1) { Geom::Point pt = _transformPoint(p.at(0), STRETCH, Geom::Point(s, s), o, d, u); - _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); + _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } - return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), STRETCH, Geom::Point(s, s), o, d, u); + return _snapTransformed(p, pointer, true, Geom::Point(0,0), STRETCH, Geom::Point(s, s), o, d, u); } /** @@ -839,8 +823,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPrefere * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ -Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, +Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(std::vector const &p, Geom::Point const &pointer, Inkscape::Snapper::ConstraintLine const &constraint, Geom::Point const &s, @@ -854,14 +837,16 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference // NOT the case for example when rotating or skewing. The bounding box itself cannot possibly rotate or skew, // so it's corners have a different transformation. The snappers cannot handle this, therefore snapping // of bounding boxes is not allowed here. - g_assert(!(point_type & Inkscape::SnapPreferences::SNAPPOINT_BBOX)); + if (p.size() > 0) { + g_assert(!(p.at(0).getSourceType() & Inkscape::SNAPSOURCE_BBOX_CATEGORY)); + } if (p.size() == 1) { Geom::Point pt = _transformPoint(p.at(0), SKEW, s, o, d, false); - _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); + _displaySnapsource(Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } - return _snapTransformed(point_type, p, pointer, true, constraint, SKEW, s, o, d, false); + return _snapTransformed(p, pointer, true, constraint, SKEW, s, o, d, false); } /** @@ -1122,12 +1107,13 @@ Geom::Point SnapManager::_transformPoint(Inkscape::SnapCandidatePoint const &p, * \param p The transformed position of the source point, paired with an identifier of the type of the snap source. */ -void SnapManager::_displaySnapsource(Inkscape::SnapPreferences::PointType point_type, Inkscape::SnapCandidatePoint const &p) const { +void SnapManager::_displaySnapsource(Inkscape::SnapCandidatePoint const &p) const { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/options/snapclosestonly/value")) { - bool p_is_a_node = point_type & Inkscape::SnapPreferences::SNAPPOINT_NODE; - bool p_is_a_bbox = point_type & Inkscape::SnapPreferences::SNAPPOINT_BBOX; + bool p_is_a_node = p.getSourceType() & Inkscape::SNAPSOURCE_NODE_CATEGORY; + bool p_is_a_bbox = p.getSourceType() & Inkscape::SNAPSOURCE_BBOX_CATEGORY; + if (snapprefs.getSnapEnabledGlobally() && ((p_is_a_node && snapprefs.getSnapModeNode()) || (p_is_a_bbox && snapprefs.getSnapModeBBox()))) { _desktop->snapindicator->set_new_snapsource(p); } else { -- cgit v1.2.3 From e52fb9fac3f1bbd924c0ca3b6b5e214a095d44af Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 30 Jan 2010 23:04:33 +0100 Subject: Finally introducing the pre-snap indicator (bzr r9034) --- src/snap.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 4727c7b3e..9ee575e22 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -214,6 +214,22 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapCandidatePoint const return findBestSnap(p, sc, false); } +void SnapManager::preSnap(Inkscape::SnapCandidatePoint const &p) +{ + // setup() must have been called before calling this method! + + if (_snapindicator) { + _snapindicator = false; // prevent other methods from drawing a snap indicator; we want to control this here + Inkscape::SnappedPoint s = freeSnap(p); + if (s.getSnapped()) { + _desktop->snapindicator->set_new_snaptarget(s, true); + } else { + _desktop->snapindicator->remove_snaptarget(); + } + _snapindicator = true; // restore the original value + } +} + /** * \brief Snap to the closest multiple of a grid pitch * -- cgit v1.2.3 From 27dcd5655a0e3c257e987fd0113df629ea4e33ba Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Fri, 12 Feb 2010 19:58:21 +0100 Subject: Constrained snapping: always enforce constraint, even when we didn't snap (bzr r9082) --- src/snap.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 9ee575e22..3cac53ebe 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -354,12 +354,14 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint Inkscape::Snapper::ConstraintLine const &constraint, Geom::OptRect const &bbox_to_snap) const { + // First project the mouse pointer onto the constraint + Geom::Point pp = constraint.projection(p.getPoint()); + if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + // The constraint should always be enforce, so we return pp here instead of p + return Inkscape::SnappedPoint(pp, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } - // First project the mouse pointer onto the constraint - Geom::Point pp = constraint.projection(p.getPoint()); // Then try to snap the projected point Inkscape::SnapCandidatePoint candidate(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, Geom::Rect()); -- cgit v1.2.3 From 1bcefc481bd2bf48d228271e48a33c383894d83a Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Fri, 12 Feb 2010 20:46:21 +0100 Subject: Fix compilation error introduced by my previous commit (bzr r9083) --- src/snap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 3cac53ebe..996ec2e2c 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -359,7 +359,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint if (!someSnapperMightSnap()) { // The constraint should always be enforce, so we return pp here instead of p - return Inkscape::SnappedPoint(pp, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } // Then try to snap the projected point -- cgit v1.2.3 From 99c82c93cb8e9d023cb65f5e0f6ea357db5092ba Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sun, 21 Feb 2010 10:01:33 +0100 Subject: Make sure that guides always snap correctly when dropping them, and improve perseverance of snap-indicator (bzr r9103) --- src/snap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 996ec2e2c..1033b0a2c 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -224,7 +224,7 @@ void SnapManager::preSnap(Inkscape::SnapCandidatePoint const &p) if (s.getSnapped()) { _desktop->snapindicator->set_new_snaptarget(s, true); } else { - _desktop->snapindicator->remove_snaptarget(); + _desktop->snapindicator->remove_snaptarget(true); } _snapindicator = true; // restore the original value } -- cgit v1.2.3 From 76e1015affb07da45fb04e3f7a5a6d9d7c5a272c Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 22 Feb 2010 23:18:29 +0100 Subject: 1) Making snapping behaviour for paraxial lines (in the pen tool) similar to other tools 2) Always apply the constraint when asking for a constrained snap 3) Show snap indicator when applying a constraint (bzr r9105) --- src/snap.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 1033b0a2c..53832994f 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -357,9 +357,14 @@ 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); + if (!someSnapperMightSnap()) { - // The constraint should always be enforce, so we return pp here instead of p - return Inkscape::SnappedPoint(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + // The constraint should always be enforced, so we return pp here instead of p + if (_snapindicator) { + _desktop->snapindicator->set_new_snaptarget(no_snap); + } + return no_snap; } // Then try to snap the projected point @@ -371,7 +376,17 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint (*i)->constrainedSnap(sc, candidate, bbox_to_snap, constraint, &_items_to_ignore); } - return findBestSnap(candidate, sc, true); + Inkscape::SnappedPoint result = findBestSnap(candidate, sc, true); + + if (result.getSnapped()) { + return result; + } + + // The constraint should always be enforced, so we return pp here instead of p + if (_snapindicator) { + _desktop->snapindicator->set_new_snaptarget(no_snap); + } + return no_snap; } /** -- cgit v1.2.3 From 6edc17e9611bfc1875cf3fdbaf8fb1ce3c820b89 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Thu, 25 Feb 2010 22:54:44 +0100 Subject: 1) Fix moving by an integer multiple of the grid spacing (-dragging in the selector tool) 2) Allow constrained translation for 1) (with ) 3) Fix snapping to the grid when pasting 4) Show snap indicators for all of the above 5) Implement snap delay mechanism for 1) and 2) (bzr r9113) --- src/snap.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 53832994f..0df58080e 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -249,15 +249,16 @@ void SnapManager::preSnap(Inkscape::SnapCandidatePoint const &p) * \return Offset vector after snapping to the closest multiple of a grid pitch */ -Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const +Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t, Geom::Point const &origin) { - if (!snapprefs.getSnapEnabledGlobally()) // No need to check for snapprefs.getSnapPostponedGlobally() here + if (!snapprefs.getSnapEnabledGlobally() || snapprefs.getSnapPostponedGlobally()) return t; if (_desktop && _desktop->gridsEnabled()) { bool success = false; Geom::Point nearest_multiple; Geom::Coord nearest_distance = NR_HUGE; + Inkscape::SnappedPoint bestSnappedPoint(t); // It will snap to the grid for which we find the closest snap. This might be a different // grid than to which the objects were initially aligned. I don't see an easy way to fix @@ -276,21 +277,28 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const Geom::Point const t_offset = t + grid->origin; SnappedConstraints sc; // Only the first three parameters are being used for grid snappers - snapper->freeSnap(sc, Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_UNDEFINED),Geom::OptRect(), NULL, NULL); + snapper->freeSnap(sc, Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_GRID_PITCH),Geom::OptRect(), NULL, NULL); // Find the best snap for this grid, including intersections of the grid-lines - Inkscape::SnappedPoint s = findBestSnap(Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_UNDEFINED), sc, false); + bool old_val = _snapindicator; + _snapindicator = false; + Inkscape::SnappedPoint s = findBestSnap(Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_GRID_PITCH), sc, false); + _snapindicator = old_val; if (s.getSnapped() && (s.getSnapDistance() < nearest_distance)) { // use getSnapDistance() instead of getWeightedDistance() here because the pointer's position // doesn't tell us anything about which node to snap success = true; nearest_multiple = s.getPoint() - to_2geom(grid->origin); nearest_distance = s.getSnapDistance(); + bestSnappedPoint = s; } } } - if (success) + if (success) { + bestSnappedPoint.setPoint(origin + nearest_multiple); + _desktop->snapindicator->set_new_snaptarget(bestSnappedPoint); return nearest_multiple; + } } return t; -- cgit v1.2.3 From 3484bb5eb21a117e39cb50f65fe6f0541be78d45 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 8 Mar 2010 22:06:42 +0100 Subject: Don't snap to points which are off-screen (bzr r9167) --- src/snap.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 0df58080e..352683623 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -281,7 +281,7 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t, Geom::Point c // Find the best snap for this grid, including intersections of the grid-lines bool old_val = _snapindicator; _snapindicator = false; - Inkscape::SnappedPoint s = findBestSnap(Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_GRID_PITCH), sc, false); + Inkscape::SnappedPoint s = findBestSnap(Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_GRID_PITCH), sc, false, false, true); _snapindicator = old_val; if (s.getSnapped() && (s.getSnapDistance() < nearest_distance)) { // use getSnapDistance() instead of getWeightedDistance() here because the pointer's position @@ -898,13 +898,15 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(std::vector::const_iterator i = sp_list.begin(); i != sp_list.end(); i++) { - // first find out if this snapped point is within snapping range // std::cout << "sp = " << (*i).getPoint() << " | source = " << (*i).getSource() << " | target = " << (*i).getTarget(); - if ((*i).getSnapDistance() <= (*i).getTolerance()) { - // if it's the first point, or if it is closer than the best snapped point so far - if (i == sp_list.begin() || bestSnappedPoint.isOtherSnapBetter(*i, false)) { - // then prefer this point over the previous one - bestSnappedPoint = *i; + bool onScreen = _desktop->get_display_area().contains((*i).getPoint()); + if (onScreen || allowOffScreen) { // Only snap to points which are not off the screen + if ((*i).getSnapDistance() <= (*i).getTolerance()) { // Only snap to points within snapping range + // if it's the first point, or if it is closer than the best snapped point so far + if (i == sp_list.begin() || bestSnappedPoint.isOtherSnapBetter(*i, false)) { + // then prefer this point over the previous one + bestSnappedPoint = *i; + } } } // std::cout << std::endl; -- cgit v1.2.3 From a87f933596b37ac2194537f20d4bf91b8899adba Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sun, 14 Mar 2010 22:04:08 +0100 Subject: New node tool: implement handle snapping Fixed bugs: - https://launchpad.net/bugs/538487 (bzr r9192) --- src/snap.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 352683623..b8b08dad5 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -368,32 +368,25 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint Inkscape::SnappedPoint no_snap = Inkscape::SnappedPoint(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_CONSTRAINT, Geom::L2(pp - p.getPoint()), 0, false, false); if (!someSnapperMightSnap()) { - // The constraint should always be enforced, so we return pp here instead of p - if (_snapindicator) { - _desktop->snapindicator->set_new_snaptarget(no_snap); - } + // Always return point on constraint return no_snap; } - // Then try to snap the projected point - Inkscape::SnapCandidatePoint candidate(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, Geom::Rect()); - SnappedConstraints sc; SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, candidate, bbox_to_snap, constraint, &_items_to_ignore); + (*i)->constrainedSnap(sc, p, bbox_to_snap, constraint, &_items_to_ignore); } - Inkscape::SnappedPoint result = findBestSnap(candidate, sc, true); + Inkscape::SnappedPoint result = findBestSnap(p, sc, true); if (result.getSnapped()) { + // only change the snap indicator if we really snapped to something + if (_snapindicator) { + _desktop->snapindicator->set_new_snaptarget(result); + } return result; } - - // The constraint should always be enforced, so we return pp here instead of p - if (_snapindicator) { - _desktop->snapindicator->set_new_snaptarget(no_snap); - } return no_snap; } -- cgit v1.2.3