From c123991dbc3ceab027b9e876e848c41833140318 Mon Sep 17 00:00:00 2001 From: dvlierop2 Date: Fri, 13 Mar 2009 20:15:31 +0000 Subject: [PATCH] * Implement constrained snapping of knots * Implement snapping of the rectangle's radius handles * Line snappers: set the snap target in the derived class instead of in findBestSnap() --- src/display/canvas-axonomgrid.cpp | 10 ++++++++-- src/display/canvas-axonomgrid.h | 3 ++- src/display/canvas-grid.cpp | 10 ++++++++-- src/display/canvas-grid.h | 3 ++- src/guide-snapper.cpp | 10 ++++++++-- src/guide-snapper.h | 3 ++- src/knot-holder-entity.cpp | 12 ++++++++++++ src/knot-holder-entity.h | 10 ++++++---- src/line-snapper.cpp | 5 ++--- src/line-snapper.h | 3 ++- src/object-edit.cpp | 15 +++++++++------ src/snap.cpp | 2 -- src/snapped-point.h | 2 +- 13 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index ea5393d39..9c6126b7c 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -757,12 +757,18 @@ 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, SnapTargetType const &target, 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, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, target, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, 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 +{ + SnappedPoint dummy = SnappedPoint(snapped_point, source, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + sc.points.push_back(dummy); +} + bool CanvasAxonomGridSnapper::ThisSnapperMightSnap() const { return _snap_enabled && _snapmanager->snapprefs.getSnapToGrids() && _snapmanager->snapprefs.getSnapModeBBoxOrNodes(); diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h index ecbd846a1..e36804d7c 100644 --- a/src/display/canvas-axonomgrid.h +++ b/src/display/canvas-axonomgrid.h @@ -78,7 +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, SnapTargetType const &target, Geom::Point const normal_to_line, const Geom::Point point_on_line) 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; CanvasAxonomGrid *grid; }; diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 3e7295b90..c971382b4 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -1003,12 +1003,18 @@ 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, SnapTargetType const &target, 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, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, target, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, 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 +{ + SnappedPoint dummy = SnappedPoint(snapped_point, source, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + sc.points.push_back(dummy); +} + /** * \return true if this Snapper will snap at least one kind of point. */ diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index 37e30fab0..750fef1b0 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -166,7 +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, SnapTargetType const &target, Geom::Point const normal_to_line, const Geom::Point point_on_line) 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; CanvasXYGrid *grid; }; diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp index 989dec16b..7ee35255f 100644 --- a/src/guide-snapper.cpp +++ b/src/guide-snapper.cpp @@ -70,12 +70,18 @@ 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, SnapTargetType const &target, 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, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, target, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, Inkscape::SNAPTARGET_GUIDE, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); sc.guide_lines.push_back(dummy); } +void Inkscape::GuideSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const +{ + SnappedPoint dummy = SnappedPoint(snapped_point, source, Inkscape::SNAPTARGET_GUIDE, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + sc.points.push_back(dummy); +} + /* Local Variables: mode:c++ diff --git a/src/guide-snapper.h b/src/guide-snapper.h index 8b59194e8..239e8b050 100644 --- a/src/guide-snapper.h +++ b/src/guide-snapper.h @@ -36,7 +36,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, SnapTargetType const &target, Geom::Point const normal_to_line, Geom::Point const point_on_line) 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 _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const; }; } diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp index df58d356a..4225dd9e3 100644 --- a/src/knot-holder-entity.cpp +++ b/src/knot-holder-entity.cpp @@ -97,6 +97,18 @@ KnotHolderEntity::snap_knot_position(Geom::Point const &p) return s * i2d.inverse(); } +Geom::Point +KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::ConstraintLine const &constraint) +{ + Geom::Matrix const i2d (sp_item_i2d_affine(item)); + Geom::Point s = p * i2d; + Inkscape::Snapper::ConstraintLine transformed_constraint = Inkscape::Snapper::ConstraintLine(constraint.getPoint() * i2d, (constraint.getPoint() + constraint.getDirection()) * i2d - constraint.getPoint() * i2d); + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop, true, item); + m.constrainedSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, s, Inkscape::SNAPSOURCE_HANDLE, transformed_constraint); + return s * i2d.inverse(); +} + /* Pattern manipulation */ diff --git a/src/knot-holder-entity.h b/src/knot-holder-entity.h index 1f5ea8e2c..c8fd29ddf 100644 --- a/src/knot-holder-entity.h +++ b/src/knot-holder-entity.h @@ -1,9 +1,9 @@ #ifndef SEEN_KNOT_HOLDER_ENTITY_H #define SEEN_KNOT_HOLDER_ENTITY_H -/** \file - * KnotHolderEntity definition. - * +/** \file + * KnotHolderEntity definition. + * * Authors: * Mitsuru Oka * Maximilian Albert @@ -20,6 +20,7 @@ #include #include "knot.h" #include <2geom/forward.h> +#include "snapper.h" struct SPItem; struct SPKnot; @@ -36,7 +37,7 @@ class KnotHolderEntity { public: KnotHolderEntity() {} virtual ~KnotHolderEntity(); - virtual void create(SPDesktop *desktop, SPItem *item, KnotHolder *parent, const gchar *tip = "", + virtual void create(SPDesktop *desktop, SPItem *item, KnotHolder *parent, const gchar *tip = "", SPKnotShapeType shape = SP_KNOT_SHAPE_DIAMOND, SPKnotModeType mode = SP_KNOT_MODE_XOR, guint32 color = 0xffffff00); @@ -57,6 +58,7 @@ public: //private: Geom::Point snap_knot_position(Geom::Point const &p); + Geom::Point snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::ConstraintLine const &constraint); SPKnot *knot; SPItem *item; diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index d751993dd..72a6cc33d 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -51,8 +51,7 @@ 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, Inkscape::SNAPTARGET_UNDEFINED, i->first, i->second); - // We don't know if we're snapping to grids or guides here; therefore the snap target type will be set in findBestSnap() + _addSnappedLine(sc, p_proj, dist, source_type, i->first, i->second); // std::cout << " -> distance = " << dist; } // std::cout << std::endl; @@ -100,7 +99,7 @@ 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 - sc.points.push_back(SnappedPoint(t, source_type, Inkscape::SNAPTARGET_UNDEFINED, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true)); + _addSnappedPoint(sc, t, dist, source_type); } } } diff --git a/src/line-snapper.h b/src/line-snapper.h index 3a7ed6aae..4c971d238 100644 --- a/src/line-snapper.h +++ b/src/line-snapper.h @@ -54,7 +54,8 @@ 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, SnapTargetType const &target, 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, Geom::Point const normal_to_line, Geom::Point const point_on_line) const = 0; + virtual void _addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const = 0; }; } diff --git a/src/object-edit.cpp b/src/object-edit.cpp index a9cf20298..0719a59d3 100644 --- a/src/object-edit.cpp +++ b/src/object-edit.cpp @@ -141,14 +141,15 @@ RectKnotHolderEntityRX::knot_set(Geom::Point const &p, Geom::Point const &/*orig //In general we cannot just snap this radius to an arbitrary point, as we have only a single //degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap //the radius then we should have a constrained snap. snap_knot_position() is unconstrained + Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(-1, 0))); if (state & GDK_CONTROL_MASK) { gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0; - rect->rx.computed = rect->ry.computed = CLAMP(rect->x.computed + rect->width.computed - p[Geom::X], 0.0, temp); + rect->rx.computed = rect->ry.computed = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, temp); rect->rx._set = rect->ry._set = true; } else { - rect->rx.computed = CLAMP(rect->x.computed + rect->width.computed - p[Geom::X], 0.0, rect->width.computed / 2.0); + rect->rx.computed = CLAMP(rect->x.computed + rect->width.computed - s[Geom::X], 0.0, rect->width.computed / 2.0); rect->rx._set = true; } @@ -190,18 +191,20 @@ RectKnotHolderEntityRY::knot_set(Geom::Point const &p, Geom::Point const &/*orig //In general we cannot just snap this radius to an arbitrary point, as we have only a single //degree of freedom. For snapping to an arbitrary point we need two DOF. If we're going to snap //the radius then we should have a constrained snap. snap_knot_position() is unconstrained + Geom::Point const s = snap_knot_position_constrained(p, Inkscape::Snapper::ConstraintLine(Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed), Geom::Point(0, 1))); - if (state & GDK_CONTROL_MASK) { + if (state & GDK_CONTROL_MASK) { // When holding control then rx will be kept equal to ry, + // resulting in a perfect circle (and not an ellipse) gdouble temp = MIN(rect->height.computed, rect->width.computed) / 2.0; - rect->rx.computed = rect->ry.computed = CLAMP(p[Geom::Y] - rect->y.computed, 0.0, temp); + rect->rx.computed = rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, temp); rect->ry._set = rect->rx._set = true; } else { if (!rect->rx._set || rect->rx.computed == 0) { - rect->ry.computed = CLAMP(p[Geom::Y] - rect->y.computed, + rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, MIN(rect->height.computed / 2.0, rect->width.computed / 2.0)); } else { - rect->ry.computed = CLAMP(p[Geom::Y] - rect->y.computed, + rect->ry.computed = CLAMP(s[Geom::Y] - rect->y.computed, 0.0, rect->height.computed / 2.0); } diff --git a/src/snap.cpp b/src/snap.cpp index f6dceedba..130742483 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -814,14 +814,12 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, Inkscape: // search for the closest snapped grid line Inkscape::SnappedLine closestGridLine; if (getClosestSL(sc.grid_lines, closestGridLine)) { - closestGridLine.setTarget(Inkscape::SNAPTARGET_GRID); sp_list.push_back(Inkscape::SnappedPoint(closestGridLine)); } // search for the closest snapped guide line Inkscape::SnappedLine closestGuideLine; if (getClosestSL(sc.guide_lines, closestGuideLine)) { - closestGuideLine.setTarget(Inkscape::SNAPTARGET_GUIDE); sp_list.push_back(Inkscape::SnappedPoint(closestGuideLine)); } diff --git a/src/snapped-point.h b/src/snapped-point.h index c0209c09d..4f27c3be0 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -99,7 +99,7 @@ public: void getPoint(Geom::Point &p) const; /* This method however always returns a point, even if no snapping - * has occured; A check should be implemented in the calling code + * has occurred; A check should be implemented in the calling code * to check for snapping. Use this method only when really needed, e.g. * when the calling code is trying to snap multiple points and must * determine itself which point is most appropriate -- 2.30.2