From cf6282e355b018fc3fb50920a93ff9b20e8e014a Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 19 Jul 2010 09:14:43 +0200 Subject: [PATCH] Fix snapping to midpoints of closing segments --- src/object-snapper.cpp | 12 ++++-- src/sp-shape.cpp | 86 ++++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 57d5b0fc5..7d593dfc4 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -13,6 +13,7 @@ #include "svg/svg.h" #include <2geom/path-intersection.h> +#include <2geom/pathvector.h> #include <2geom/point.h> #include <2geom/rect.h> #include <2geom/line.h> @@ -386,9 +387,14 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapCandidatePoint const & if (!very_lenghty_prose && !very_complex_path) { SPCurve *curve = curve_for_item(root_item); if (curve) { - // We will get our own copy of the path, which must be freed at some point - Geom::PathVector *borderpathv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), (*i).additional_affine); - _paths_to_snap_to->push_back(Inkscape::SnapCandidatePath(borderpathv, SNAPTARGET_PATH, Geom::OptRect())); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it. + // We will get our own copy of the pathvector, which must be freed at some point + + // Geom::PathVector *pv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), (*i).additional_affine); + + Geom::PathVector *pv = new Geom::PathVector(curve->get_pathvector()); + (*pv) *= sp_item_i2d_affine(root_item) * (*i).additional_affine * _snapmanager->getDesktop()->doc2dt(); // (_edit_transform * _i2d_transform); + + _paths_to_snap_to->push_back(Inkscape::SnapCandidatePath(pv, SNAPTARGET_PATH, Geom::OptRect())); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it. curve->unref(); } } diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 3064341b6..0038908bf 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -1208,51 +1208,57 @@ static void sp_shape_snappoints(SPItem const *item, std::vectorgetSnapToItemNode()) { - p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + // Add the first point of the path + p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve - while (curve_it2 != path_it->end_closed()) + while (curve_it1 != path_it->end_default()) { - /* Test whether to add the node between curve_it1 and curve_it2. - * Loop to end_closed (so always including closing segment); the last node to be added - * is the node between the closing segment and the segment before that, regardless - * of the path being closed or not. If the path is closed, the final point was already added by - * adding the initial point. */ - - Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); - - bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE); - bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); - - if (c1 || c2) { - Inkscape::SnapSourceType sst; - Inkscape::SnapTargetType stt; - switch (nodetype) { - case Geom::NODE_CUSP: - sst = Inkscape::SNAPSOURCE_NODE_CUSP; - stt = Inkscape::SNAPTARGET_NODE_CUSP; - break; - case Geom::NODE_SMOOTH: - case Geom::NODE_SYMM: - sst = Inkscape::SNAPSOURCE_NODE_SMOOTH; - stt = Inkscape::SNAPTARGET_NODE_SMOOTH; - break; - default: - sst = Inkscape::SNAPSOURCE_UNDEFINED; - stt = Inkscape::SNAPTARGET_UNDEFINED; - break; - } - p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt)); - } - - // Consider midpoints of line segments for snapping - if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping) - if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { - p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); - } - } + // For each path: consider midpoints of line segments for snapping + if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforces strict snapping) + if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { + p.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + } + } + + if (curve_it2 == path_it->end_default()) { // Test will only pass for the last iteration of the while loop + if (snapprefs->getSnapToItemNode() && !path_it->closed()) { + // Add the last point of the path, but only for open paths + // (for closed paths the first and last point will coincide) + p.push_back(Inkscape::SnapCandidatePoint((*curve_it1).finalPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); + } + } else { + /* Test whether to add the node between curve_it1 and curve_it2. + * Loop to end_default (so only iterating through the stroked part); */ + + Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2); + + bool c1 = snapprefs->getSnapToItemNode() && (nodetype == Geom::NODE_CUSP || nodetype == Geom::NODE_NONE); + bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); + + if (c1 || c2) { + Inkscape::SnapSourceType sst; + Inkscape::SnapTargetType stt; + switch (nodetype) { + case Geom::NODE_CUSP: + sst = Inkscape::SNAPSOURCE_NODE_CUSP; + stt = Inkscape::SNAPTARGET_NODE_CUSP; + break; + case Geom::NODE_SMOOTH: + case Geom::NODE_SYMM: + sst = Inkscape::SNAPSOURCE_NODE_SMOOTH; + stt = Inkscape::SNAPTARGET_NODE_SMOOTH; + break; + default: + sst = Inkscape::SNAPSOURCE_UNDEFINED; + stt = Inkscape::SNAPTARGET_UNDEFINED; + break; + } + p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, sst, stt)); + } + } ++curve_it1; ++curve_it2; -- 2.30.2