summaryrefslogtreecommitdiffstats
path: root/src/snap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/snap.cpp')
-rw-r--r--src/snap.cpp94
1 files changed, 68 insertions, 26 deletions
diff --git a/src/snap.cpp b/src/snap.cpp
index 7b0b4ce48..f8fe8e3fa 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<Inkscape::SnapCandidatePoint>::iterator j = transformed_points.begin();
// std::cout << std::endl;
@@ -753,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]);
@@ -802,6 +799,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
@@ -816,11 +816,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
@@ -838,7 +838,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
}
}
@@ -851,8 +851,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:
@@ -881,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:
@@ -932,6 +946,14 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// Using " < 1e6" instead of " < Geom::infinity()" 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 : Geom::infinity());
+
+ 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 +969,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector<Inkscape::SnapCandidatePoint> 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 +993,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector<Inkscape::Snap
Inkscape::SnappedPoint SnapManager::constrainedSnapTranslate(std::vector<Inkscape::SnapCandidatePoint> 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 +1018,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslate(std::vector<Inkscap
Inkscape::SnappedPoint SnapManager::freeSnapScale(std::vector<Inkscape::SnapCandidatePoint> 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 +1043,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(std::vector<Inkscape::SnapCand
Inkscape::SnappedPoint SnapManager::constrainedSnapScale(std::vector<Inkscape::SnapCandidatePoint> 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 +1072,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(std::vector<Inkscape:
Geom::Coord const &s,
Geom::Point const &o,
Geom::Dim2 d,
- bool u) const
+ bool u)
{
Inkscape::SnappedPoint result = _snapTransformed(p, pointer, true, Geom::Point(0,0), STRETCH, Geom::Point(s, s), o, d, u);
@@ -1078,7 +1100,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(std::vector<Inkscape::Sn
Inkscape::Snapper::SnapConstraint const &constraint,
Geom::Point const &s,
Geom::Point const &o,
- Geom::Dim2 d) const
+ Geom::Dim2 d)
{
// "s" contains skew factor in s[0], and scale factor in s[1]
@@ -1113,7 +1135,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(std::vector<Inkscape::Sn
Inkscape::SnappedPoint SnapManager::constrainedSnapRotate(std::vector<Inkscape::SnapCandidatePoint> 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 +1451,26 @@ void SnapManager::_displaySnapsource(Inkscape::SnapCandidatePoint const &p) cons
}
}
+void SnapManager::keepClosestPointOnly(std::vector<Inkscape::SnapCandidatePoint> &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<Inkscape::SnapCandidatePoint>::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++