summaryrefslogtreecommitdiffstats
path: root/src/snap.cpp
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2014-11-23 23:36:49 +0000
committerJabiertxof <jtx@jtx.marker.es>2014-11-23 23:36:49 +0000
commit0969085ddf607a7a98cf7fd6d9b10da5fbebe62d (patch)
tree59b2bc9ed3412ab2de4c703ef30342dfe2401704 /src/snap.cpp
parentrefactor from lastApplied (diff)
parentFixed a bug pointed by suv running from comand line, also removed another des... (diff)
downloadinkscape-0969085ddf607a7a98cf7fd6d9b10da5fbebe62d.tar.gz
inkscape-0969085ddf607a7a98cf7fd6d9b10da5fbebe62d.zip
fixing to trunk
(bzr r12588.1.34)
Diffstat (limited to 'src/snap.cpp')
-rw-r--r--src/snap.cpp99
1 files changed, 43 insertions, 56 deletions
diff --git a/src/snap.cpp b/src/snap.cpp
index ecf799cdc..8138e4546 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -116,7 +116,7 @@ void SnapManager::freeSnapReturnByRef(Geom::Point &p,
Inkscape::SnapSourceType const source_type,
Geom::OptRect const &bbox_to_snap) const
{
- Inkscape::SnappedPoint const s = freeSnap(Inkscape::SnapCandidatePoint(p, source_type), bbox_to_snap);
+ Inkscape::SnappedPoint const s = freeSnap(Inkscape::SnapCandidatePoint(p, source_type, Inkscape::SNAPTARGET_PATH), bbox_to_snap);
s.getPointIfSnapped(p);
}
@@ -239,7 +239,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint
// Snapping the mouse pointer instead of the constrained position of the knot allows
// to snap to things which don't intersect with the constraint line; this is basically
// then just a freesnap with the constraint applied afterwards
- // We'll only to this if we're dragging a single handle, and for example not when transforming an object in the selector tool
+ // We'll only do this if we're dragging a single handle, and for example not when transforming an object in the selector tool
result = freeSnap(p, bbox_to_snap);
if (result.getSnapped()) {
// only change the snap indicator if we really snapped to something
@@ -274,7 +274,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint
/* See the documentation for constrainedSnap() directly above for more details.
* The difference is that multipleConstrainedSnaps() will take a list of constraints instead of a single one,
- * and will try to snap the SnapCandidatePoint to all of the provided constraints and see which one fits best
+ * and will try to snap the SnapCandidatePoint to only the closest constraint
* \param p Source point to be snapped
* \param constraints List of directions or lines along which snapping must occur
* \param dont_snap If true then we will only apply the constraint, without snapping
@@ -293,16 +293,11 @@ Inkscape::SnappedPoint SnapManager::multipleConstrainedSnaps(Inkscape::SnapCandi
return no_snap;
}
- IntermSnapResults isr;
- SnapperList const snappers = getSnappers();
- std::vector<Geom::Point> projections;
- bool snapping_is_futile = !someSnapperMightSnap() || dont_snap;
-
- Inkscape::SnappedPoint result = no_snap;
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool snap_mouse = prefs->getBool("/options/snapmousepointer/value", false);
+ // We haven't tried to snap yet; we will first determine which constraint is closest to where we are now,
+ // i.e. lets find out which of the constraints yields the closest projection of point p
+ // Project the mouse pointer on each of the constraints
+ std::vector<Geom::Point> projections;
for (std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin(); c != constraints.end(); ++c) {
// Project the mouse pointer onto the constraint; In case we don't snap then we will
// return the projection onto the constraint, such that the constraint is always enforced
@@ -310,55 +305,47 @@ Inkscape::SnappedPoint SnapManager::multipleConstrainedSnaps(Inkscape::SnapCandi
projections.push_back(pp);
}
- if (snap_mouse && p.isSingleHandle() && !dont_snap) {
+ // Select the closest constraint
+ no_snap.setPoint(projections.front());
+ Inkscape::Snapper::SnapConstraint cc = constraints.front(); //closest constraint
+
+ std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin();
+ std::vector<Geom::Point>::iterator pp = projections.begin();
+ for (; pp != projections.end(); ++pp) {
+ if (Geom::L2(*pp - p.getPoint()) < Geom::L2(no_snap.getPoint() - p.getPoint())) {
+ no_snap.setPoint(*pp); // Remember the projection onto the closest constraint
+ cc = *c; // Remember the closest constraint itself
+ }
+ ++c;
+ }
+
+ if (!someSnapperMightSnap() || dont_snap) {
+ return no_snap;
+ }
+
+ IntermSnapResults isr;
+ SnapperList const snappers = getSnappers();
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool snap_mouse = prefs->getBool("/options/snapmousepointer/value", false);
+
+ Inkscape::SnappedPoint result = no_snap;
+ if (snap_mouse && p.isSingleHandle()) {
// Snapping the mouse pointer instead of the constrained position of the knot allows
// to snap to things which don't intersect with the constraint line; this is basically
// then just a freesnap with the constraint applied afterwards
// We'll only to this if we're dragging a single handle, and for example not when transforming an object in the selector tool
result = freeSnap(p, bbox_to_snap);
+ // Now apply the constraint afterwards
+ result.setPoint(cc.projection(result.getPoint()));
} else {
- // Iterate over the constraints
- for (std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin(); c != constraints.end(); ++c) {
- // Try to snap to the constraint
- if (!snapping_is_futile) {
- for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); ++i) {
- (*i)->constrainedSnap(isr, p, bbox_to_snap, *c, &_items_to_ignore,_unselected_nodes);
- }
- }
+ // Try to snap along the closest constraint
+ for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); ++i) {
+ (*i)->constrainedSnap(isr, p, bbox_to_snap, cc, &_items_to_ignore,_unselected_nodes);
}
result = findBestSnap(p, isr, true);
}
- if (result.getSnapped()) {
- if (snap_mouse) {
- // If "snap_mouse" then we still have to apply the constraint, because so far we only tried a freeSnap
- Geom::Point result_closest;
- for (std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin(); c != constraints.end(); ++c) {
- // Project the mouse pointer onto the constraint; In case we don't snap then we will
- // return the projection onto the constraint, such that the constraint is always enforced
- Geom::Point result_p = (*c).projection(result.getPoint());
- if (c == constraints.begin() || (Geom::L2(result_p - p.getPoint()) < Geom::L2(result_closest - p.getPoint()))) {
- result_closest = result_p;
- }
- }
- result.setPoint(result_closest);
- }
- return result;
- }
-
- // So we didn't snap, but we still need to return a point on one of the constraints
- // Find out which of the constraints yielded the closest projection of point p
- for (std::vector<Geom::Point>::iterator pp = projections.begin(); pp != projections.end(); ++pp) {
- if (pp != projections.begin()) {
- if (Geom::L2(*pp - p.getPoint()) < Geom::L2(no_snap.getPoint() - p.getPoint())) {
- no_snap.setPoint(*pp);
- }
- } else {
- no_snap.setPoint(projections.front());
- }
- }
-
- return no_snap;
+ return result.getSnapped() ? result : no_snap;
}
Inkscape::SnappedPoint SnapManager::constrainedAngularSnap(Inkscape::SnapCandidatePoint const &p,
@@ -443,7 +430,7 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline)
Inkscape::SnapCandidatePoint candidate(p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN, Inkscape::SNAPTARGET_UNDEFINED);
IntermSnapResults isr;
- Inkscape::Snapper::SnapConstraint cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line));
+ Inkscape::Snapper::SnapConstraint cl(guideline.getPoint(), Geom::rot90(guideline.getNormal()));
SnapperList snappers = getSnappers();
for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); ++i) {
@@ -570,7 +557,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// be collected. Therefore we enforce that the first SnapCandidatePoint that is to be freeSnapped always
// has source_num == 0;
// TODO: This is a bit ugly so fix this; do we need sourcenum for anything else? if we don't then get rid
- // of it and explicitely communicate to the object snapper that this is a first point
+ // of it and explicitly communicate to the object snapper that this is a first point
if (first_free_snap) {
(*j).setSourceNum(0);
first_free_snap = false;
@@ -616,8 +603,8 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// and the scaling factor for the other direction should remain
// untouched (unless scaling is uniform of course)
for (int index = 0; index < 2; index++) {
- if (fabs(b[index]) > 1e-6) { // if SCALING CAN occur in this direction
- if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-12) { // if SNAPPING DID occur in this direction
+ if (fabs(b[index]) > 1e-4) { // if SCALING CAN occur in this direction
+ if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-7) { // if SNAPPING DID occur in this direction
result[index] = a[index] / b[index]; // then calculate it!
}
// we might have left result[1-index] = Geom::infinity()
@@ -669,7 +656,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
case ROTATE:
// 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 ;-)
+ result[1] = result[0]; // dummy value; how else should we store an angle in a point ;-)
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)