diff options
| author | Diederik van Lierop <mail@diedenrezi.nl> | 2008-04-30 07:32:12 +0000 |
|---|---|---|
| committer | dvlierop2 <dvlierop2@users.sourceforge.net> | 2008-04-30 07:32:12 +0000 |
| commit | 8e980bd257a274f7f32aca2e05f2a694675cf4ef (patch) | |
| tree | 4b2b83970d640c900a3eadb0266e29a92f088dde /src/object-snapper.cpp | |
| parent | merge redundant language-agnostics options into CPPFLAGS, split off linker flags (diff) | |
| download | inkscape-8e980bd257a274f7f32aca2e05f2a694675cf4ef.tar.gz inkscape-8e980bd257a274f7f32aca2e05f2a694675cf4ef.zip | |
- Major refactoring of snapping related code...
- Enabling snap indicator for all remaining tools
(bzr r5556)
Diffstat (limited to 'src/object-snapper.cpp')
| -rw-r--r-- | src/object-snapper.cpp | 112 |
1 files changed, 53 insertions, 59 deletions
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index a91014158..57ec1b347 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -60,21 +60,20 @@ Inkscape::ObjectSnapper::~ObjectSnapper() * \param r Pointer to the current document * \param it List of items to ignore * \param first_point If true then this point is the first one from a whole bunch of points - * \param points_to_snap The whole bunch of points, all from the same selection and having the same transformation + * \param bbox_to_snap Bounding box hulling the whole bunch of points, all from the same selection and having the same transformation * \param DimensionToSnap Snap in X, Y, or both directions. */ void Inkscape::ObjectSnapper::_findCandidates(SPObject* r, - std::vector<SPItem const *> const &it, + std::vector<SPItem const *> const *it, bool const &first_point, - std::vector<NR::Point> &points_to_snap, + NR::Rect const &bbox_to_snap, DimensionToSnap const snap_dim) const { bool const c1 = (snap_dim == TRANSL_SNAP_XY) && ThisSnapperMightSnap(); bool const c2 = (snap_dim != TRANSL_SNAP_XY) && GuidesMightSnap(); - bool const c3 = points_to_snap.size() == 0; - if (!(c1 || c2) || c3) { + if (!(c1 || c2)) { return; } @@ -84,49 +83,32 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* r, _candidates->clear(); } - NR::Maybe<NR::Rect> bbox = NR::Rect(); // a default NR::Rect is infinitely large - NR::Coord t = getSnapperTolerance(); + NR::Maybe<NR::Rect> bbox_of_item = NR::Rect(); // a default NR::Rect is infinitely large + NR::Rect bbox_to_snap_incl = bbox_to_snap; // _incl means: will include the snapper tolerance + bbox_to_snap_incl.growBy(getSnapperTolerance()); // see? - // When dragging a guide... - NR::Point p_guide = points_to_snap[0]; - if (!getSnapperAlwaysSnap()) { - bbox = NR::Rect(p_guide, p_guide); // bbox is now just a single point: p_guide - bbox->growBy(t); // bbox width and height now measure 2x snapper tolerance - // for angled guidelines the bbox is now larger than really needed - // (up to sqrt(2) for 45 deg. guidelines) but we'll leave it like that - } // else: use an infinitely large bbox to find candidates - for (SPObject* o = sp_object_first_child(r); o != NULL; o = SP_OBJECT_NEXT(o)) { if (SP_IS_ITEM(o) && !SP_ITEM(o)->isLocked() && !desktop->itemIsHidden(SP_ITEM(o))) { /* See if this item is on the ignore list */ - std::vector<SPItem const *>::const_iterator i = it.begin(); - while (i != it.end() && *i != o) { - i++; + std::vector<SPItem const *>::const_iterator i; + if (it != NULL) { + i = it->begin(); + while (i != it->end() && *i != o) { + i++; + } } - if (i == it.end()) { + if (it == NULL || i == it->end()) { /* See if the item is within range */ if (SP_IS_GROUP(o)) { - _findCandidates(o, it, false, points_to_snap, snap_dim); + _findCandidates(o, it, false, bbox_to_snap, snap_dim); } else { - // Now let's see if any of the snapping points is within snapping range of this object - if (snap_dim == TRANSL_SNAP_XY) { - bbox = sp_item_bbox_desktop(SP_ITEM(o)); - } // else: we're snapping a guide to an object and we will use the bbox as defined above - - if (bbox) { - for (std::vector<NR::Point>::const_iterator i = points_to_snap.begin(); i != points_to_snap.end(); i++) { - NR::Point b_min = bbox->min(); - NR::Point b_max = bbox->max(); - bool withinX = ((*i)[NR::X] >= b_min[NR::X] - t) && ((*i)[NR::X] <= b_max[NR::X] + t); - bool withinY = ((*i)[NR::Y] >= b_min[NR::Y] - t) && ((*i)[NR::Y] <= b_max[NR::Y] + t); - if (withinX && withinY) { - //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)); - break; - } + bbox_of_item = sp_item_bbox_desktop(SP_ITEM(o)); + if (bbox_of_item) { + if (bbox_to_snap_incl.intersects(*bbox_of_item)) { + //This item is within snapping range, so record it as a candidate + _candidates->push_back(SP_ITEM(o)); } } } @@ -396,7 +378,8 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc, bool const being_edited = (node_tool_active && (*k) == _paths_to_snap_to->back()); //if true then this path k is currently being edited in the node tool - for (unsigned i = 1 ; i < (*k)->pts.size() ; i++) { + for (unsigned i = 1 ; i < (*k)->pts.size() ; i++) { + //pts describes a polyline approximation, which might consist of 1000s of points! NR::Point start_point; NR::Point end_point; NR::Maybe<Path::cut_position> o = NR::Nothing(); @@ -435,6 +418,13 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc, if (o && o->t >= 0 && o->t <= 1) { /* Convert the nearest point back to desktop coordinates */ NR::Point const o_it = get_point_on_Path(*k, o->piece, o->t); + + /* IF YOU'RE BUG HUNTING: IT LOOKS LIKE get_point_on_Path SOMETIMES + * RETURNS THE WRONG POINT (WITH AN OFFSET, BUT STILL ON THE PATH. + * THIS BUG WILL NO LONGER BE ENCOUNTERED ONCE WE'VE SWITCHED TO + * 2GEOM FOR THE OBJECT SNAPPER + */ + NR::Point const o_dt = desktop->doc2dt(o_it); NR::Coord const dist = NR::L2(o_dt - p); @@ -549,21 +539,22 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, } -void Inkscape::ObjectSnapper::_doFreeSnap(SnappedConstraints &sc, +void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, Inkscape::Snapper::PointType const &t, NR::Point const &p, bool const &first_point, - std::vector<NR::Point> &points_to_snap, - std::vector<SPItem const *> const &it, + NR::Maybe<NR::Rect> const &bbox_to_snap, + std::vector<SPItem const *> const *it, std::vector<NR::Point> *unselected_nodes) const { - if ( NULL == _named_view ) { + if (_snap_enabled == false || getSnapFrom(t) == false || _named_view == NULL) { return; } /* 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, TRANSL_SNAP_XY); + NR::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : NR::Rect(p, p); + _findCandidates(sp_document_root(_named_view->document), it, first_point, local_bbox_to_snap, TRANSL_SNAP_XY); } if (_snap_to_itemnode || _snap_to_bboxnode) { @@ -580,31 +571,36 @@ void Inkscape::ObjectSnapper::_doFreeSnap(SnappedConstraints &sc, * of the node snapping requirements (i.e. only unselected nodes must be snapable). * That path must not be ignored however when snapping to the paths, so we add it here * manually when applicable - */ - g_assert(it.size() == 1); - g_assert(SP_IS_PATH(*it.begin())); - _snapPaths(sc, t, p, first_point, unselected_nodes, SP_PATH(*it.begin()), border_bpath); + */ + SPPath *path = NULL; + if (it != NULL) { + g_assert(SP_IS_PATH(*it->begin())); + g_assert(it->size() == 1); + path = SP_PATH(*it->begin()); + } + _snapPaths(sc, t, p, first_point, unselected_nodes, path, border_bpath); } else { _snapPaths(sc, t, p, first_point, NULL, NULL, border_bpath); } } } -void Inkscape::ObjectSnapper::_doConstrainedSnap( SnappedConstraints &sc, +void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, Inkscape::Snapper::PointType const &t, NR::Point const &p, bool const &first_point, - std::vector<NR::Point> &points_to_snap, + NR::Maybe<NR::Rect> const &bbox_to_snap, ConstraintLine const &c, - std::vector<SPItem const *> const &it) const + std::vector<SPItem const *> const *it) const { - if ( NULL == _named_view ) { + if (_snap_enabled == false || getSnapFrom(t) == false || _named_view == NULL) { return; } /* 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, TRANSL_SNAP_XY); + NR::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : NR::Rect(p, p); + _findCandidates(sp_document_root(_named_view->document), it, first_point, local_bbox_to_snap, TRANSL_SNAP_XY); } // A constrained snap, is a snap in only one degree of freedom (specified by the constraint line). @@ -634,10 +630,7 @@ void Inkscape::ObjectSnapper::guideSnap(SnappedConstraints &sc, /* Get a list of all the SPItems that we will try to snap to */ std::vector<SPItem*> cand; std::vector<SPItem const *> const it; //just an empty list - - std::vector<NR::Point> points_to_snap; - points_to_snap.push_back(p); - + DimensionToSnap snap_dim; if (guide_normal == component_vectors[NR::Y]) { snap_dim = GUIDE_TRANSL_SNAP_Y; @@ -646,6 +639,7 @@ void Inkscape::ObjectSnapper::guideSnap(SnappedConstraints &sc, } 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 @@ -655,8 +649,8 @@ void Inkscape::ObjectSnapper::guideSnap(SnappedConstraints &sc, // 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); + + _findCandidates(sp_document_root(_named_view->document), &it, true, NR::Rect(p, p), snap_dim); _snapTranslatingGuideToNodes(sc, Inkscape::Snapper::SNAPPOINT_GUIDE, p, guide_normal); // _snapRotatingGuideToNodes has not been implemented yet. |
