From 1aa821e67cb9667c99920eadec0f58532f73652c Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Thu, 24 Dec 2009 21:10:43 +0100 Subject: [PATCH] refactoring the snapping code (laying the groundwork for my next commit which reduces snap jitter) --- src/display/canvas-axonomgrid.cpp | 76 +++---- src/display/canvas-axonomgrid.h | 4 +- src/display/canvas-grid.cpp | 48 ++--- src/display/canvas-grid.h | 4 +- .../internal/pdfinput/pdf-parser.cpp | 22 +- src/gradient-drag.cpp | 4 +- src/guide-snapper.cpp | 12 +- src/guide-snapper.h | 8 +- src/libnr/nr-compose.cpp | 1 + src/line-snapper.cpp | 14 +- src/line-snapper.h | 10 +- src/object-snapper.cpp | 203 +++++++++--------- src/object-snapper.h | 86 ++++---- src/snap.cpp | 80 +++---- src/snap.h | 52 ++--- src/snapped-curve.cpp | 8 +- src/snapped-curve.h | 2 +- src/snapped-line.cpp | 70 +++--- src/snapped-line.h | 4 +- src/snapped-point.cpp | 47 ++-- src/snapped-point.h | 11 +- src/snapper.h | 28 +-- 22 files changed, 403 insertions(+), 391 deletions(-) diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index a92e7cf5b..ee05cd01c 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -359,9 +359,9 @@ CanvasAxonomGrid::readRepr() } if ( (value = repr->attribute("snapvisiblegridlinesonly")) ) { - g_assert(snapper != NULL); - snapper->setSnapVisibleOnly(strcmp(value,"false") != 0 && strcmp(value, "0") != 0); - } + g_assert(snapper != NULL); + snapper->setSnapVisibleOnly(strcmp(value,"false") != 0 && strcmp(value, "0") != 0); + } for (GSList *l = canvasitems; l != NULL; l = l->next) { sp_canvas_item_request_update ( SP_CANVAS_ITEM(l->data) ); @@ -671,9 +671,9 @@ CanvasAxonomGridSnapper::CanvasAxonomGridSnapper(CanvasAxonomGrid *grid, SnapMan */ Geom::Coord CanvasAxonomGridSnapper::getSnapperTolerance() const { - SPDesktop const *dt = _snapmanager->getDesktop(); - double const zoom = dt ? dt->current_zoom() : 1; - return _snapmanager->snapprefs.getGridTolerance() / zoom; + SPDesktop const *dt = _snapmanager->getDesktop(); + double const zoom = dt ? dt->current_zoom() : 1; + return _snapmanager->snapprefs.getGridTolerance() / zoom; } bool CanvasAxonomGridSnapper::getSnapperAlwaysSnap() const @@ -694,22 +694,22 @@ CanvasAxonomGridSnapper::_getSnapLines(Geom::Point const &p) const double spacing_v; if (getSnapVisibleOnly()) { - // Only snapping to visible grid lines - spacing_h = grid->spacing_ylines; // this is the spacing of the visible grid lines measured in screen pixels - spacing_v = grid->lyw; // vertical - // convert screen pixels to px - // FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary - SPDesktop const *dt = _snapmanager->getDesktop(); - if (dt) { - spacing_h /= dt->current_zoom(); - spacing_v /= dt->current_zoom(); - } - } else { - // Snapping to any grid line, whether it's visible or not - spacing_h = grid->lengthy /(grid->tan_angle[X] + grid->tan_angle[Z]); - spacing_v = grid->lengthy; - - } + // Only snapping to visible grid lines + spacing_h = grid->spacing_ylines; // this is the spacing of the visible grid lines measured in screen pixels + spacing_v = grid->lyw; // vertical + // convert screen pixels to px + // FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary + SPDesktop const *dt = _snapmanager->getDesktop(); + if (dt) { + spacing_h /= dt->current_zoom(); + spacing_v /= dt->current_zoom(); + } + } else { + // Snapping to any grid line, whether it's visible or not + spacing_h = grid->lengthy /(grid->tan_angle[X] + grid->tan_angle[Z]); + spacing_v = grid->lengthy; + + } // In an axonometric grid, any point will be surrounded by 6 grid lines: // - 2 vertical grid lines, one left and one right from the point @@ -746,18 +746,18 @@ CanvasAxonomGridSnapper::_getSnapLines(Geom::Point const &p) const Geom::Point p_x(0, y_proj_along_x_max); Geom::Line line_x(p_x, p_x + vers_x); Geom::Point p_z(0, y_proj_along_z_max); - Geom::Line line_z(p_z, p_z + vers_z); + Geom::Line line_z(p_z, p_z + vers_z); Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default - try - { - inters = Geom::intersection(line_x, line_z); - } - catch (Geom::InfiniteSolutions e) - { - // We're probably dealing with parallel lines; this is useless! - return s; - } + try + { + inters = Geom::intersection(line_x, line_z); + } + catch (Geom::InfiniteSolutions e) + { + // We're probably dealing with parallel lines; this is useless! + return s; + } // Determine which half of the parallelogram to use bool use_left_half = true; @@ -765,7 +765,7 @@ CanvasAxonomGridSnapper::_getSnapLines(Geom::Point const &p) const if (inters) { Geom::Point inters_pt = line_x.pointAt((*inters).ta); - use_left_half = (p[Geom::X] - grid->origin[Geom::X]) < inters_pt[Geom::X]; + use_left_half = (p[Geom::X] - grid->origin[Geom::X]) < inters_pt[Geom::X]; use_right_half = !use_left_half; } @@ -786,16 +786,16 @@ CanvasAxonomGridSnapper::_getSnapLines(Geom::Point const &p) const return s; } -void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, Geom::Point const normal_to_line, Geom::Point const point_on_line) const +void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, Inkscape::SNAPTARGET_GRID, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, source_num, Inkscape::SNAPTARGET_GRID, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); sc.grid_lines.push_back(dummy); } -void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const +void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const { - SnappedPoint dummy = SnappedPoint(snapped_point, source, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); - sc.points.push_back(dummy); + SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + sc.points.push_back(dummy); } bool CanvasAxonomGridSnapper::ThisSnapperMightSnap() const diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h index e36804d7c..4b1cd4834 100644 --- a/src/display/canvas-axonomgrid.h +++ b/src/display/canvas-axonomgrid.h @@ -78,8 +78,8 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; - void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const; + void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; CanvasAxonomGrid *grid; }; diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 5037c0375..3532c504a 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -635,9 +635,9 @@ CanvasXYGrid::readRepr() } if ( (value = repr->attribute("snapvisiblegridlinesonly")) ) { - g_assert(snapper != NULL); - snapper->setSnapVisibleOnly(strcmp(value,"false") != 0 && strcmp(value, "0") != 0); - } + g_assert(snapper != NULL); + snapper->setSnapVisibleOnly(strcmp(value,"false") != 0 && strcmp(value, "0") != 0); + } for (GSList *l = canvasitems; l != NULL; l = l->next) { sp_canvas_item_request_update ( SP_CANVAS_ITEM(l->data) ); @@ -972,9 +972,9 @@ CanvasXYGridSnapper::CanvasXYGridSnapper(CanvasXYGrid *grid, SnapManager *sm, Ge */ Geom::Coord CanvasXYGridSnapper::getSnapperTolerance() const { - SPDesktop const *dt = _snapmanager->getDesktop(); - double const zoom = dt ? dt->current_zoom() : 1; - return _snapmanager->snapprefs.getGridTolerance() / zoom; + SPDesktop const *dt = _snapmanager->getDesktop(); + double const zoom = dt ? dt->current_zoom() : 1; + return _snapmanager->snapprefs.getGridTolerance() / zoom; } bool CanvasXYGridSnapper::getSnapperAlwaysSnap() const @@ -993,20 +993,20 @@ CanvasXYGridSnapper::_getSnapLines(Geom::Point const &p) const for (unsigned int i = 0; i < 2; ++i) { - double spacing; - - if (getSnapVisibleOnly()) { - // Only snapping to visible grid lines - spacing = grid->sw[i]; // this is the spacing of the visible grid lines measured in screen pixels - // convert screen pixels to px - // FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary - SPDesktop const *dt = _snapmanager->getDesktop(); - if (dt) { - spacing /= dt->current_zoom(); - } + double spacing; + + if (getSnapVisibleOnly()) { + // Only snapping to visible grid lines + spacing = grid->sw[i]; // this is the spacing of the visible grid lines measured in screen pixels + // convert screen pixels to px + // FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary + SPDesktop const *dt = _snapmanager->getDesktop(); + if (dt) { + spacing /= dt->current_zoom(); + } } else { - // Snapping to any grid line, whether it's visible or not - spacing = grid->spacing[i]; + // Snapping to any grid line, whether it's visible or not + spacing = grid->spacing[i]; } Geom::Coord rounded; @@ -1024,16 +1024,16 @@ CanvasXYGridSnapper::_getSnapLines(Geom::Point const &p) const return s; } -void CanvasXYGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, Geom::Point const normal_to_line, Geom::Point const point_on_line) const +void CanvasXYGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, Inkscape::SNAPTARGET_GRID, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, source_num, Inkscape::SNAPTARGET_GRID, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); sc.grid_lines.push_back(dummy); } -void CanvasXYGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const +void CanvasXYGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const { - SnappedPoint dummy = SnappedPoint(snapped_point, source, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); - sc.points.push_back(dummy); + SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + sc.points.push_back(dummy); } /** diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index 58cfbf735..daf28c15c 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -166,8 +166,8 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; - void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const; + void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; CanvasXYGrid *grid; }; diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index 118896fd3..a32f1a67f 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -809,7 +809,7 @@ void PdfParser::opSetExtGState(Object args[], int numArgs) { blendingColorSpace = NULL; isolated = knockout = gFalse; if (!obj4.dictLookup(const_cast("CS"), &obj5)->isNull()) { - blendingColorSpace = GfxColorSpace::parse(&obj5); + blendingColorSpace = GfxColorSpace::parse(&obj5,(Gfx*)this); } obj5.free(); if (obj4.dictLookup(const_cast("I"), &obj5)->isBool()) { @@ -1009,9 +1009,9 @@ void PdfParser::opSetFillColorSpace(Object args[], int numArgs) { state->setFillPattern(NULL); res->lookupColorSpace(args[0].getName(), &obj); if (obj.isNull()) { - colorSpace = GfxColorSpace::parse(&args[0]); + colorSpace = GfxColorSpace::parse(&args[0],(Gfx*)this); } else { - colorSpace = GfxColorSpace::parse(&obj); + colorSpace = GfxColorSpace::parse(&obj,(Gfx*)this); } obj.free(); if (colorSpace) { @@ -1032,9 +1032,9 @@ void PdfParser::opSetStrokeColorSpace(Object args[], int numArgs) { state->setStrokePattern(NULL); res->lookupColorSpace(args[0].getName(), &obj); if (obj.isNull()) { - colorSpace = GfxColorSpace::parse(&args[0]); + colorSpace = GfxColorSpace::parse(&args[0],(Gfx*)this); } else { - colorSpace = GfxColorSpace::parse(&obj); + colorSpace = GfxColorSpace::parse(&obj,(Gfx*)this); } obj.free(); if (colorSpace) { @@ -1101,7 +1101,7 @@ void PdfParser::opSetFillColorN(Object args[], int numArgs) { builder->updateStyle(state); } if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName()))) { + (pattern = res->lookupPattern(args[numArgs-1].getName(),(Gfx*)this))) { state->setFillPattern(pattern); builder->updateStyle(state); } @@ -1145,7 +1145,7 @@ void PdfParser::opSetStrokeColorN(Object args[], int numArgs) { builder->updateStyle(state); } if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName()))) { + (pattern = res->lookupPattern(args[numArgs-1].getName(),(Gfx*)this))) { state->setStrokePattern(pattern); builder->updateStyle(state); } @@ -1543,7 +1543,7 @@ void PdfParser::opShFill(Object args[], int numArgs) { double *matrix = NULL; GBool savedState = gFalse; - if (!(shading = res->lookupShading(args[0].getName()))) { + if (!(shading = res->lookupShading(args[0].getName(),(Gfx*)this))) { return; } @@ -2507,7 +2507,7 @@ void PdfParser::doImage(Object *ref, Stream *str, GBool inlineImg) { } } if (!obj1.isNull()) { - colorSpace = GfxColorSpace::parse(&obj1); + colorSpace = GfxColorSpace::parse(&obj1,(Gfx*)this); } else if (csMode == streamCSDeviceGray) { colorSpace = new GfxDeviceGrayColorSpace(); } else if (csMode == streamCSDeviceRGB) { @@ -2592,7 +2592,7 @@ void PdfParser::doImage(Object *ref, Stream *str, GBool inlineImg) { obj2.free(); } } - maskColorSpace = GfxColorSpace::parse(&obj1); + maskColorSpace = GfxColorSpace::parse(&obj1,(Gfx*)this); obj1.free(); if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { goto err1; @@ -2767,7 +2767,7 @@ void PdfParser::doForm(Object *str) { if (obj1.dictLookup(const_cast("S"), &obj2)->isName(const_cast("Transparency"))) { transpGroup = gTrue; if (!obj1.dictLookup(const_cast("CS"), &obj3)->isNull()) { - blendingColorSpace = GfxColorSpace::parse(&obj3); + blendingColorSpace = GfxColorSpace::parse(&obj3,(Gfx*)this); } obj3.free(); if (obj1.dictLookup(const_cast("I"), &obj3)->isBool()) { diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index c16ed2456..e61bd9552 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -609,7 +609,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp dist = fabs(p[Geom::Y] - dragger->parent->hor_levels[i]); if (dist < snap_dist) { p[Geom::Y] = dragger->parent->hor_levels[i]; - s = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_HANDLE, Inkscape::SNAPTARGET_GRADIENTS_PARENT_BBOX, dist, snap_dist, false, false); + s = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_HANDLE, 0, Inkscape::SNAPTARGET_GRADIENTS_PARENT_BBOX, dist, snap_dist, false, false); was_snapped = true; sp_knot_moveto (knot, p); } @@ -618,7 +618,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp dist = fabs(p[Geom::X] - dragger->parent->vert_levels[i]); if (dist < snap_dist) { p[Geom::X] = dragger->parent->vert_levels[i]; - s = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_HANDLE, Inkscape::SNAPTARGET_GRADIENTS_PARENT_BBOX, dist, snap_dist, false, false); + s = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_HANDLE, 0, Inkscape::SNAPTARGET_GRADIENTS_PARENT_BBOX, dist, snap_dist, false, false); was_snapped = true; sp_knot_moveto (knot, p); } diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp index 5cf97958a..9121e3ee2 100644 --- a/src/guide-snapper.cpp +++ b/src/guide-snapper.cpp @@ -68,22 +68,22 @@ bool Inkscape::GuideSnapper::ThisSnapperMightSnap() const return (_snap_enabled && _snapmanager->snapprefs.getSnapToGuides() && _snapmanager->getNamedView()->showguides); } -void Inkscape::GuideSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, Geom::Point const normal_to_line, Geom::Point const point_on_line) const +void Inkscape::GuideSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, Inkscape::SNAPTARGET_GUIDE, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, source_num, Inkscape::SNAPTARGET_GUIDE, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); sc.guide_lines.push_back(dummy); } -void Inkscape::GuideSnapper::_addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source) const +void Inkscape::GuideSnapper::_addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const { - SnappedPoint dummy = SnappedPoint(origin, source, Inkscape::SNAPTARGET_GUIDE_ORIGIN, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint dummy = SnappedPoint(origin, source, source_num, Inkscape::SNAPTARGET_GUIDE_ORIGIN, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); sc.points.push_back(dummy); } -void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const +void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const { - SnappedPoint dummy = SnappedPoint(snapped_point, source, Inkscape::SNAPTARGET_GUIDE, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint dummy = SnappedPoint(snapped_point, source, source_num, Inkscape::SNAPTARGET_GUIDE, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); sc.points.push_back(dummy); } diff --git a/src/guide-snapper.h b/src/guide-snapper.h index 1dc602f72..5adac6e22 100644 --- a/src/guide-snapper.h +++ b/src/guide-snapper.h @@ -30,13 +30,13 @@ public: bool ThisSnapperMightSnap() const; Geom::Coord getSnapperTolerance() const; //returns the tolerance of the snapper in screen pixels (i.e. independent of zoom) - bool getSnapperAlwaysSnap() const; //if true, then the snapper will always snap, regardless of its tolerance + bool getSnapperAlwaysSnap() const; //if true, then the snapper will always snap, regardless of its tolerance private: LineList _getSnapLines(Geom::Point const &p) const; - void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, Geom::Point const normal_to_line, Geom::Point const point_on_line) const; - void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source) const; - void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const; + void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const; + void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; + void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; }; } diff --git a/src/libnr/nr-compose.cpp b/src/libnr/nr-compose.cpp index 3b99678e2..74f9d036b 100644 --- a/src/libnr/nr-compose.cpp +++ b/src/libnr/nr-compose.cpp @@ -773,6 +773,7 @@ nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const un c[3] = a; /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */ nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (px, w, h, rs, mpx, mrs, c); + // This mmx optimized code is approx. 2x faster than the non-optimized code below (Measured by Diederik van Lierop, 2009-12-17) return; } #endif diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index 5d5a77280..31fa07515 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -25,7 +25,7 @@ void Inkscape::LineSnapper::freeSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const &source_type, - bool const &/*f*/, + long source_num, Geom::OptRect const &/*bbox_to_snap*/, std::vector const */*it*/, std::vector > */*unselected_nodes*/) const @@ -49,13 +49,13 @@ void Inkscape::LineSnapper::freeSnap(SnappedConstraints &sc, Geom::Coord const dist = Geom::L2(p_proj - p); //Store any line that's within snapping range if (dist < getSnapperTolerance()) { - _addSnappedLine(sc, p_proj, dist, source_type, i->first, i->second); + _addSnappedLine(sc, p_proj, dist, source_type, source_num, i->first, i->second); // For any line that's within range, we will also look at it's "point on line" p1. For guides // this point coincides with its origin; for grids this is of no use, but we cannot // discern between grids and guides here Geom::Coord const dist_p1 = Geom::L2(p1 - p); if (dist_p1 < getSnapperTolerance()) { - _addSnappedLinesOrigin(sc, p1, dist_p1, source_type); + _addSnappedLinesOrigin(sc, p1, dist_p1, source_type, source_num); // Only relevant for guides; grids don't have an origin per line // Therefore _addSnappedLinesOrigin() will only be implemented for guides } @@ -69,7 +69,7 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const &source_type, - bool const &/*f*/, + long source_num, Geom::OptRect const &/*bbox_to_snap*/, ConstraintLine const &c, std::vector const */*it*/) const @@ -112,13 +112,13 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, // This snappoint is therefore fully constrained, so there's no need // to look for additional intersections; just return the snapped point // and forget about the line - _addSnappedPoint(sc, t, dist, source_type); + _addSnappedPoint(sc, t, dist, source_type, source_num); // For any line that's within range, we will also look at it's "point on line" p1. For guides // this point coincides with its origin; for grids this is of no use, but we cannot // discern between grids and guides here Geom::Coord const dist_p1 = Geom::L2(p1 - p); if (dist_p1 < getSnapperTolerance()) { - _addSnappedLinesOrigin(sc, p1, dist_p1, source_type); + _addSnappedLinesOrigin(sc, p1, dist_p1, source_type, source_num); // Only relevant for guides; grids don't have an origin per line // Therefore _addSnappedLinesOrigin() will only be implemented for guides } @@ -130,7 +130,7 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, // Will only be overridden in the guide-snapper class, because grid lines don't have an origin; the // grid-snapper classes will use this default empty method -void Inkscape::LineSnapper::_addSnappedLinesOrigin(SnappedConstraints &/*sc*/, Geom::Point const /*origin*/, Geom::Coord const /*snapped_distance*/, SnapSourceType const &/*source_type*/) const +void Inkscape::LineSnapper::_addSnappedLinesOrigin(SnappedConstraints &/*sc*/, Geom::Point const /*origin*/, Geom::Coord const /*snapped_distance*/, SnapSourceType const &/*source_type*/, long /*source_num*/) const { } diff --git a/src/line-snapper.h b/src/line-snapper.h index 4ad08a99f..af36b8330 100644 --- a/src/line-snapper.h +++ b/src/line-snapper.h @@ -28,7 +28,7 @@ public: Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const &source_type, - bool const &first_point, + long source_num, Geom::OptRect const &bbox_to_snap, std::vector const *it, std::vector > *unselected_nodes) const; @@ -37,7 +37,7 @@ public: Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const &source_type, - bool const &first_point, + long source_num, Geom::OptRect const &bbox_to_snap, ConstraintLine const &c, std::vector const *it) const; @@ -54,12 +54,12 @@ private: */ virtual LineList _getSnapLines(Geom::Point const &p) const = 0; - virtual void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, Geom::Point const normal_to_line, Geom::Point const point_on_line) const = 0; + virtual void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num, Geom::Point const normal_to_line, Geom::Point const point_on_line) const = 0; // Will only be implemented for guide lines, because grid lines don't have an origin - virtual void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source) const; + virtual void _addSnappedLinesOrigin(SnappedConstraints &sc, Geom::Point const origin, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const; - virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const = 0; + virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, long source_num) const = 0; }; } diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 22d438c1e..88c260782 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -67,9 +67,9 @@ Inkscape::ObjectSnapper::~ObjectSnapper() */ Geom::Coord Inkscape::ObjectSnapper::getSnapperTolerance() const { - SPDesktop const *dt = _snapmanager->getDesktop(); - double const zoom = dt ? dt->current_zoom() : 1; - return _snapmanager->snapprefs.getObjectTolerance() / zoom; + SPDesktop const *dt = _snapmanager->getDesktop(); + double const zoom = dt ? dt->current_zoom() : 1; + return _snapmanager->snapprefs.getObjectTolerance() / zoom; } bool Inkscape::ObjectSnapper::getSnapperAlwaysSnap() const @@ -81,7 +81,6 @@ bool Inkscape::ObjectSnapper::getSnapperAlwaysSnap() const * Find all items within snapping range. * \param parent Pointer to the document's root, or to a clipped path or mask object * \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 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. */ @@ -173,7 +172,7 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType const &t, - bool const &first_point) const + bool const &first_point) const { // Now, let's first collect all points to snap to. If we have a whole bunch of points to snap, // e.g. when translating an item using the selector tool, then we will only do this for the @@ -212,47 +211,47 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType g_return_if_fail(root_item); //Collect all nodes so we can snap to them - if (p_is_a_node || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node) || p_is_a_guide) { - // Note: there are two ways in which intersections are considered: - // Method 1: Intersections are calculated for each shape individually, for both the - // snap source and snap target (see sp_shape_snappoints) - // Method 2: Intersections are calculated for each curve or line that we've snapped to, i.e. only for - // the target (see the intersect() method in the SnappedCurve and SnappedLine classes) - // Some differences: - // - Method 1 doesn't find intersections within a set of multiple objects - // - Method 2 only works for targets - // When considering intersections as snap targets: - // - Method 1 only works when snapping to nodes, whereas - // - Method 2 only works when snapping to paths - // - There will be performance differences too! - // If both methods are being used simultaneously, then this might lead to duplicate targets! - - // Well, here we will be looking for snap TARGETS. Both methods can therefore be used. - // When snapping to paths, we will get a collection of snapped lines and snapped curves. findBestSnap() will - // go hunting for intersections (but only when asked to in the prefs of course). In that case we can just - // temporarily block the intersections in sp_item_snappoints, we don't need duplicates. If we're not snapping to - // paths though but only to item nodes then we should still look for the intersections in sp_item_snappoints() - bool old_pref = _snapmanager->snapprefs.getSnapIntersectionCS(); - if (_snapmanager->snapprefs.getSnapToItemPath()) { - _snapmanager->snapprefs.setSnapIntersectionCS(false); - } - - sp_item_snappoints(root_item, true, *_points_to_snap_to, &_snapmanager->snapprefs); - - if (_snapmanager->snapprefs.getSnapToItemPath()) { - _snapmanager->snapprefs.setSnapIntersectionCS(old_pref); - } - } + if (p_is_a_node || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node) || p_is_a_guide) { + // Note: there are two ways in which intersections are considered: + // Method 1: Intersections are calculated for each shape individually, for both the + // snap source and snap target (see sp_shape_snappoints) + // Method 2: Intersections are calculated for each curve or line that we've snapped to, i.e. only for + // the target (see the intersect() method in the SnappedCurve and SnappedLine classes) + // Some differences: + // - Method 1 doesn't find intersections within a set of multiple objects + // - Method 2 only works for targets + // When considering intersections as snap targets: + // - Method 1 only works when snapping to nodes, whereas + // - Method 2 only works when snapping to paths + // - There will be performance differences too! + // If both methods are being used simultaneously, then this might lead to duplicate targets! + + // Well, here we will be looking for snap TARGETS. Both methods can therefore be used. + // When snapping to paths, we will get a collection of snapped lines and snapped curves. findBestSnap() will + // go hunting for intersections (but only when asked to in the prefs of course). In that case we can just + // temporarily block the intersections in sp_item_snappoints, we don't need duplicates. If we're not snapping to + // paths though but only to item nodes then we should still look for the intersections in sp_item_snappoints() + bool old_pref = _snapmanager->snapprefs.getSnapIntersectionCS(); + if (_snapmanager->snapprefs.getSnapToItemPath()) { + _snapmanager->snapprefs.setSnapIntersectionCS(false); + } + + sp_item_snappoints(root_item, true, *_points_to_snap_to, &_snapmanager->snapprefs); + + if (_snapmanager->snapprefs.getSnapToItemPath()) { + _snapmanager->snapprefs.setSnapIntersectionCS(old_pref); + } + } //Collect the bounding box's corners so we can snap to them - if (p_is_a_bbox || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_bbox) || p_is_a_guide) { - // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox - // of the item AND the bbox of the clipping path at the same time - if (!(*i).clip_or_mask) { - Geom::OptRect b = sp_item_bbox_desktop(root_item, bbox_type); - getBBoxPoints(b, _points_to_snap_to, true, _snapmanager->snapprefs.getSnapToBBoxNode(), _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints(), _snapmanager->snapprefs.getSnapBBoxMidpoints()); - } - } + if (p_is_a_bbox || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_bbox) || p_is_a_guide) { + // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox + // of the item AND the bbox of the clipping path at the same time + if (!(*i).clip_or_mask) { + Geom::OptRect b = sp_item_bbox_desktop(root_item, bbox_type); + getBBoxPoints(b, _points_to_snap_to, true, _snapmanager->snapprefs.getSnapToBBoxNode(), _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints(), _snapmanager->snapprefs.getSnapBBoxMidpoints()); + } + } } } } @@ -261,12 +260,12 @@ void Inkscape::ObjectSnapper::_snapNodes(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const &source_type, - bool const &first_point, + long source_num, std::vector > *unselected_nodes) const { // Iterate through all nodes, find out which one is the closest to p, and snap to it! - _collectNodes(t, first_point); + _collectNodes(t, source_num == 0); if (unselected_nodes != NULL) { _points_to_snap_to->insert(_points_to_snap_to->end(), unselected_nodes->begin(), unselected_nodes->end()); @@ -278,7 +277,7 @@ void Inkscape::ObjectSnapper::_snapNodes(SnappedConstraints &sc, for (std::vector >::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) { Geom::Coord dist = Geom::L2((*k).first - p); if (dist < getSnapperTolerance() && dist < s.getSnapDistance()) { - s = SnappedPoint((*k).first, source_type, static_cast((*k).second), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + s = SnappedPoint((*k).first, source_type, source_num, static_cast((*k).second), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); success = true; } } @@ -298,10 +297,10 @@ void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &s // Although we won't snap to paths here (which would give us under constrained snaps) we can still snap to intersections of paths. if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { - _collectPaths(t, true); - _snapPaths(sc, t, p, SNAPSOURCE_GUIDE, true, NULL, NULL); - // The paths themselves should be discarded in findBestSnap(), as we should only snap to their intersections - } + _collectPaths(t, true); + _snapPaths(sc, t, p, SNAPSOURCE_GUIDE, 0, NULL, NULL); + // The paths themselves should be discarded in findBestSnap(), as we should only snap to their intersections + } SnappedPoint s; @@ -313,7 +312,7 @@ void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &s Geom::Coord dist = Geom::L2((*k).first - 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).first, SNAPSOURCE_GUIDE, static_cast((*k).second), dist, tol, getSnapperAlwaysSnap(), true); + s = SnappedPoint((*k).first, SNAPSOURCE_GUIDE, 0, static_cast((*k).second), dist, tol, getSnapperAlwaysSnap(), true); sc.points.push_back(s); } } @@ -428,11 +427,11 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const &source_type, - bool const &first_point, + long source_num, std::vector > *unselected_nodes, SPPath const *selected_path) const { - _collectPaths(t, first_point); + _collectPaths(t, source_num == 0); // Now we can finally do the real snapping, using the paths collected above g_assert(_snapmanager->getDesktop() != NULL); @@ -440,7 +439,7 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc, bool const node_tool_active = _snapmanager->snapprefs.getSnapToItemPath() && selected_path != NULL; - if (first_point) { + if (source_num == 0) { /* findCandidates() is used for snapping to both paths and nodes. It ignores the path that is * currently being edited, because that path requires special care: when snapping to nodes * only the unselected nodes of that path should be considered, and these will be passed on separately. @@ -503,7 +502,7 @@ 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, source_type, it_p->second)); + sc.curves.push_back(Inkscape::SnappedCurve(sp_dt, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, curve, source_type, source_num, it_p->second)); } } } @@ -535,11 +534,11 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const source_type, - bool const &first_point, + long source_num, ConstraintLine const &c) const { - _collectPaths(t, first_point); + _collectPaths(t, source_num == 0); // Now we can finally do the real snapping, using the paths collected above @@ -577,7 +576,7 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, // 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), source_type, k->second, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint s(_snapmanager->getDesktop()->doc2dt(p_inters), source_type, source_num, k->second, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); sc.points.push_back(s); } } @@ -591,7 +590,7 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const &source_type, - bool const &first_point, + long source_num, Geom::OptRect const &bbox_to_snap, std::vector const *it, std::vector > *unselected_nodes) const @@ -601,17 +600,17 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, } /* Get a list of all the SPItems that we will try to snap to */ - if (first_point) { + if (source_num == 0) { Geom::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : Geom::Rect(p, p); - _findCandidates(sp_document_root(_snapmanager->getDocument()), it, first_point, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); + _findCandidates(sp_document_root(_snapmanager->getDocument()), it, source_num == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); } if (_snapmanager->snapprefs.getSnapToItemNode() || _snapmanager->snapprefs.getSnapSmoothNodes() - || _snapmanager->snapprefs.getSnapToBBoxNode() || _snapmanager->snapprefs.getSnapToPageBorder() - || _snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints() - || _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints() - || _snapmanager->snapprefs.getIncludeItemCenter()) { - _snapNodes(sc, t, p, source_type, first_point, unselected_nodes); + || _snapmanager->snapprefs.getSnapToBBoxNode() || _snapmanager->snapprefs.getSnapToPageBorder() + || _snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints() + || _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints() + || _snapmanager->snapprefs.getIncludeItemCenter()) { + _snapNodes(sc, t, p, source_type, source_num, unselected_nodes); } if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { @@ -625,13 +624,13 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, SPPath *path = NULL; if (it != NULL) { if (it->size() == 1 && SP_IS_PATH(*it->begin())) { - path = SP_PATH(*it->begin()); + path = SP_PATH(*it->begin()); } // else: *it->begin() might be a SPGroup, e.g. when editing a LPE of text that has been converted to a group of paths // as reported in bug #356743. In that case we can just ignore it, i.e. not snap to this item } - _snapPaths(sc, t, p, source_type, first_point, unselected_nodes, path); + _snapPaths(sc, t, p, source_type, source_num, unselected_nodes, path); } else { - _snapPaths(sc, t, p, source_type, first_point, NULL, NULL); + _snapPaths(sc, t, p, source_type, source_num, NULL, NULL); } } } @@ -640,7 +639,7 @@ void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, SnapSourceType const &source_type, - bool const &first_point, + long source_num, Geom::OptRect const &bbox_to_snap, ConstraintLine const &c, std::vector const *it) const @@ -650,9 +649,9 @@ void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, } /* Get a list of all the SPItems that we will try to snap to */ - if (first_point) { + if (source_num == 0) { Geom::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : Geom::Rect(p, p); - _findCandidates(sp_document_root(_snapmanager->getDocument()), it, first_point, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); + _findCandidates(sp_document_root(_snapmanager->getDocument()), it, source_num == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); } // A constrained snap, is a snap in only one degree of freedom (specified by the constraint line). @@ -665,7 +664,7 @@ void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, // so we will more or less snap to them anyhow. if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { - _snapPathsConstrained(sc, t, p, source_type, first_point, c); + _snapPathsConstrained(sc, t, p, source_type, 0, c); } } @@ -723,13 +722,13 @@ void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc, bool Inkscape::ObjectSnapper::ThisSnapperMightSnap() const { bool snap_to_something = _snapmanager->snapprefs.getSnapToItemPath() - || _snapmanager->snapprefs.getSnapToItemNode() - || _snapmanager->snapprefs.getSnapToBBoxPath() - || _snapmanager->snapprefs.getSnapToBBoxNode() - || _snapmanager->snapprefs.getSnapToPageBorder() - || _snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints() - || _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints() - || _snapmanager->snapprefs.getIncludeItemCenter(); + || _snapmanager->snapprefs.getSnapToItemNode() + || _snapmanager->snapprefs.getSnapToBBoxPath() + || _snapmanager->snapprefs.getSnapToBBoxNode() + || _snapmanager->snapprefs.getSnapToPageBorder() + || _snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints() + || _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints() + || _snapmanager->snapprefs.getIncludeItemCenter(); return (_snap_enabled && _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && snap_to_something); } @@ -737,12 +736,12 @@ 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() - || _snapmanager->snapprefs.getSnapToPageBorder() - || (_snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxNode()) - || (_snapmanager->snapprefs.getSnapModeBBox() && (_snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints())) - || (_snapmanager->snapprefs.getSnapModeNode() && (_snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints())) - || (_snapmanager->snapprefs.getSnapModeNode() && _snapmanager->snapprefs.getIncludeItemCenter()) - || (_snapmanager->snapprefs.getSnapModeNode() && (_snapmanager->snapprefs.getSnapToItemPath() && _snapmanager->snapprefs.getSnapIntersectionCS())); + || _snapmanager->snapprefs.getSnapToPageBorder() + || (_snapmanager->snapprefs.getSnapModeBBox() && _snapmanager->snapprefs.getSnapToBBoxNode()) + || (_snapmanager->snapprefs.getSnapModeBBox() && (_snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints())) + || (_snapmanager->snapprefs.getSnapModeNode() && (_snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints())) + || (_snapmanager->snapprefs.getSnapModeNode() && _snapmanager->snapprefs.getIncludeItemCenter()) + || (_snapmanager->snapprefs.getSnapModeNode() && (_snapmanager->snapprefs.getSnapToItemPath() && _snapmanager->snapprefs.getSnapIntersectionCS())); return (_snap_enabled && _snapmanager->snapprefs.getSnapModeGuide() && snap_to_something); } @@ -784,21 +783,21 @@ void Inkscape::ObjectSnapper::_getBorderNodes(std::vector > *points, bool const isTarget, bool const includeCorners, bool const includeLineMidpoints, bool const includeObjectMidpoints) { - if (bbox) { - // collect the corners of the bounding box - for ( unsigned k = 0 ; k < 4 ; k++ ) { - if (includeCorners) { - points->push_back(std::make_pair((bbox->corner(k)), isTarget ? int(Inkscape::SNAPTARGET_BBOX_CORNER) : int(Inkscape::SNAPSOURCE_BBOX_CORNER))); - } - // optionally, collect the midpoints of the bounding box's edges too - if (includeLineMidpoints) { - points->push_back(std::make_pair((bbox->corner(k) + bbox->corner((k+1) % 4))/2, isTarget ? int(Inkscape::SNAPTARGET_BBOX_EDGE_MIDPOINT) : int(Inkscape::SNAPSOURCE_BBOX_EDGE_MIDPOINT))); - } - } - if (includeObjectMidpoints) { - points->push_back(std::make_pair(bbox->midpoint(), isTarget ? int(Inkscape::SNAPTARGET_BBOX_MIDPOINT) : int(Inkscape::SNAPSOURCE_BBOX_MIDPOINT))); - } - } + if (bbox) { + // collect the corners of the bounding box + for ( unsigned k = 0 ; k < 4 ; k++ ) { + if (includeCorners) { + points->push_back(std::make_pair((bbox->corner(k)), isTarget ? int(Inkscape::SNAPTARGET_BBOX_CORNER) : int(Inkscape::SNAPSOURCE_BBOX_CORNER))); + } + // optionally, collect the midpoints of the bounding box's edges too + if (includeLineMidpoints) { + points->push_back(std::make_pair((bbox->corner(k) + bbox->corner((k+1) % 4))/2, isTarget ? int(Inkscape::SNAPTARGET_BBOX_EDGE_MIDPOINT) : int(Inkscape::SNAPSOURCE_BBOX_EDGE_MIDPOINT))); + } + } + if (includeObjectMidpoints) { + points->push_back(std::make_pair(bbox->midpoint(), isTarget ? int(Inkscape::SNAPTARGET_BBOX_MIDPOINT) : int(Inkscape::SNAPSOURCE_BBOX_MIDPOINT))); + } + } } /* diff --git a/src/object-snapper.h b/src/object-snapper.h index baa60a096..2fcafb79a 100644 --- a/src/object-snapper.h +++ b/src/object-snapper.h @@ -46,47 +46,47 @@ class ObjectSnapper : public Snapper { public: - ObjectSnapper(SnapManager *sm, Geom::Coord const d); + ObjectSnapper(SnapManager *sm, Geom::Coord const d); ~ObjectSnapper(); - 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 - TRANSL_SNAP_XY}; // All other cases; for snapping to objects, other than guides - - void guideFreeSnap(SnappedConstraints &sc, - Geom::Point const &p, - Geom::Point const &guide_normal) const; - - void guideConstrainedSnap(SnappedConstraints &sc, - Geom::Point const &p, - Geom::Point const &guide_normal, - ConstraintLine const &c) const; - - bool ThisSnapperMightSnap() const; - bool GuidesMightSnap() const; - - Geom::Coord getSnapperTolerance() const; //returns the tolerance of the snapper in screen pixels (i.e. independent of zoom) - bool getSnapperAlwaysSnap() const; //if true, then the snapper will always snap, regardless of its tolerance - - void freeSnap(SnappedConstraints &sc, - Inkscape::SnapPreferences::PointType const &t, - Geom::Point const &p, - SnapSourceType const &source_type, - bool const &first_point, - Geom::OptRect const &bbox_to_snap, - std::vector const *it, - std::vector > *unselected_nodes) const; - - void constrainedSnap(SnappedConstraints &sc, - Inkscape::SnapPreferences::PointType const &t, - Geom::Point const &p, - SnapSourceType const &source_type, - bool const &first_point, - Geom::OptRect const &bbox_to_snap, - ConstraintLine const &c, - std::vector const *it) const; + 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 + TRANSL_SNAP_XY}; // All other cases; for snapping to objects, other than guides + + void guideFreeSnap(SnappedConstraints &sc, + Geom::Point const &p, + Geom::Point const &guide_normal) const; + + void guideConstrainedSnap(SnappedConstraints &sc, + Geom::Point const &p, + Geom::Point const &guide_normal, + ConstraintLine const &c) const; + + bool ThisSnapperMightSnap() const; + bool GuidesMightSnap() const; + + Geom::Coord getSnapperTolerance() const; //returns the tolerance of the snapper in screen pixels (i.e. independent of zoom) + bool getSnapperAlwaysSnap() const; //if true, then the snapper will always snap, regardless of its tolerance + + void freeSnap(SnappedConstraints &sc, + Inkscape::SnapPreferences::PointType const &t, + Geom::Point const &p, + SnapSourceType const &source_type, + long source_num, + Geom::OptRect const &bbox_to_snap, + std::vector const *it, + std::vector > *unselected_nodes) const; + + void constrainedSnap(SnappedConstraints &sc, + Inkscape::SnapPreferences::PointType const &t, + Geom::Point const &p, + SnapSourceType const &source_type, + long source_num, + Geom::OptRect const &bbox_to_snap, + ConstraintLine const &c, + std::vector const *it) 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 @@ -106,7 +106,7 @@ private: Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, // in desktop coordinates SnapSourceType const &source_type, - bool const &first_point, + long source_num, std::vector > *unselected_nodes) const; // in desktop coordinates void _snapTranslatingGuideToNodes(SnappedConstraints &sc, @@ -119,9 +119,9 @@ private: void _snapPaths(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, - Geom::Point const &p, // in desktop coordinates + Geom::Point const &p, // in desktop coordinates SnapSourceType const &source_type, - bool const &first_point, + long source_num, std::vector > *unselected_nodes, // in desktop coordinates SPPath const *selected_path) const; @@ -129,7 +129,7 @@ private: Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, // in desktop coordinates SnapSourceType const source_type, - bool const &first_point, + long source_num, ConstraintLine const &c) const; bool isUnselectedNode(Geom::Point const &point, std::vector > const *unselected_nodes) const; diff --git a/src/snap.cpp b/src/snap.cpp index 545607889..2e38e4f14 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -164,18 +164,18 @@ bool SnapManager::gridSnapperMightSnap() const * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred * \param source_type Detailed description of the source type, will be used by the snap indicator - * \param first_point If true then this point is the first one from a set of points, all from the same selection and having the same transformation + * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, Geom::Point &p, Inkscape::SnapSourceType const source_type, - bool first_point, + long source_num, Geom::OptRect const &bbox_to_snap) const { //TODO: PointType and source_type are somewhat redundant; can't we get rid of the point_type parameter? - Inkscape::SnappedPoint const s = freeSnap(point_type, p, source_type, first_point, bbox_to_snap); + Inkscape::SnappedPoint const s = freeSnap(point_type, p, source_type, source_num, bbox_to_snap); s.getPoint(p); } @@ -194,7 +194,7 @@ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Current position of the snap source * \param source_type Detailed description of the source type, will be used by the snap indicator - * \param first_point If true then this point is the first one from a set of points, all from the same selection and having the same transformation + * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics */ @@ -203,11 +203,11 @@ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointType point_type, Geom::Point const &p, Inkscape::SnapSourceType const &source_type, - bool first_point, + long source_num, Geom::OptRect const &bbox_to_snap) const { - if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, source_type, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + if (!someSnapperMightSnap()) { + return Inkscape::SnappedPoint(p, source_type, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } std::vector *items_to_ignore; @@ -224,7 +224,7 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, point_type, p, source_type, first_point, bbox_to_snap, items_to_ignore, _unselected_nodes); + (*i)->freeSnap(sc, point_type, p, source_type, source_num, bbox_to_snap, items_to_ignore, _unselected_nodes); } if (_item_to_ignore) { @@ -280,7 +280,7 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const Geom::Point const t_offset = t + grid->origin; SnappedConstraints sc; // Only the first three parameters are being used for grid snappers - snapper->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_NODE, t_offset, Inkscape::SNAPSOURCE_UNDEFINED, TRUE, Geom::OptRect(), NULL, NULL); + snapper->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_NODE, t_offset, Inkscape::SNAPSOURCE_UNDEFINED, 0, Geom::OptRect(), NULL, NULL); // Find the best snap for this grid, including intersections of the grid-lines Inkscape::SnappedPoint s = findBestSnap(t_offset, Inkscape::SNAPSOURCE_UNDEFINED, sc, false); if (s.getSnapped() && (s.getSnapDistance() < nearest_distance)) { @@ -323,7 +323,7 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred * \param source_type Detailed description of the source type, will be used by the snap indicator * \param constraint The direction or line along which snapping must occur - * \param first_point If true then this point is the first one from a set of points, all from the same selection and having the same transformation + * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ @@ -331,10 +331,10 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp Geom::Point &p, Inkscape::SnapSourceType const source_type, Inkscape::Snapper::ConstraintLine const &constraint, - bool first_point, + long source_num, Geom::OptRect const &bbox_to_snap) const { - Inkscape::SnappedPoint const s = constrainedSnap(point_type, p, source_type, constraint, first_point, bbox_to_snap); + Inkscape::SnappedPoint const s = constrainedSnap(point_type, p, source_type, constraint, source_num, bbox_to_snap); s.getPoint(p); } @@ -353,7 +353,7 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp * \param p Current position of the snap source * \param source_type Detailed description of the source type, will be used by the snap indicator * \param constraint The direction or line along which snapping must occur - * \param first_point If true then this point is the first one from a set of points, all from the same selection and having the same transformation + * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ @@ -361,11 +361,11 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P Geom::Point const &p, Inkscape::SnapSourceType const &source_type, Inkscape::Snapper::ConstraintLine const &constraint, - bool first_point, + long source_num, Geom::OptRect const &bbox_to_snap) const { if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, source_type, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(p, source_type, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } std::vector *items_to_ignore; @@ -386,7 +386,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P SnappedConstraints sc; SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, point_type, pp, source_type, first_point, bbox_to_snap, constraint, items_to_ignore); + (*i)->constrainedSnap(sc, point_type, pp, source_type, source_num, bbox_to_snap, constraint, items_to_ignore); } if (_item_to_ignore) { @@ -420,7 +420,7 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, Inkscape::SnapSourceType source_type = Inkscape::SNAPSOURCE_GUIDE_ORIGIN; if (drag_type == SP_DRAG_ROTATE) { - source_type = Inkscape::SNAPSOURCE_GUIDE; + source_type = Inkscape::SNAPSOURCE_GUIDE; } // Snap to nodes @@ -432,9 +432,9 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, // Snap to guides & grid lines SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); - for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, true, Geom::OptRect(), NULL, NULL); - } + for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { + (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, 0, Geom::OptRect(), NULL, NULL); + } // Snap to intersections of curves, but not to the curves themselves! (see _snapTranslatingGuideToNodes in object-snapper.cpp) Inkscape::SnappedPoint const s = findBestSnap(p, source_type, sc, false, true); @@ -458,7 +458,7 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const { - if (!snapprefs.getSnapEnabledGlobally() || snapprefs.getSnapPostponedGlobally()) { + if (!snapprefs.getSnapEnabledGlobally() || snapprefs.getSnapPostponedGlobally()) { return; } @@ -472,15 +472,15 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) SnappedConstraints sc; Inkscape::Snapper::ConstraintLine cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line)); if (object.ThisSnapperMightSnap()) { - object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, true, Geom::OptRect(), cl, NULL); + object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, 0, Geom::OptRect(), cl, 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, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, true, Geom::OptRect(), cl, NULL); - } + SnapperList snappers = getGridSnappers(); + snappers.push_back(&guide); + for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { + (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, source_type, 0, Geom::OptRect(), cl, NULL); + } Inkscape::SnappedPoint const s = findBestSnap(p, source_type, sc, false); s.getPoint(p); @@ -566,6 +566,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( g_assert(best_snapped_point.getAtIntersection() == false); std::vector >::const_iterator j = transformed_points.begin(); + long source_num = 0; // std::cout << std::endl; for (std::vector >::const_iterator i = points.begin(); i != points.end(); i++) { @@ -593,7 +594,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( if (transformation_type == SCALE && !uniform) { g_warning("Non-uniform constrained scaling is not supported!"); } - snapped_point = constrainedSnap(type, (*j).first, static_cast((*j).second), dedicated_constraint, i == points.begin(), bbox); + snapped_point = constrainedSnap(type, (*j).first, static_cast((*j).second), dedicated_constraint, source_num, bbox); } else { bool const c1 = fabs(b[Geom::X]) < 1e-6; bool const c2 = fabs(b[Geom::Y]) < 1e-6; @@ -602,9 +603,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // move in that specific direction; therefore it should only snap in that direction, otherwise // we will get snapped points with an invalid transformation dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, component_vectors[c1]); - snapped_point = constrainedSnap(type, (*j).first, static_cast((*j).second), dedicated_constraint, i == points.begin(), bbox); + snapped_point = constrainedSnap(type, (*j).first, static_cast((*j).second), dedicated_constraint, source_num, bbox); } else { - snapped_point = freeSnap(type, (*j).first, static_cast((*j).second), i == points.begin(), bbox); + snapped_point = freeSnap(type, (*j).first, static_cast((*j).second), source_num, bbox); } } // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl; @@ -715,6 +716,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( } j++; + source_num++; } Geom::Coord best_metric; @@ -917,10 +919,10 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference */ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, - Inkscape::SnapSourceType const source_type, - SnappedConstraints &sc, - bool constrained, - bool noCurves) const + Inkscape::SnapSourceType const source_type, + SnappedConstraints &sc, + bool constrained, + bool noCurves) const { /* @@ -943,10 +945,10 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, // search for the closest snapped curve if (!noCurves) { - Inkscape::SnappedCurve closestCurve; - if (getClosestCurve(sc.curves, closestCurve)) { - sp_list.push_back(Inkscape::SnappedPoint(closestCurve)); - } + Inkscape::SnappedCurve closestCurve; + if (getClosestCurve(sc.curves, closestCurve)) { + sp_list.push_back(Inkscape::SnappedPoint(closestCurve)); + } } if (snapprefs.getSnapIntersectionCS()) { @@ -1005,7 +1007,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, } // now let's see which snapped point gets a thumbs up - Inkscape::SnappedPoint bestSnappedPoint = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + Inkscape::SnappedPoint bestSnappedPoint = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_UNDEFINED, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); // std::cout << "Finding the best snap..." << std::endl; for (std::list::const_iterator i = sp_list.begin(); i != sp_list.end(); i++) { // first find out if this snapped point is within snapping range diff --git a/src/snap.h b/src/snap.h index e621bdb60..a3e463092 100644 --- a/src/snap.h +++ b/src/snap.h @@ -52,14 +52,14 @@ class SPNamedView; class SnapManager { public: - enum Transformation { + enum Transformation { TRANSLATION, SCALE, STRETCH, SKEW }; - SnapManager(SPNamedView const *v); + SnapManager(SPNamedView const *v); typedef std::list SnapperList; @@ -67,30 +67,30 @@ public: bool gridSnapperMightSnap() const; void setup(SPDesktop const *desktop, - bool snapindicator = true, - SPItem const *item_to_ignore = NULL, - std::vector > *unselected_nodes = NULL, - SPGuide *guide_to_ignore = NULL); + bool snapindicator = true, + SPItem const *item_to_ignore = NULL, + std::vector > *unselected_nodes = NULL, + SPGuide *guide_to_ignore = NULL); void setup(SPDesktop const *desktop, - bool snapindicator, - std::vector &items_to_ignore, - std::vector > *unselected_nodes = NULL, - SPGuide *guide_to_ignore = NULL); + bool snapindicator, + std::vector &items_to_ignore, + std::vector > *unselected_nodes = NULL, + SPGuide *guide_to_ignore = NULL); // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a // point if snapping has occurred (by overwriting p); otherwise p is untouched void freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, - Geom::Point &p, - Inkscape::SnapSourceType const source_type, - bool first_point = true, - Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; + Geom::Point &p, + Inkscape::SnapSourceType const source_type, + long source_num = 0, + Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; Inkscape::SnappedPoint freeSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::SnapSourceType const &source_type, - bool first_point = true, + Geom::Point const &p, + Inkscape::SnapSourceType const &source_type, + long source_num = 0, Geom::OptRect const &bbox_to_snap = Geom::OptRect() ) const; Geom::Point multipleOfGridPitch(Geom::Point const &t) const; @@ -98,17 +98,17 @@ public: // constrainedSnapReturnByRef() is preferred over constrainedSnap(), because it only returns a // point, by overwriting p, if snapping has occurred; otherwise p is untouched void constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, - Geom::Point &p, - Inkscape::SnapSourceType const source_type, - Inkscape::Snapper::ConstraintLine const &constraint, - bool first_point = true, - Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; + Geom::Point &p, + Inkscape::SnapSourceType const source_type, + Inkscape::Snapper::ConstraintLine const &constraint, + long source_num = 0, + Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; Inkscape::SnappedPoint constrainedSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::SnapSourceType const &source_type, - Inkscape::Snapper::ConstraintLine const &constraint, - bool first_point = true, + Geom::Point const &p, + Inkscape::SnapSourceType const &source_type, + Inkscape::Snapper::ConstraintLine const &constraint, + long source_num = 0, Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; void guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SPGuideDragType drag_type) const; diff --git a/src/snapped-curve.cpp b/src/snapped-curve.cpp index 4da2d4c7d..334038638 100644 --- a/src/snapped-curve.cpp +++ b/src/snapped-curve.cpp @@ -12,7 +12,7 @@ #include <2geom/crossing.h> #include <2geom/path-intersection.h> -Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, SnapTargetType target) +Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, long source_num, SnapTargetType target) { _distance = snapped_distance; _tolerance = std::max(snapped_tolerance, 1.0); @@ -25,6 +25,7 @@ Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, Geom::Coo _at_intersection = false; _fully_constrained = fully_constrained; _source = source; + _source_num = source_num; _target = target; } @@ -41,6 +42,7 @@ Inkscape::SnappedCurve::SnappedCurve() _at_intersection = false; _fully_constrained = false; _source = SNAPSOURCE_UNDEFINED; + _source_num = 0; _target = SNAPTARGET_UNDEFINED; } @@ -83,12 +85,12 @@ Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &cur // TODO: Investigate whether it is possible to use document coordinates everywhere // in the snapper code. Only the mouse position should be in desktop coordinates, I guess. // All paths are already in document coords and we are certainly not going to change THAT. - return SnappedPoint(best_p, Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_PATH_INTERSECTION, primaryDist, primaryC->getTolerance(), primaryC->getAlwaysSnap(), true, true, + return SnappedPoint(best_p, Inkscape::SNAPSOURCE_UNDEFINED, primaryC->getSourceNum(), Inkscape::SNAPTARGET_PATH_INTERSECTION, primaryDist, primaryC->getTolerance(), primaryC->getAlwaysSnap(), true, true, secondaryDist, secondaryC->getTolerance(), secondaryC->getAlwaysSnap()); } // No intersection - return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); } // search for the closest snapped line diff --git a/src/snapped-curve.h b/src/snapped-curve.h index 0a1fe2431..4eea6e734 100644 --- a/src/snapped-curve.h +++ b/src/snapped-curve.h @@ -24,7 +24,7 @@ class SnappedCurve : public SnappedPoint { public: SnappedCurve(); - SnappedCurve(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, SnapTargetType target); + SnappedCurve(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, long source_num, SnapTargetType target); ~SnappedCurve(); Inkscape::SnappedPoint intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Matrix dt2doc) const; //intersect with another SnappedCurve diff --git a/src/snapped-line.cpp b/src/snapped-line.cpp index 3ebbeaf70..9dde22a4e 100644 --- a/src/snapped-line.cpp +++ b/src/snapped-line.cpp @@ -11,12 +11,13 @@ #include "snapped-line.h" #include <2geom/line.h> -Inkscape::SnappedLineSegment::SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line) +Inkscape::SnappedLineSegment::SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line) : _start_point_of_line(start_point_of_line), _end_point_of_line(end_point_of_line) { _point = snapped_point; _source = source; - _target = target; + _source_num = source_num; + _target = target; _distance = snapped_distance; _tolerance = std::max(snapped_tolerance, 1.0); _always_snap = always_snap; @@ -32,7 +33,8 @@ Inkscape::SnappedLineSegment::SnappedLineSegment() _end_point_of_line = Geom::Point(0,0); _point = Geom::Point(0,0); _source = SNAPSOURCE_UNDEFINED; - _target = SNAPTARGET_UNDEFINED; + _source_num = 0; + _target = SNAPTARGET_UNDEFINED; _distance = NR_HUGE; _tolerance = 1; _always_snap = false; @@ -50,19 +52,19 @@ Inkscape::SnappedLineSegment::~SnappedLineSegment() Inkscape::SnappedPoint Inkscape::SnappedLineSegment::intersect(SnappedLineSegment const &line) const { Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default - try - { - inters = Geom::intersection(getLineSegment(), line.getLineSegment()); - } - catch (Geom::InfiniteSolutions e) - { - // We're probably dealing with parallel lines, so they don't really cross - inters = Geom::OptCrossing(); - } + try + { + inters = Geom::intersection(getLineSegment(), line.getLineSegment()); + } + catch (Geom::InfiniteSolutions e) + { + // We're probably dealing with parallel lines, so they don't really cross + inters = Geom::OptCrossing(); + } if (inters) { Geom::Point inters_pt = getLineSegment().pointAt((*inters).ta); - /* If a snapper has been told to "always snap", then this one should be preferred + /* If a snapper has been told to "always snap", then this one should be preferred * over the other, if that other one has not been told so. (The preferred snapper * will be labeled "primary" below) */ @@ -78,22 +80,23 @@ Inkscape::SnappedPoint Inkscape::SnappedLineSegment::intersect(SnappedLineSegmen Inkscape::SnappedLineSegment const *secondarySLS = use_this_as_primary ? &line : this; Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(inters_pt - this->getPoint()) : Geom::L2(inters_pt - line.getPoint()); Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(inters_pt - line.getPoint()) : Geom::L2(inters_pt - this->getPoint()); - return SnappedPoint(inters_pt, SNAPSOURCE_UNDEFINED, SNAPTARGET_PATH_INTERSECTION, primaryDist, primarySLS->getTolerance(), primarySLS->getAlwaysSnap(), true, true, + return SnappedPoint(inters_pt, SNAPSOURCE_UNDEFINED, primarySLS->getSourceNum(), SNAPTARGET_PATH_INTERSECTION, primaryDist, primarySLS->getTolerance(), primarySLS->getAlwaysSnap(), true, true, secondaryDist, secondarySLS->getTolerance(), secondarySLS->getAlwaysSnap()); } // No intersection - return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); }; -Inkscape::SnappedLine::SnappedLine(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &normal_to_line, Geom::Point const &point_on_line) +Inkscape::SnappedLine::SnappedLine(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &normal_to_line, Geom::Point const &point_on_line) : _normal_to_line(normal_to_line), _point_on_line(point_on_line) { - _source = source; - _target = target; - _distance = snapped_distance; + _source = source; + _source_num = source_num; + _target = target; + _distance = snapped_distance; _tolerance = std::max(snapped_tolerance, 1.0); _always_snap = always_snap; _second_distance = NR_HUGE; @@ -108,7 +111,8 @@ Inkscape::SnappedLine::SnappedLine() _normal_to_line = Geom::Point(0,0); _point_on_line = Geom::Point(0,0); _source = SNAPSOURCE_UNDEFINED; - _target = SNAPTARGET_UNDEFINED; + _source_num = 0; + _target = SNAPTARGET_UNDEFINED; _distance = NR_HUGE; _tolerance = 1; _always_snap = false; @@ -130,19 +134,19 @@ Inkscape::SnappedPoint Inkscape::SnappedLine::intersect(SnappedLine const &line) // The point of intersection should be considered for snapping, but might be outside the snapping range Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default - try - { - inters = Geom::intersection(getLine(), line.getLine()); - } - catch (Geom::InfiniteSolutions e) - { - // We're probably dealing with parallel lines, so they don't really cross - inters = Geom::OptCrossing(); - } + try + { + inters = Geom::intersection(getLine(), line.getLine()); + } + catch (Geom::InfiniteSolutions e) + { + // We're probably dealing with parallel lines, so they don't really cross + inters = Geom::OptCrossing(); + } if (inters) { - Geom::Point inters_pt = getLine().pointAt((*inters).ta); - /* If a snapper has been told to "always snap", then this one should be preferred + Geom::Point inters_pt = getLine().pointAt((*inters).ta); + /* If a snapper has been told to "always snap", then this one should be preferred * over the other, if that other one has not been told so. (The preferred snapper * will be labelled "primary" below) */ @@ -157,14 +161,14 @@ Inkscape::SnappedPoint Inkscape::SnappedLine::intersect(SnappedLine const &line) Inkscape::SnappedLine const *secondarySL = use_this_as_primary ? &line : this; Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(inters_pt - this->getPoint()) : Geom::L2(inters_pt - line.getPoint()); Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(inters_pt - line.getPoint()) : Geom::L2(inters_pt - this->getPoint()); - return SnappedPoint(inters_pt, Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED, primaryDist, primarySL->getTolerance(), primarySL->getAlwaysSnap(), true, true, + return SnappedPoint(inters_pt, Inkscape::SNAPSOURCE_UNDEFINED, primarySL->getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, primaryDist, primarySL->getTolerance(), primarySL->getAlwaysSnap(), true, true, secondaryDist, secondarySL->getTolerance(), secondarySL->getAlwaysSnap()); // The type of the snap target is yet undefined, as we cannot tell whether // we're snapping to grid or the guide lines; must be set by on a higher level } // No intersection - return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, 0, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); } // search for the closest snapped line segment diff --git a/src/snapped-line.h b/src/snapped-line.h index 3dec432e7..b95e7a7df 100644 --- a/src/snapped-line.h +++ b/src/snapped-line.h @@ -23,7 +23,7 @@ class SnappedLineSegment : public SnappedPoint { public: SnappedLineSegment(); - SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance,bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line); + SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &snapped_tolerance,bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line); ~SnappedLineSegment(); Inkscape::SnappedPoint intersect(SnappedLineSegment const &line) const; //intersect with another SnappedLineSegment Geom::LineSegment getLineSegment() const {return Geom::LineSegment(_start_point_of_line, _end_point_of_line);} @@ -39,7 +39,7 @@ class SnappedLine : public SnappedPoint { public: SnappedLine(); - SnappedLine(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &normal_to_line, Geom::Point const &point_on_line); + SnappedLine(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &normal_to_line, Geom::Point const &point_on_line); ~SnappedLine(); Inkscape::SnappedPoint intersect(SnappedLine const &line) const; //intersect with another SnappedLine // This line is described by this equation: diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp index 2d028c6d7..102e761b9 100644 --- a/src/snapped-point.cpp +++ b/src/snapped-point.cpp @@ -14,8 +14,8 @@ #include "preferences.h" // overloaded constructor -Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained) - : _point(p), _source(source), _target(target), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a) +Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained) + : _point(p), _source(source), _source_num(source_num), _target(target), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a) { // tolerance should never be smaller than 1 px, as it is used for normalization in isOtherSnapBetter. We don't want a division by zero. _at_intersection = false; @@ -27,8 +27,8 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const _pointer_distance = NR_HUGE; } -Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2) - : _point(p), _source(source), _target(target), _at_intersection(at_intersection), _fully_constrained(fully_constrained), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a), +Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2) + : _point(p), _source(source), _source_num(source_num), _target(target), _at_intersection(at_intersection), _fully_constrained(fully_constrained), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a), _second_distance(d2), _second_tolerance(std::max(t2,1.0)), _second_always_snap(a2) { // tolerance should never be smaller than 1 px, as it is used for normalization in @@ -41,6 +41,7 @@ Inkscape::SnappedPoint::SnappedPoint() { _point = Geom::Point(0,0); _source = SNAPSOURCE_UNDEFINED, + _source_num = 0, _target = SNAPTARGET_UNDEFINED, _at_intersection = false; _fully_constrained = false; @@ -73,7 +74,7 @@ bool getClosestSP(std::list &list, Inkscape::SnappedPoin bool success = false; for (std::list::const_iterator i = list.begin(); i != list.end(); i++) { - if ((i == list.begin()) || (*i).getSnapDistance() < result.getSnapDistance()) { + if ((i == list.begin()) || (*i).getSnapDistance() < result.getSnapDistance()) { result = *i; success = true; } @@ -93,9 +94,9 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth // (both the snap distance and the pointer distance are measured in document pixels, not in screen pixels) if (weighted) { - Geom::Coord const dist_pointer_other = other_one.getPointerDistance(); - Geom::Coord const dist_pointer_this = getPointerDistance(); - // Weight factor: controls which node should be preferred for snapping, which is either + Geom::Coord const dist_pointer_other = other_one.getPointerDistance(); + Geom::Coord const dist_pointer_this = getPointerDistance(); + // Weight factor: controls which node should be preferred for snapping, which is either // the node with the closest snap (w = 0), or the node closest to the mousepointer (w = 1) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); double w = prefs->getDoubleLimited("/options/snapweight/value", 0.5, 0, 1); @@ -103,21 +104,21 @@ bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &oth w = 1; } if (w > 0) { - if (!(w == 1 && dist_pointer_this == dist_pointer_other)) { - // When accounting for the distance to the mouse pointer, then at least one of the snapped points should - // have that distance set. If not, then this is a bug. Either "weighted" must be set to false, or the - // mouse pointer distance must be set. - g_assert(dist_pointer_this != NR_HUGE || dist_pointer_other != NR_HUGE); - // The snap distance will always be smaller than the tolerance set for the snapper. The pointer distance can - // however be very large. To compare these in a fair way, we will have to normalize these metrics first - // The closest pointer distance will be normalized to 1.0; the other one will be > 1.0 - // The snap distance will be normalized to 1.0 if it's equal to the snapper tolerance - double const norm_p = std::min(dist_pointer_this, dist_pointer_other); - double const norm_t_other = std::min(50.0, other_one.getTolerance()); - double const norm_t_this = std::min(50.0, getTolerance()); - dist_other = w * dist_pointer_other / norm_p + (1-w) * dist_other / norm_t_other; - dist_this = w * dist_pointer_this / norm_p + (1-w) * dist_this / norm_t_this; - } + if (!(w == 1 && dist_pointer_this == dist_pointer_other)) { + // When accounting for the distance to the mouse pointer, then at least one of the snapped points should + // have that distance set. If not, then this is a bug. Either "weighted" must be set to false, or the + // mouse pointer distance must be set. + g_assert(dist_pointer_this != NR_HUGE || dist_pointer_other != NR_HUGE); + // The snap distance will always be smaller than the tolerance set for the snapper. The pointer distance can + // however be very large. To compare these in a fair way, we will have to normalize these metrics first + // The closest pointer distance will be normalized to 1.0; the other one will be > 1.0 + // The snap distance will be normalized to 1.0 if it's equal to the snapper tolerance + double const norm_p = std::min(dist_pointer_this, dist_pointer_other); + double const norm_t_other = std::min(50.0, other_one.getTolerance()); + double const norm_t_this = std::min(50.0, getTolerance()); + dist_other = w * dist_pointer_other / norm_p + (1-w) * dist_other / norm_t_other; + dist_this = w * dist_pointer_this / norm_p + (1-w) * dist_this / norm_t_this; + } } } diff --git a/src/snapped-point.h b/src/snapped-point.h index 70d16b0be..70d353a73 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -78,8 +78,8 @@ class SnappedPoint public: SnappedPoint(); - SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2); - SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained); + SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2); + SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained); ~SnappedPoint(); Geom::Coord getSnapDistance() const {return _distance;} @@ -115,13 +115,15 @@ public: void setTarget(SnapTargetType const target) {_target = target;} SnapTargetType getTarget() const {return _target;} void setSource(SnapSourceType const source) {_source = source;} - SnapSourceType getSource() const {return _source;} + SnapSourceType getSource() const {return _source;} + long getSourceNum() const {return _source_num;} bool isOtherSnapBetter(SnappedPoint const &other_one, bool weighted) const; /*void dump() const { std::cout << "_point = " << _point << std::endl; std::cout << "_source = " << _source << std::endl; + std::cout << "_source_num = " << _source_num << std::endl; std::cout << "_target = " << _target << std::endl; std::cout << "_at_intersection = " << _at_intersection << std::endl; std::cout << "_fully_constrained = " << _fully_constrained << std::endl; @@ -138,6 +140,7 @@ public: protected: Geom::Point _point; // Location of the snapped point SnapSourceType _source; // Describes what snapped + long _source_num; // Sequence number of the source point that snapped, if that point is part of a set of points. (starting at zero) SnapTargetType _target; // Describes to what we've snapped to bool _at_intersection; // If true, the snapped point is at an intersection bool _fully_constrained; // When snapping for example to a node, then the snap will be "fully constrained". @@ -153,7 +156,7 @@ protected: bool _always_snap; /* If the snapped point is at an intersection of e.g. two lines, then this is - the distance to the fartest line */ + the distance to the farthest line */ Geom::Coord _second_distance; /* The snapping tolerance in screen pixels (depends on zoom)*/ Geom::Coord _second_tolerance; diff --git a/src/snapper.h b/src/snapper.h index 110b3d36a..93756f7af 100644 --- a/src/snapper.h +++ b/src/snapper.h @@ -39,9 +39,9 @@ namespace Inkscape class Snapper { public: - Snapper() {} - Snapper(SnapManager *sm, ::Geom::Coord const t); - virtual ~Snapper() {} + Snapper() {} + Snapper(SnapManager *sm, ::Geom::Coord const t); + virtual ~Snapper() {} virtual Geom::Coord getSnapperTolerance() const = 0; //returns the tolerance of the snapper in screen pixels (i.e. independent of zoom) virtual bool getSnapperAlwaysSnap() const = 0; //if true, then the snapper will always snap, regardless of its tolerance @@ -53,7 +53,7 @@ public: // These four methods are only used for grids, for which snapping can be enabled individually void setEnabled(bool s); - void setSnapVisibleOnly(bool s); + void setSnapVisibleOnly(bool s); bool getEnabled() const {return _snap_enabled;} bool getSnapVisibleOnly() const {return _snap_visible_only;} @@ -61,7 +61,7 @@ public: SnapPreferences::PointType const &/*t*/, Geom::Point const &/*p*/, SnapSourceType const &/*source_type*/, - bool const &/*first_point*/, + long source_num, Geom::OptRect const &/*bbox_to_snap*/, std::vector const */*it*/, std::vector > */*unselected_nodes*/) const {}; @@ -90,9 +90,9 @@ public: } Geom::Point projection(Geom::Point const &p) const { // returns the projection of p on this constraintline - Geom::Point const p1_on_cl = _has_point ? _point : p; - Geom::Point const p2_on_cl = p1_on_cl + _direction; - return Geom::projection(p, Geom::Line(p1_on_cl, p2_on_cl)); + Geom::Point const p1_on_cl = _has_point ? _point : p; + Geom::Point const p2_on_cl = p1_on_cl + _direction; + return Geom::projection(p, Geom::Line(p1_on_cl, p2_on_cl)); } private: @@ -103,20 +103,20 @@ public: }; virtual void constrainedSnap(SnappedConstraints &/*sc*/, - SnapPreferences::PointType const &/*t*/, + SnapPreferences::PointType const &/*t*/, Geom::Point const &/*p*/, SnapSourceType const &/*source_type*/, - bool const &/*first_point*/, + long source_num, Geom::OptRect const &/*bbox_to_snap*/, ConstraintLine const &/*c*/, std::vector const */*it*/) const {}; protected: - SnapManager *_snapmanager; + SnapManager *_snapmanager; - // This is only used for grids, for which snapping can be enabled individually - bool _snap_enabled; ///< true if this snapper is enabled, otherwise false - bool _snap_visible_only; + // This is only used for grids, for which snapping can be enabled individually + bool _snap_enabled; ///< true if this snapper is enabled, otherwise false + bool _snap_visible_only; }; } -- 2.30.2