summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 26c33d9)
raw | patch | inline | side by side (parent: 26c33d9)
author | Diederik van Lierop <mailat-signdiedenrezidotnl> | |
Tue, 10 Aug 2010 22:18:26 +0000 (00:18 +0200) | ||
committer | Diederik van Lierop <mailat-signdiedenrezidotnl> | |
Tue, 10 Aug 2010 22:18:26 +0000 (00:18 +0200) |
diff --git a/src/draw-context.cpp b/src/draw-context.cpp
index a531b88d13bc69861932501316fc8beb59abe212..c0ae626d5f436773fda56d0e34cae72e0d33cce6 100644 (file)
--- a/src/draw-context.cpp
+++ b/src/draw-context.cpp
@@ -511,7 +511,7 @@ void spdc_endpoint_snap_rotation(SPEventContext const *const ec, Geom::Point &p,
/* Snap it along best vector */
SnapManager &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager;
m.setup(SP_EVENT_CONTEXT_DESKTOP(ec));
- m.constrainedSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE, Inkscape::Snapper::SnapConstraint(best));
+ m.constrainedSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE, Inkscape::Snapper::SnapConstraint(o, best));
}
}
}
diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp
index 19e6c0fe67b56108957c937ccee6b24bb4179783..0a1567a47a21454cfa6357acf50b9d9969779a26 100644 (file)
--- a/src/line-snapper.cpp
+++ b/src/line-snapper.cpp
Inkscape::SnapCandidatePoint const &p,
Geom::OptRect const &/*bbox_to_snap*/,
SnapConstraint const &c,
- std::vector<SPItem const *> const */*it*/) const
+ std::vector<SPItem const *> const */*it*/,
+ std::vector<SnapCandidatePoint> */*unselected_nodes*/) const
{
if (_snap_enabled == false || _snapmanager->snapprefs.getSnapFrom(p.getSourceType()) == false) {
diff --git a/src/line-snapper.h b/src/line-snapper.h
index 4f3d17998f9fe371612506b1e8c2aed6020dfb60..cdc45c286bce947b2cb86904c88f7095025702db 100644 (file)
--- a/src/line-snapper.h
+++ b/src/line-snapper.h
Inkscape::SnapCandidatePoint const &p,
Geom::OptRect const &bbox_to_snap,
SnapConstraint const &c,
- std::vector<SPItem const *> const *it) const;
+ std::vector<SPItem const *> const *it,
+ std::vector<SnapCandidatePoint> *unselected_nodes) const;
protected:
typedef std::list<std::pair<Geom::Point, Geom::Point> > LineList;
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index d84ee9c4f09db5009019d874be01dd4d9ab60b4e..23af26d47f36d48e291fd8efbb8998249b2006e2 100644 (file)
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
void Inkscape::ObjectSnapper::_snapNodes(SnappedConstraints &sc,
Inkscape::SnapCandidatePoint const &p,
- std::vector<SnapCandidatePoint> *unselected_nodes) const
+ std::vector<SnapCandidatePoint> *unselected_nodes,
+ SnapConstraint const &c) const
{
// Iterate through all nodes, find out which one is the closest to p, and snap to it!
bool success = false;
for (std::vector<SnapCandidatePoint>::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) {
- Geom::Coord dist = Geom::L2((*k).getPoint() - p.getPoint());
+ Geom::Point target_pt = (*k).getPoint();
+ if (!c.isUndefined()) {
+ // We're snapping to nodes along a constraint only, so find out if this node
+ // is at the constraint, while allowing for a small margin
+ if (Geom::L2(target_pt - c.projection(target_pt)) > 1e-9) {
+ // The distance from the target point to its projection on the constraint
+ // is too large, so this point is not on the constraint. Skip it!
+ continue;
+ }
+ }
+
+ Geom::Coord dist = Geom::L2(target_pt - p.getPoint());
if (dist < getSnapperTolerance() && dist < s.getSnapDistance()) {
- s = SnappedPoint((*k).getPoint(), p.getSourceType(), p.getSourceNum(), (*k).getTargetType(), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, true, (*k).getTargetBBox());
+ s = SnappedPoint(target_pt, p.getSourceType(), p.getSourceNum(), (*k).getTargetType(), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, true, (*k).getTargetBBox());
success = true;
}
}
Geom::Coord tol = getSnapperTolerance();
for (std::vector<SnapCandidatePoint>::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) {
-
+ Geom::Point target_pt = (*k).getPoint();
// Project each node (*k) on the guide line (running through point p)
- Geom::Point p_proj = Geom::projection((*k).getPoint(), Geom::Line(p, p + Geom::rot90(guide_normal)));
- Geom::Coord dist = Geom::L2((*k).getPoint() - p_proj); // distance from node to the guide
+ Geom::Point p_proj = Geom::projection(target_pt, Geom::Line(p, p + Geom::rot90(guide_normal)));
+ Geom::Coord dist = Geom::L2(target_pt - p_proj); // distance from node to the guide
Geom::Coord dist2 = Geom::L2(p - p_proj); // distance from projection of node on the guide, to the mouse location
if ((dist < tol && dist2 < tol) || getSnapperAlwaysSnap()) {
- s = SnappedPoint((*k).getPoint(), SNAPSOURCE_GUIDE, 0, (*k).getTargetType(), dist, tol, getSnapperAlwaysSnap(), false, true, (*k).getTargetBBox());
+ s = SnappedPoint(target_pt, SNAPSOURCE_GUIDE, 0, (*k).getTargetType(), dist, tol, getSnapperAlwaysSnap(), false, true, (*k).getTargetBBox());
sc.points.push_back(s);
}
}
_findCandidates(sp_document_root(_snapmanager->getDocument()), it, p.getSourceNum() == 0, local_bbox_to_snap, false, Geom::identity());
}
-
+ // TODO: Argh, UGLY! Get rid of this here, move this logic to the snap manager
bool snap_nodes = (_snapmanager->snapprefs.getSnapModeNode() && (
_snapmanager->snapprefs.getSnapToItemNode() ||
_snapmanager->snapprefs.getSnapSmoothNodes() ||
Inkscape::SnapCandidatePoint const &p,
Geom::OptRect const &bbox_to_snap,
SnapConstraint const &c,
- std::vector<SPItem const *> const *it) const
+ std::vector<SPItem const *> const *it,
+ std::vector<SnapCandidatePoint> *unselected_nodes) const
{
if (_snap_enabled == false || _snapmanager->snapprefs.getSnapFrom(p.getSourceType()) == false) {
return;
// This is useful for example when scaling an object while maintaining a fixed aspect ratio. It's
// nodes are only allowed to move in one direction (i.e. in one degree of freedom).
- // When snapping to objects, we either snap to their nodes or their paths. It is however very
- // unlikely that any node will be exactly at the constrained line, so for a constrained snap
- // to objects we will only consider the object's paths. Beside, the nodes will be at these paths,
- // so we will more or less snap to them anyhow.
+ // TODO: Argh, UGLY! Get rid of this here, move this logic to the snap manager
+ bool snap_nodes = (_snapmanager->snapprefs.getSnapModeNode() && (
+ _snapmanager->snapprefs.getSnapToItemNode() ||
+ _snapmanager->snapprefs.getSnapSmoothNodes() ||
+ _snapmanager->snapprefs.getSnapLineMidpoints() ||
+ _snapmanager->snapprefs.getSnapObjectMidpoints()
+ )) || (_snapmanager->snapprefs.getSnapModeBBox() && (
+ _snapmanager->snapprefs.getSnapToBBoxNode() ||
+ _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() ||
+ _snapmanager->snapprefs.getSnapBBoxMidpoints()
+ )) || (_snapmanager->snapprefs.getSnapModeBBoxOrNodes() && (
+ _snapmanager->snapprefs.getIncludeItemCenter() ||
+ _snapmanager->snapprefs.getSnapToPageBorder()
+ ));
+
+ if (snap_nodes) {
+ _snapNodes(sc, p, unselected_nodes, c);
+ }
if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) {
_snapPathsConstrained(sc, p, c);
diff --git a/src/object-snapper.h b/src/object-snapper.h
index 99c8a077ea0bac95b90cf93f3df5aa0ffdb66a33..4933d84598ed72ec1acce5e3ca984c282b5eed59 100644 (file)
--- a/src/object-snapper.h
+++ b/src/object-snapper.h
Inkscape::SnapCandidatePoint const &p,
Geom::OptRect const &bbox_to_snap,
SnapConstraint const &c,
- std::vector<SPItem const *> const *it) const;
+ std::vector<SPItem const *> const *it,
+ std::vector<SnapCandidatePoint> *unselected_nodes) const;
private:
//store some lists of candidates, points and paths, so we don't have to rebuild them for each point we want to snap
void _snapNodes(SnappedConstraints &sc,
Inkscape::SnapCandidatePoint const &p,
- std::vector<SnapCandidatePoint> *unselected_nodes) const; // in desktop coordinates
+ std::vector<SnapCandidatePoint> *unselected_nodes,
+ SnapConstraint const &c = SnapConstraint()) const; // in desktop coordinates
void _snapTranslatingGuide(SnappedConstraints &sc,
Geom::Point const &p,
diff --git a/src/snap.cpp b/src/snap.cpp
index bcacb81e2328416447589344e395ee48408b52d5..7ba85a9aa95855b1f9b784e0171a726771b09dfd 100644 (file)
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -374,7 +374,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapCandidatePoint
SnappedConstraints sc;
SnapperList const snappers = getSnappers();
for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) {
- (*i)->constrainedSnap(sc, p, bbox_to_snap, constraint, &_items_to_ignore);
+ (*i)->constrainedSnap(sc, p, bbox_to_snap, constraint, &_items_to_ignore, _unselected_nodes);
}
Inkscape::SnappedPoint result = findBestSnap(p, sc, true);
@@ -422,7 +422,7 @@ Inkscape::SnappedPoint SnapManager::multipleConstrainedSnaps(Inkscape::SnapCandi
// Try to snap to the constraint
if (!snapping_is_futile) {
for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) {
- (*i)->constrainedSnap(sc, p, bbox_to_snap, *c, &_items_to_ignore);
+ (*i)->constrainedSnap(sc, p, bbox_to_snap, *c, &_items_to_ignore,_unselected_nodes);
}
}
}
@@ -526,14 +526,14 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline)
SnappedConstraints sc;
Inkscape::Snapper::SnapConstraint cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line));
if (object.ThisSnapperMightSnap()) {
- object.constrainedSnap(sc, candidate, Geom::OptRect(), cl, NULL);
+ object.constrainedSnap(sc, candidate, Geom::OptRect(), cl, NULL, 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, candidate, Geom::OptRect(), cl, NULL);
+ (*i)->constrainedSnap(sc, candidate, Geom::OptRect(), cl, NULL, NULL);
}
Inkscape::SnappedPoint const s = findBestSnap(candidate, sc, false);
diff --git a/src/snapper.h b/src/snapper.h
index d8214db8016691d9205e7937b484a47d98e97030..91784d3aefa539adf5751e1b58795a3b0f7e6dae 100644 (file)
--- a/src/snapper.h
+++ b/src/snapper.h
class SnapConstraint
{
private:
- enum SnapConstraintType {LINE, DIRECTION, CIRCLE};
+ enum SnapConstraintType {LINE, DIRECTION, CIRCLE, UNDEFINED};
public:
// Constructs a direction constraint, e.g. horizontal or vertical but without a specified point
SnapConstraint(Geom::Line const &l) : _point(l.origin()), _direction(l.versor()), _type(LINE) {}
// Constructs a circular constraint
SnapConstraint(Geom::Point const &p, Geom::Point const &d, Geom::Coord const &r) : _point(p), _direction(d), _radius(r), _type(CIRCLE) {}
+ // Undefined, or empty constraint
+ SnapConstraint() : _type(UNDEFINED) {}
- bool hasPoint() const {return _type != DIRECTION;}
+ bool hasPoint() const {return _type != DIRECTION && _type != UNDEFINED;}
Geom::Point getPoint() const {
- g_assert(_type != DIRECTION);
+ g_assert(_type != DIRECTION && _type != UNDEFINED);
return _point;
}
bool isCircular() const { return _type == CIRCLE; }
bool isLinear() const { return _type == LINE; }
bool isDirection() const { return _type == DIRECTION; }
+ bool isUndefined() const { return _type == UNDEFINED; }
Geom::Point projection(Geom::Point const &p) const { // returns the projection of p on this constraint
if (_type == CIRCLE) {
// point to be projected is exactly at the center of the circle, so any point on the circle is a projection
return _point + Geom::Point(_radius, 0);
}
- } else {
+ } else if (_type != UNDEFINED){
// project on to a linear constraint
Geom::Point const p1_on_cl = (_type == LINE) ? _point : p;
Geom::Point const p2_on_cl = p1_on_cl + _direction;
return Geom::projection(p, Geom::Line(p1_on_cl, p2_on_cl));
+ } else {
+ g_warning("Bug: trying to find the projection onto an undefined constraint");
+ return Geom::Point();
}
}
Inkscape::SnapCandidatePoint const &/*p*/,
Geom::OptRect const &/*bbox_to_snap*/,
SnapConstraint const &/*c*/,
- std::vector<SPItem const *> const */*it*/) const {};
+ std::vector<SPItem const *> const */*it*/,
+ std::vector<SnapCandidatePoint> */*unselected_nodes*/) const {};
protected:
SnapManager *_snapmanager;