summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: adcda3e)
raw | patch | inline | side by side (parent: adcda3e)
author | dvlierop2 <dvlierop2@users.sourceforge.net> | |
Thu, 27 Dec 2007 19:45:52 +0000 (19:45 +0000) | ||
committer | dvlierop2 <dvlierop2@users.sourceforge.net> | |
Thu, 27 Dec 2007 19:45:52 +0000 (19:45 +0000) |
src/libnr/nr-point-fns.cpp | patch | blob | history | |
src/object-snapper.cpp | patch | blob | history | |
src/object-snapper.h | patch | blob | history | |
src/snap.cpp | patch | blob | history |
index 4428ed9b36f24b9fc1ee3d72fa960a775c5d3550..a7b128bdbeaf597201dbcb7617984712600a8987 100644 (file)
@@ -111,6 +111,8 @@ project_on_linesegment(NR::Point const p, NR::Point const p1, NR::Point const p2
// calculate u according to "Minimum Distance between a Point and a Line"
// see http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
+ // Warning: projected points will not necessarily be in between the endpoints of the linesegments!
+
if (p1 == p2) { // to avoid div. by zero below
return p;
}
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 71c790c17f44b9281a538e885f5576a02168856f..c03884ffd05880a14a89e6981262c1232aea2ae3 100644 (file)
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
double d = getDistance();
bool withinX = ((*i)[NR::X] >= b_min[NR::X] - d) && ((*i)[NR::X] <= b_max[NR::X] + d);
bool withinY = ((*i)[NR::Y] >= b_min[NR::Y] - d) && ((*i)[NR::Y] <= b_max[NR::Y] + d);
- if (snap_dim == SNAP_X && withinX || snap_dim == SNAP_Y && withinY || snap_dim == SNAP_XY && withinX && withinY) {
+ bool c1 = snap_dim == GUIDE_TRANSL_SNAP_X && withinX;
+ bool c2 = snap_dim == GUIDE_TRANSL_SNAP_Y && withinY;
+ bool c3 = snap_dim == TRANSL_SNAP_XY && withinX && withinY;
+ // For an angled guide at e.g 45 deg., the bbox is very large and might even span
+ // the full desktop. Therefore we will simply return _any_ candidate, without looking at
+ // the bbox and the snapping distance.
+ bool c4 = snap_dim == ANGLED_GUIDE_TRANSL_SNAP || snap_dim == ANGLED_GUIDE_ROT_SNAP;
+ if ( c1 || c2 || c3 || c4) {
//We've found a point that is within snapping range
//of this object, so record it as a candidate
_candidates->push_back(SP_ITEM(o));
@@ -173,36 +180,19 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::Snapper::PointType const &
void Inkscape::ObjectSnapper::_snapNodes(SnappedConstraints &sc,
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
- bool const &first_point,
- DimensionToSnap const snap_dim) const
+ bool const &first_point) const
{
+ // Iterate through all nodes, find out which one is the closest to p, and snap to it!
+
_collectNodes(t, first_point);
- //Do the snapping, using all the nodes and corners collected before
- NR::Point snapped_point;
SnappedPoint s;
bool success = false;
for (std::vector<NR::Point>::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) {
- /* Try to snap to this node of the path */
- NR::Coord dist = NR_HUGE;
- switch (snap_dim) {
- case SNAP_X:
- dist = fabs((*k)[NR::X] - p[NR::X]);
- snapped_point = NR::Point((*k)[NR::X], p[NR::Y]);
- break;
- case SNAP_Y:
- dist = fabs((*k)[NR::Y] - p[NR::Y]);
- snapped_point = NR::Point(p[NR::X], (*k)[NR::Y]);
- break;
- case SNAP_XY:
- dist = NR::L2(*k - p);
- snapped_point = *k;
- break;
- }
-
+ NR::Coord dist = NR::L2(*k - p);
if (dist < getDistance() && dist < s.getDistance()) {
- s = SnappedPoint(snapped_point, dist);
+ s = SnappedPoint(*k, dist);
success = true;
}
}
}
}
+void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &sc,
+ Inkscape::Snapper::PointType const &t,
+ NR::Point const &p,
+ NR::Point const &guide_normal) const
+{
+ // Iterate through all nodes, find out which one is the closest to this guide, and snap to it!
+ _collectNodes(t, true);
+
+ SnappedPoint s;
+ bool success = false;
+
+ for (std::vector<NR::Point>::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) {
+ // Project each node (*k) on the guide line (running through point p)
+ NR::Point p_proj = project_on_linesegment(*k, p, p + NR::rot90(guide_normal));
+ NR::Coord dist = NR::L2(*k - p_proj);
+ if (dist < getDistance() && dist < s.getDistance()) {
+ s = SnappedPoint(*k, dist);
+ success = true;
+ }
+ }
+
+ if (success) {
+ sc.points.push_back(s);
+ }
+}
void Inkscape::ObjectSnapper::_collectPaths(Inkscape::Snapper::PointType const &t,
bool const &first_point) const
/* Get a list of all the SPItems that we will try to snap to */
if (first_point) {
- _findCandidates(sp_document_root(_named_view->document), it, first_point, points_to_snap, SNAP_XY);
+ _findCandidates(sp_document_root(_named_view->document), it, first_point, points_to_snap, TRANSL_SNAP_XY);
}
if (_snap_to_itemnode || _snap_to_bboxnode) {
- _snapNodes(sc, t, p, first_point, SNAP_XY);
+ _snapNodes(sc, t, p, first_point);
}
if (_snap_to_itempath || _snap_to_bboxpath) {
_snapPaths(sc, t, p, first_point);
/* Get a list of all the SPItems that we will try to snap to */
if (first_point) {
- _findCandidates(sp_document_root(_named_view->document), it, first_point, points_to_snap, SNAP_XY);
+ _findCandidates(sp_document_root(_named_view->document), it, first_point, points_to_snap, TRANSL_SNAP_XY);
}
// A constrained snap, is a snap in only one degree of freedom (specified by the constraint line).
void Inkscape::ObjectSnapper::guideSnap(SnappedConstraints &sc,
- NR::Point const &p,
- DimensionToSnap const snap_dim) const
+ NR::Point const &p,
+ NR::Point const &guide_normal) const
{
if ( NULL == _named_view ) {
return;
std::vector<NR::Point> points_to_snap;
points_to_snap.push_back(p);
+ // This method is used to snap a guide to nodes, while dragging the guide around
+ DimensionToSnap snap_dim;
+ if (guide_normal == component_vectors[NR::Y]) {
+ snap_dim = GUIDE_TRANSL_SNAP_Y;
+ } else if (guide_normal == component_vectors[NR::X]) {
+ snap_dim = GUIDE_TRANSL_SNAP_X;
+ } else {
+ snap_dim = ANGLED_GUIDE_TRANSL_SNAP;
+ }
+ // We don't support ANGLED_GUIDE_ROT_SNAP yet.
+
+ // It would be cool to allow the user to rotate a guide by dragging it, instead of
+ // only translating it. (For example when CTRL is pressed). We will need an UI part
+ // for that first; and some important usability choices need to be made:
+ // E.g. which point should be used for pivoting? A previously snapped point,
+ // or a transformation center (which can be moved after clicking for the
+ // second time on an object; but should this point then be constrained to the
+ // line, or can it be located anywhere?)
+
_findCandidates(sp_document_root(_named_view->document), it, true, points_to_snap, snap_dim);
- _snapNodes(sc, Inkscape::Snapper::SNAPPOINT_GUIDE, p, true, snap_dim);
+ _snapTranslatingGuideToNodes(sc, Inkscape::Snapper::SNAPPOINT_GUIDE, p, guide_normal);
+
+ // _snapRotatingGuideToNodes has not been implemented yet.
}
/**
diff --git a/src/object-snapper.h b/src/object-snapper.h
index c16b42580fdf692d2d3c3776e1aedcb8a1fda350..a2d199c875d63d9528dd3b9596d96a03a244f59b 100644 (file)
--- a/src/object-snapper.h
+++ b/src/object-snapper.h
ObjectSnapper(SPNamedView const *nv, NR::Coord const d);
~ObjectSnapper();
- enum DimensionToSnap {SNAP_X, SNAP_Y, SNAP_XY};
+ enum DimensionToSnap {
+ GUIDE_TRANSL_SNAP_X, // For snapping a vertical guide (normal in the X-direction) to objects,
+ GUIDE_TRANSL_SNAP_Y, // For snapping a horizontal guide (normal in the Y-direction) to objects
+ ANGLED_GUIDE_TRANSL_SNAP, // For snapping an angled guide, while translating it accross the desktop
+ ANGLED_GUIDE_ROT_SNAP, // For snapping an angled guide, while rotating it around some pivot point
+ TRANSL_SNAP_XY}; // All other cases; for snapping to objects, other than guides
void setSnapToItemNode(bool s) {
_snap_to_itemnode = s;
void guideSnap(SnappedConstraints &sc,
NR::Point const &p,
- DimensionToSnap const snap_dim) const;
+ NR::Point const &guide_normal) const;
bool ThisSnapperMightSnap() const;
void _snapNodes(SnappedConstraints &sc,
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
- bool const &first_point,
- DimensionToSnap const snap_dim) const;
-
+ bool const &first_point) const;
+
+ void _snapTranslatingGuideToNodes(SnappedConstraints &sc,
+ Inkscape::Snapper::PointType const &t,
+ NR::Point const &p,
+ NR::Point const &guide_normal) const;
+
void _collectNodes(Inkscape::Snapper::PointType const &t,
bool const &first_point) const;
diff --git a/src/snap.cpp b/src/snap.cpp
index b4e284271d83e47608831ff7636711818dc0835b..c6fa3fc25e50284553870052e3067e71f5e09cff 100644 (file)
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -285,29 +285,16 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::Snapper::PointType
}
Inkscape::SnappedPoint SnapManager::guideSnap(NR::Point const &p,
- NR::Point const &guide_normal) const
+ NR::Point const &guide_normal) const
{
- if (!object.ThisSnapperMightSnap()) {
- return Inkscape::SnappedPoint(p, NR_HUGE);
- }
-
// This method is used to snap a guide to nodes, while dragging the guide around
- Inkscape::ObjectSnapper::DimensionToSnap snap_dim;
- if (guide_normal == component_vectors[NR::Y]) {
- snap_dim = Inkscape::ObjectSnapper::SNAP_Y;
- } else if (guide_normal == component_vectors[NR::X]) {
- snap_dim = Inkscape::ObjectSnapper::SNAP_X;
- } else {
- g_warning("WARNING: snapping of angled guides is not supported yet!");
- // this is because _snapnodes, called in object.guideSnap, cannot only handle
- // vertical or horizontal lines for now....
- // Rotating an agled guide will require some additional code, as it would be great to
- // have it rotate around a snapped point
- snap_dim = Inkscape::ObjectSnapper::SNAP_XY;
+
+ if (!(object.ThisSnapperMightSnap() && _snap_enabled_globally)) {
+ return Inkscape::SnappedPoint(p, NR_HUGE);
}
SnappedConstraints sc;
- object.guideSnap(sc, p, snap_dim);
+ object.guideSnap(sc, p, guide_normal);
return findBestSnap(p, sc, false);
}