summaryrefslogtreecommitdiffstats
path: root/src/object-snapper.cpp
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2010-07-13 20:16:51 +0000
committerTed Gould <ted@gould.cx>2010-07-13 20:16:51 +0000
commitef2d72d29fce61231bdd7888ab8330503158e9d6 (patch)
tree4685bfddef010181fdd87fc182016b994f2b69d9 /src/object-snapper.cpp
parentPulling in a more recent trunk (diff)
parentTranslations. Romanian nsh file update. (diff)
downloadinkscape-ef2d72d29fce61231bdd7888ab8330503158e9d6.tar.gz
inkscape-ef2d72d29fce61231bdd7888ab8330503158e9d6.zip
Upgrading to trunk
(bzr r8254.1.57)
Diffstat (limited to 'src/object-snapper.cpp')
-rw-r--r--src/object-snapper.cpp83
1 files changed, 56 insertions, 27 deletions
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 536affb82..f96335c4a 100644
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
@@ -16,6 +16,7 @@
#include <2geom/point.h>
#include <2geom/rect.h>
#include <2geom/line.h>
+#include <2geom/circle.h>
#include "document.h"
#include "sp-namedview.h"
#include "sp-image.h"
@@ -91,6 +92,12 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent,
return;
}
+ if (_snapmanager->getDesktop() == NULL) {
+ g_warning("desktop == NULL, so we cannot snap; please inform the developpers of this bug");
+ // Apparently the etup() method from the SnapManager class hasn't been called before trying to snap.
+ }
+
+
if (first_point) {
_candidates->clear();
}
@@ -99,7 +106,6 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent,
bbox_to_snap_incl.expandBy(getSnapperTolerance()); // see?
for (SPObject* o = sp_object_first_child(parent); o != NULL; o = SP_OBJECT_NEXT(o)) {
- g_assert(_snapmanager->getDesktop() != NULL);
if (SP_IS_ITEM(o) && !(_snapmanager->getDesktop()->itemIsHidden(SP_ITEM(o)) && !clip_or_mask)) {
// Snapping to items in a locked layer is allowed
// Don't snap to hidden objects, unless they're a clipped path or a mask
@@ -441,6 +447,9 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc,
}
}
+ int num_path = 0;
+ int num_segm = 0;
+
for (std::vector<Inkscape::SnapCandidatePath >::const_iterator it_p = _paths_to_snap_to->begin(); it_p != _paths_to_snap_to->end(); it_p++) {
bool const being_edited = node_tool_active && (*it_p).currently_being_edited;
//if true then this pathvector it_pv is currently being edited in the node tool
@@ -482,11 +491,13 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc,
if (!being_edited || (c1 && c2)) {
Geom::Coord const dist = Geom::distance(sp_doc, p_doc);
if (dist < getSnapperTolerance()) {
- sc.curves.push_back(Inkscape::SnappedCurve(sp_dt, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, curve, p.getSourceType(), p.getSourceNum(), it_p->target_type, it_p->target_bbox));
+ sc.curves.push_back(Inkscape::SnappedCurve(sp_dt, num_path, num_segm, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, curve, p.getSourceType(), p.getSourceNum(), it_p->target_type, it_p->target_bbox));
}
}
}
+ num_segm++;
} // End of: for (Geom::PathVector::iterator ....)
+ num_path++;
}
}
@@ -512,7 +523,7 @@ bool Inkscape::ObjectSnapper::isUnselectedNode(Geom::Point const &point, std::ve
void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc,
Inkscape::SnapCandidatePoint const &p,
- ConstraintLine const &c) const
+ SnapConstraint const &c) const
{
_collectPaths(p, p.getSourceNum() == 0);
@@ -527,36 +538,54 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc,
direction_vector = Geom::unit_vector(direction_vector);
}
- // The intersection point of the constraint line with any path,
- // must lie within two points on the constraintline: p_min_on_cl and p_max_on_cl
- // The distance between those points is twice the snapping tolerance
+ // The intersection point of the constraint line with any path, must lie within two points on the
+ // SnapConstraint: p_min_on_cl and p_max_on_cl. The distance between those points is twice the snapping tolerance
Geom::Point const p_proj_on_cl = p.getPoint(); // projection has already been taken care of in constrainedSnap in the snapmanager;
Geom::Point const p_min_on_cl = _snapmanager->getDesktop()->dt2doc(p_proj_on_cl - getSnapperTolerance() * direction_vector);
Geom::Point const p_max_on_cl = _snapmanager->getDesktop()->dt2doc(p_proj_on_cl + getSnapperTolerance() * direction_vector);
+ Geom::Coord tolerance = getSnapperTolerance();
+
+ // PS: Because the paths we're about to snap to are all expressed relative to document coordinate system, we will have
+ // to convert the snapper coordinates from the desktop coordinates to document coordinates
- Geom::Path cl;
- std::vector<Geom::Path> clv;
- cl.start(p_min_on_cl);
- cl.appendNew<Geom::LineSegment>(p_max_on_cl);
- clv.push_back(cl);
+ std::vector<Geom::Path> constraint_path;
+ if (c.isCircular()) {
+ Geom::Circle constraint_circle(_snapmanager->getDesktop()->dt2doc(c.getPoint()), c.getRadius());
+ constraint_circle.getPath(constraint_path);
+ } else {
+ Geom::Path constraint_line;
+ constraint_line.start(p_min_on_cl);
+ constraint_line.appendNew<Geom::LineSegment>(p_max_on_cl);
+ constraint_path.push_back(constraint_line);
+ }
for (std::vector<Inkscape::SnapCandidatePath >::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) {
if (k->path_vector) {
- Geom::CrossingSet cs = Geom::crossings(clv, *(k->path_vector));
- if (cs.size() > 0) {
- // We need only the first element of cs, because cl is only a single straight linesegment
- // This first element contains a vector filled with crossings of cl with k->first
- for (std::vector<Geom::Crossing>::const_iterator m = cs[0].begin(); m != cs[0].end(); m++) {
- if ((*m).ta >= 0 && (*m).ta <= 1 ) {
- // Reconstruct the point of intersection
- Geom::Point p_inters = p_min_on_cl + ((*m).ta) * (p_max_on_cl - p_min_on_cl);
- // When it's within snapping range, then return it
- // (within snapping range == between p_min_on_cl and p_max_on_cl == 0 < ta < 1)
- Geom::Coord dist = Geom::L2(_snapmanager->getDesktop()->dt2doc(p_proj_on_cl) - p_inters);
- SnappedPoint s(_snapmanager->getDesktop()->doc2dt(p_inters), p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, k->target_bbox);
+ Geom::CrossingSet cs = Geom::crossings(constraint_path, *(k->path_vector));
+ unsigned int index = 0;
+ for (Geom::CrossingSet::const_iterator i = cs.begin(); i != cs.end(); i++) {
+ if (index >= constraint_path.size()) {
+ break;
+ }
+ for (Geom::Crossings::const_iterator m = (*i).begin(); m != (*i).end(); m++) {
+ //std::cout << "ta = " << (*m).ta << " | tb = " << (*m).tb << std::endl;
+ // Reconstruct the point of intersection
+ Geom::Point p_inters = constraint_path[index].pointAt((*m).ta);
+ // .. and convert it to desktop coordinates
+ p_inters = _snapmanager->getDesktop()->doc2dt(p_inters);
+ Geom::Coord dist = Geom::L2(p_proj_on_cl - p_inters);
+ SnappedPoint s = SnappedPoint(p_inters, p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, k->target_bbox);;
+ if (dist <= tolerance) { // If the intersection is within snapping range, then we might snap to it
+ if (c.isCircular()) {
+ Geom::Point v_orig = c.getDirection(); // vector from the origin to the original (untransformed) point
+ Geom::Point v_inters = p_inters - c.getPoint();
+ Geom::Coord radians = atan2(Geom::dot(Geom::rot90(v_orig), v_inters), Geom::dot(v_orig, v_inters));
+ s.setTransformation(Geom::Point(radians, radians));
+ }
sc.points.push_back(s);
}
}
+ index++;
}
}
}
@@ -612,7 +641,7 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc,
void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc,
Inkscape::SnapCandidatePoint const &p,
Geom::OptRect const &bbox_to_snap,
- ConstraintLine const &c,
+ SnapConstraint const &c,
std::vector<SPItem const *> const *it) const
{
if (_snap_enabled == false || _snapmanager->snapprefs.getSnapFrom(p.getSourceType()) == false) {
@@ -667,7 +696,7 @@ void Inkscape::ObjectSnapper::guideFreeSnap(SnappedConstraints &sc,
void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc,
Geom::Point const &p,
Geom::Point const &guide_normal,
- ConstraintLine const &/*c*/) const
+ SnapConstraint const &/*c*/) const
{
/* Get a list of all the SPItems that we will try to snap to */
std::vector<SPItem*> cand;
@@ -693,7 +722,7 @@ void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc,
bool Inkscape::ObjectSnapper::ThisSnapperMightSnap() const
{
bool snap_to_something = _snapmanager->snapprefs.getSnapToItemPath()
- || _snapmanager->snapprefs.getSnapToItemNode()
+ || _snapmanager->snapprefs.getSnapToItemNode() || _snapmanager->snapprefs.getSnapSmoothNodes()
|| _snapmanager->snapprefs.getSnapToBBoxPath()
|| _snapmanager->snapprefs.getSnapToBBoxNode()
|| _snapmanager->snapprefs.getSnapToPageBorder()
@@ -706,7 +735,7 @@ bool Inkscape::ObjectSnapper::ThisSnapperMightSnap() const
bool Inkscape::ObjectSnapper::GuidesMightSnap() const // almost the same as ThisSnapperMightSnap above, but only looking at points (and not paths)
{
- bool snap_to_something = _snapmanager->snapprefs.getSnapToItemNode()
+ bool snap_to_something = _snapmanager->snapprefs.getSnapToItemNode() || _snapmanager->snapprefs.getSnapSmoothNodes()
|| _snapmanager->snapprefs.getSnapToPageBorder()
|| (_snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxNode())
|| (_snapmanager->snapprefs.getSnapModeBBox() && (_snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints()))