From c210fd393e9423898f9c745fe081da3d90e9b605 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 27 Dec 2010 22:18:34 +0100 Subject: Node tool: snap while scaling a selection of nodes. Consider this as experimental; needs cleanup! (bzr r9985) --- src/snap.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 8 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 79f398cc5..85d2fd5af 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -22,6 +22,7 @@ #include "sp-namedview.h" #include "snap.h" +#include "snap-enums.h" #include "snapped-line.h" #include "snapped-curve.h" @@ -682,7 +683,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( Geom::Point const &transformation, Geom::Point const &origin, Geom::Dim2 dim, - bool uniform) const + bool uniform) { /* We have a list of points, which we are proposing to transform in some way. We need to see ** if any of these points, when transformed, snap to anything. If they do, we return the @@ -734,6 +735,12 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( g_warning("Unconstrained rotation is not supported!"); } + // We will try to snap a set of points, but we don't want to have a snap indicator displayed + // for each of them. That's why it's temporarily disabled here, and re-enabled again after we + // have finished calling the freeSnap() and constrainedSnap() methods + bool _orig_snapindicator_status = _snapindicator; + _snapindicator = false; + std::vector::iterator j = transformed_points.begin(); // std::cout << std::endl; @@ -802,6 +809,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl; snapped_point.setPointerDistance(Geom::L2(pointer - (*i).getPoint())); + // Allow the snapindicator to be displayed again + _snapindicator = _orig_snapindicator_status; + Geom::Point result; /*Find the transformation that describes where the snapped point has @@ -891,6 +901,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( if (snapped_point.getSnapped()) { // We snapped; keep track of the best snap + // TODO: Compare the transformations instead of the snap points; we should be looking for the closest transformation if (best_snapped_point.isOtherSnapBetter(snapped_point, true)) { best_transformation = result; best_snapped_point = snapped_point; @@ -932,6 +943,15 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // Using " < 1e6" instead of " < NR_HUGE" for catching some rounding errors // These rounding errors might be caused by NRRects, see bug #1584301 best_snapped_point.setSnapDistance(best_metric < 1e6 ? best_metric : NR_HUGE); + + if (_snapindicator) { + if (best_snapped_point.getSnapped()) { + _desktop->snapindicator->set_new_snaptarget(best_snapped_point); + } else { + _desktop->snapindicator->remove_snaptarget(); + } + } + return best_snapped_point; } @@ -947,7 +967,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector const &p, Geom::Point const &pointer, - Geom::Point const &tr) const + Geom::Point const &tr) { Inkscape::SnappedPoint result = _snapTransformed(p, pointer, false, Geom::Point(0,0), TRANSLATE, tr, Geom::Point(0,0), Geom::X, false); @@ -971,7 +991,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector const &p, Geom::Point const &pointer, Inkscape::Snapper::SnapConstraint const &constraint, - Geom::Point const &tr) const + Geom::Point const &tr) { Inkscape::SnappedPoint result = _snapTransformed(p, pointer, true, constraint, TRANSLATE, tr, Geom::Point(0,0), Geom::X, false); @@ -996,7 +1016,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslate(std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, - Geom::Point const &o) const + Geom::Point const &o) { Inkscape::SnappedPoint result = _snapTransformed(p, pointer, false, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); @@ -1021,7 +1041,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, - Geom::Point const &o) const + Geom::Point const &o) { // When constrained scaling, only uniform scaling is supported. Inkscape::SnappedPoint result = _snapTransformed(p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); @@ -1050,7 +1070,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(std::vector const &p, Geom::Point const &pointer, Geom::Coord const &angle, - Geom::Point const &o) const + Geom::Point const &o) { // Snapping the nodes of the bounding box of a selection that is being transformed, will only work if // the transformation of the bounding box is equal to the transformation of the individual nodes. This is @@ -1429,6 +1449,26 @@ void SnapManager::_displaySnapsource(Inkscape::SnapCandidatePoint const &p) cons } } +void SnapManager::keepClosestPointOnly(std::vector &points, const Geom::Point &reference) const +{ + if (points.size() < 2) return; + + Inkscape::SnapCandidatePoint closest_point = Inkscape::SnapCandidatePoint(Geom::Point(NR_HUGE, NR_HUGE), Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED); + Geom::Coord closest_dist = NR_HUGE; + + for(std::vector::const_iterator i = points.begin(); i != points.end(); i++) { + Geom::Coord dist = Geom::L2((*i).getPoint() - reference); + if (i == points.begin() || dist < closest_dist) { + closest_point = *i; + closest_dist = dist; + } + } + + closest_point.setSourceNum(-1); + points.clear(); + points.push_back(closest_point); +} + /* Local Variables: mode:c++ -- cgit v1.2.3 From e2fe5c8411dcbd514f1df51de0925c0719019dc9 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 27 Dec 2010 23:03:25 +0100 Subject: Snapping: improve calculation of metrics for scaling, modify some comments, and remove a line of obsolete debugging output (bzr r9986) --- src/snap.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index 85d2fd5af..f13b02b46 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -826,11 +826,11 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( /* 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 - * line. If we prefer snapping to an intersection instead of to a single + * line. If we prefer snapping to an intersection over to a single * grid line, then we cannot use "metric = Geom::L2(result)". Therefore the * snapped distance will be used as a metric. Please note that the snapped - * distance is defined as the distance to the nearest line of the intersection, - * and not to the intersection itself! + * distance to an intersection is defined as the distance to the nearest line + * of the intersection, and not to the intersection itself! */ // Only for translations, the relevant metric will be the real snapped distance, // so we don't have to do anything special here @@ -848,7 +848,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-12) { // if SNAPPING DID occur in this direction result[index] = a[index] / b[index]; // then calculate it! } - // we might leave result[1-index] = NR_HUGE + // we might have left result[1-index] = NR_HUGE // if scaling didn't occur in the other direction } } @@ -861,8 +861,12 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( } // Compare the resulting scaling with the desired scaling 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])); + if (scale_metric[0] == NR_HUGE || scale_metric[1] == NR_HUGE) { + snapped_point.setSnapDistance(std::min(scale_metric[0], scale_metric[1])); + } else { + snapped_point.setSnapDistance(Geom::L2(scale_metric)); + } + snapped_point.setSecondSnapDistance(NR_HUGE); break; } case STRETCH: @@ -901,7 +905,6 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( if (snapped_point.getSnapped()) { // We snapped; keep track of the best snap - // TODO: Compare the transformations instead of the snap points; we should be looking for the closest transformation if (best_snapped_point.isOtherSnapBetter(snapped_point, true)) { best_transformation = result; best_snapped_point = snapped_point; -- cgit v1.2.3 From 795d604aaf9c1c8146d513fbdcf21ac442a0d1a0 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Sat, 12 Mar 2011 00:01:04 +0100 Subject: Snap while rotating: fix removal of points too close to the rotation center (bzr r10093) --- src/snap.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/snap.cpp') diff --git a/src/snap.cpp b/src/snap.cpp index f13b02b46..fb8f70c49 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -760,16 +760,6 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( dedicated_constraint = Inkscape::Snapper::SnapConstraint(origin, b); } else if (transformation_type == ROTATE) { Geom::Coord r = Geom::L2(b); // the radius of the circular constraint - if (r < 1e-9) { // points too close to the rotation center will not move. Don't try to snap these - // as they will always yield a perfect snap result if they're already snapped beforehand (e.g. - // when the transformation center has been snapped to a grid intersection in the selector tool) - continue; // skip this SnapCandidate and continue with the next one - // PS1: Apparently we don't have to do this for skewing, but why? - // PS2: We cannot easily filter these points upstream, e.g. in the grab() method (seltrans.cpp) - // because the rotation center will change when pressing shift, and grab() won't be recalled. - // Filtering could be done in handleRequest() (again in seltrans.cpp), by iterating through - // the snap candidates. But hey, we're iterating here anyway. - } dedicated_constraint = Inkscape::Snapper::SnapConstraint(origin, b, r); } else if (transformation_type == STRETCH) { // when non-uniform stretching { dedicated_constraint = Inkscape::Snapper::SnapConstraint((*i).getPoint(), component_vectors[dim]); @@ -895,8 +885,18 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // a is vector to snapped point; b is vector to original point; now lets calculate angle between a and b result[0] = atan2(Geom::dot(Geom::rot90(b), a), Geom::dot(b, a)); result[1] = result[1]; // how else should we store an angle in a point ;-) - // Store the metric for this transformation as a virtual distance (we're storing an angle) - snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); + if (Geom::L2(b) < 1e-9) { // points too close to the rotation center will not move. Don't try to snap these + // as they will always yield a perfect snap result if they're already snapped beforehand (e.g. + // when the transformation center has been snapped to a grid intersection in the selector tool) + snapped_point.setSnapDistance(NR_HUGE); + // PS1: Apparently we don't have to do this for skewing, but why? + // PS2: We cannot easily filter these points upstream, e.g. in the grab() method (seltrans.cpp) + // because the rotation center will change when pressing shift, and grab() won't be recalled. + // Filtering could be done in handleRequest() (again in seltrans.cpp), by iterating through + // the snap candidates. But hey, we're iterating here anyway. + } else { + snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); + } snapped_point.setSecondSnapDistance(NR_HUGE); break; default: -- cgit v1.2.3