summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDiederik van Lierop <mail@diedenrezi.nl>2012-02-14 20:56:34 +0000
committerDiederik van Lierop <mail@diedenrezi.nl>2012-02-14 20:56:34 +0000
commite182d3546498c8c865fb155481890c5571430c6f (patch)
tree3ea9d416ab9610220a3e11fbdae0f62c1ba91741 /src
parentUpdate Authors & Translators lists in About dialog (diff)
downloadinkscape-e182d3546498c8c865fb155481890c5571430c6f.tar.gz
inkscape-e182d3546498c8c865fb155481890c5571430c6f.zip
1) Add checkboxes for perpendicular and tangential snapping to the document properties dialog (on the snap tab)
2) Newly created guides (dragged off the ruler) will take on the angle of the curve that's being snapped to (either perpendicularly or tangentialy, depending of the settings in the document properties dialog) (bzr r10975)
Diffstat (limited to 'src')
-rw-r--r--src/attributes-test.h2
-rw-r--r--src/attributes.cpp2
-rw-r--r--src/attributes.h2
-rw-r--r--src/desktop-events.cpp67
-rw-r--r--src/object-snapper.cpp13
-rw-r--r--src/snap-candidate.h4
-rw-r--r--src/snap-preferences.cpp11
-rw-r--r--src/snap-preferences.h8
-rw-r--r--src/snap.cpp30
-rw-r--r--src/snap.h10
-rw-r--r--src/snapped-curve.cpp4
-rw-r--r--src/snapped-curve.h2
-rw-r--r--src/snapped-point.cpp5
-rw-r--r--src/snapped-point.h2
-rw-r--r--src/sp-namedview.cpp10
-rw-r--r--src/ui/dialog/document-properties.cpp12
-rw-r--r--src/ui/dialog/document-properties.h2
17 files changed, 138 insertions, 48 deletions
diff --git a/src/attributes-test.h b/src/attributes-test.h
index ec2b0c6af..5a036fd41 100644
--- a/src/attributes-test.h
+++ b/src/attributes-test.h
@@ -342,6 +342,8 @@ struct {char const *attr; bool supported;} const all_attrs[] = {
{"sodipodi:version", false},
{"inkscape:version", true},
{"inkscape:object-paths", true},
+ {"inkscape:snap-perpendicular", true},
+ {"inkscape:snap-tangential", true},
{"inkscape:snap-path-clip", true},
{"inkscape:snap-path-mask", true},
{"inkscape:object-nodes", true},
diff --git a/src/attributes.cpp b/src/attributes.cpp
index 9203d916b..87cc0488c 100644
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
@@ -91,6 +91,8 @@ static SPStyleProp const props[] = {
{SP_ATTR_INKSCAPE_WINDOW_Y, "inkscape:window-y"},
{SP_ATTR_INKSCAPE_WINDOW_MAXIMIZED, "inkscape:window-maximized"},
{SP_ATTR_INKSCAPE_SNAP_GLOBAL, "inkscape:snap-global"},
+ {SP_ATTR_INKSCAPE_SNAP_PERP, "inkscape:snap-perpendicular"},
+ {SP_ATTR_INKSCAPE_SNAP_TANG, "inkscape:snap-tangential"},
{SP_ATTR_INKSCAPE_SNAP_BBOX, "inkscape:snap-bbox"},
{SP_ATTR_INKSCAPE_SNAP_NODE, "inkscape:snap-nodes"},
{SP_ATTR_INKSCAPE_SNAP_OTHERS, "inkscape:snap-others"},
diff --git a/src/attributes.h b/src/attributes.h
index 8c7955a77..c78882cbf 100644
--- a/src/attributes.h
+++ b/src/attributes.h
@@ -91,6 +91,8 @@ enum SPAttributeEnum {
SP_ATTR_INKSCAPE_WINDOW_Y,
SP_ATTR_INKSCAPE_WINDOW_MAXIMIZED,
SP_ATTR_INKSCAPE_SNAP_GLOBAL,
+ SP_ATTR_INKSCAPE_SNAP_PERP,
+ SP_ATTR_INKSCAPE_SNAP_TANG,
SP_ATTR_INKSCAPE_SNAP_BBOX,
SP_ATTR_INKSCAPE_SNAP_NODE,
SP_ATTR_INKSCAPE_SNAP_OTHERS,
diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index 923b15a88..ec9dbcea3 100644
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
@@ -50,6 +50,7 @@ using Inkscape::DocumentUndo;
static void snoop_extended(GdkEvent* event, SPDesktop *desktop);
static void init_extended();
+void sp_dt_ruler_snap_new_guide(SPDesktop *desktop, SPCanvasItem *guide, Geom::Point &event_dt, Geom::Point &normal);
/* Root item handler */
@@ -149,16 +150,11 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
Geom::Point event_dt(desktop->w2d(event_w));
if (!(event->motion.state & GDK_SHIFT_MASK)) {
- SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
- // We only have a temporary guide which is not stored in our document yet.
- // Because the guide snapper only looks in the document for guides to snap to,
- // we don't have to worry about a guide snapping to itself here
- m.guideFreeSnap(event_dt, SP_DRAG_MOVE_ORIGIN, Geom::rot90(normal));
- m.unSetup();
+ sp_dt_ruler_snap_new_guide(desktop, guide, event_dt, normal);
}
-
+ sp_guideline_set_normal(SP_GUIDELINE(guide), normal);
sp_guideline_set_position(SP_GUIDELINE(guide), event_dt);
+
desktop->set_coordinate_status(event_dt);
desktop->setPosition(event_dt);
}
@@ -172,13 +168,7 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
Geom::Point event_dt(desktop->w2d(event_w));
if (!(event->button.state & GDK_SHIFT_MASK)) {
- SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
- // We only have a temporary guide which is not stored in our document yet.
- // Because the guide snapper only looks in the document for guides to snap to,
- // we don't have to worry about a guide snapping to itself here
- m.guideFreeSnap(event_dt, SP_DRAG_MOVE_ORIGIN, Geom::rot90(normal));
- m.unSetup();
+ sp_dt_ruler_snap_new_guide(desktop, guide, event_dt, normal);
}
dragging = false;
@@ -305,8 +295,11 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
}
} else if (!((drag_type == SP_DRAG_ROTATE) && (event->motion.state & GDK_CONTROL_MASK))) {
// cannot use shift here to disable snapping, because we already use it for rotating the guide
- Geom::Point origin = (drag_type == SP_DRAG_ROTATE) ? guide->point_on_line : Geom::rot90(guide->normal_to_line);
- m.guideFreeSnap(motion_dt, drag_type, origin);
+ if (drag_type == SP_DRAG_ROTATE) {
+ m.guideFreeSnap(motion_dt, guide->point_on_line, true, false);
+ } else {
+ m.guideFreeSnap(motion_dt, guide->normal_to_line, false, true);
+ }
}
m.unSetup();
@@ -379,8 +372,11 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
}
} else if (!((drag_type == SP_DRAG_ROTATE) && (event->motion.state & GDK_CONTROL_MASK))) {
// cannot use shift here to disable snapping, because we already use it for rotating the guide
- Geom::Point origin = (drag_type == SP_DRAG_ROTATE) ? guide->point_on_line : Geom::rot90(guide->normal_to_line);
- m.guideFreeSnap(event_dt, drag_type, origin);
+ if (drag_type == SP_DRAG_ROTATE) {
+ m.guideFreeSnap(event_dt, guide->point_on_line, true, false);
+ } else {
+ m.guideFreeSnap(event_dt, guide->normal_to_line, false, true);
+ }
}
m.unSetup();
@@ -661,6 +657,39 @@ void snoop_extended(GdkEvent* event, SPDesktop *desktop)
}
+void sp_dt_ruler_snap_new_guide(SPDesktop *desktop, SPCanvasItem *guide, Geom::Point &event_dt, Geom::Point &normal)
+{
+ SnapManager &m = desktop->namedview->snap_manager;
+ m.setup(desktop);
+ // We're dragging a brand new guide, just pulled of the rulers seconds ago. When snapping to a
+ // path this guide will change it slope to become either tangential or perpendicular to that path. It's
+ // therefore not useful to try tangential or perpendicular snapping, so this will be disabled temporarily
+ bool pref_perp = m.snapprefs.getSnapPerp();
+ bool pref_tang = m.snapprefs.getSnapTang();
+ m.snapprefs.setSnapPerp(false);
+ m.snapprefs.setSnapTang(false);
+ // We only have a temporary guide which is not stored in our document yet.
+ // Because the guide snapper only looks in the document for guides to snap to,
+ // we don't have to worry about a guide snapping to itself here
+ Geom::Point normal_orig = normal;
+ m.guideFreeSnap(event_dt, normal, false, false);
+ // After snapping, both event_dt and normal have been modified accordingly; we'll take the normal (of the
+ // curve we snapped to) to set the normal the guide. And rotate it by 90 deg. if needed
+ if (pref_perp) { // Perpendicular snapping to paths is requested by the user, so let's do that
+ if (normal != normal_orig) {
+ normal = Geom::rot90(normal);
+ }
+ }
+ if (!(pref_tang || pref_perp)) { // if we don't want to snap either perpendicularly or tangentially, then
+ normal = normal_orig; // we must restore the normal to it's original state
+ }
+ // Restore the preferences
+ m.snapprefs.setSnapPerp(pref_perp);
+ m.snapprefs.setSnapTang(pref_tang);
+ m.unSetup();
+}
+
+
/*
Local Variables:
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 1a4d79a7d..328f58e68 100644
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
@@ -499,8 +499,8 @@ void Inkscape::ObjectSnapper::_snapPaths(IntermSnapResults &isr,
// continue counting
bool strict_snapping = _snapmanager->snapprefs.getStrictSnapping();
- bool snap_perp = _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH_PERPENDICULAR);
- bool snap_tang = _snapmanager->snapprefs.isTargetSnappable(SNAPTARGET_PATH_TANGENTIAL);
+ bool snap_perp = _snapmanager->snapprefs.getSnapPerp();
+ bool snap_tang = _snapmanager->snapprefs.getSnapTang();
//dt->snapindicator->remove_debugging_points();
for (std::vector<SnapCandidatePath >::const_iterator it_p = _paths_to_snap_to->begin(); it_p != _paths_to_snap_to->end(); it_p++) {
@@ -549,7 +549,14 @@ void Inkscape::ObjectSnapper::_snapPaths(IntermSnapResults &isr,
// std::cout << " dist -> " << dist << std::endl;
if (dist < getSnapperTolerance()) {
// Add the curve we have snapped to
- isr.curves.push_back(SnappedCurve(sp_dt, num_path, index, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, curve, p.getSourceType(), p.getSourceNum(), it_p->target_type, it_p->target_bbox));
+ Geom::Point sp_tangent_dt = Geom::Point(0,0);
+ if (p.getSourceType() == Inkscape::SNAPSOURCE_GUIDE_ORIGIN) {
+ // We currently only use the tangent when snapping guides, so only in this case we will
+ // actually calculate the tangent to avoid wasting CPU cycles
+ Geom::Point sp_tangent_doc = curve->unitTangentAt(*np);
+ sp_tangent_dt = dt->doc2dt(sp_tangent_doc) - dt->doc2dt(Geom::Point(0,0));
+ }
+ isr.curves.push_back(SnappedCurve(sp_dt, sp_tangent_dt, num_path, index, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, curve, p.getSourceType(), p.getSourceNum(), it_p->target_type, it_p->target_bbox));
if (snap_tang || snap_perp) {
// For each curve that's within snapping range, we will now also search for tangential and perpendicular snaps
_snapPathsTangPerp(snap_tang, snap_perp, isr, p, curve, dt);
diff --git a/src/snap-candidate.h b/src/snap-candidate.h
index e97893c43..1c84cdbae 100644
--- a/src/snap-candidate.h
+++ b/src/snap-candidate.h
@@ -63,8 +63,8 @@ public:
void setDistance(Geom::Coord dist) {_dist = dist;}
Geom::Coord getDistance() { return _dist;}
- void addOrigin(Geom::Point &pt) { _origins_and_vectors.push_back(std::make_pair(pt, false)); }
- void addVector(Geom::Point &v) { _origins_and_vectors.push_back(std::make_pair(v, true)); }
+ void addOrigin(Geom::Point pt) { _origins_and_vectors.push_back(std::make_pair(pt, false)); }
+ void addVector(Geom::Point v) { _origins_and_vectors.push_back(std::make_pair(v, true)); }
std::vector<std::pair<Geom::Point, bool> > const & getOriginsAndVectors() const {return _origins_and_vectors;}
bool operator <(const SnapCandidatePoint &other) const { return _dist < other._dist; } // Needed for sorting the SnapCandidatePoints
diff --git a/src/snap-preferences.cpp b/src/snap-preferences.cpp
index 821073fb5..09924e3bc 100644
--- a/src/snap-preferences.cpp
+++ b/src/snap-preferences.cpp
@@ -16,7 +16,9 @@
Inkscape::SnapPreferences::SnapPreferences() :
_snap_enabled_globally(true),
_snap_postponed_globally(false),
- _strict_snapping(true)
+ _strict_snapping(true),
+ _snap_perp(false),
+ _snap_tang(false)
{
// Check for powers of two; see the comments in snap-enums.h
g_assert((SNAPTARGET_BBOX_CATEGORY != 0) && !(SNAPTARGET_BBOX_CATEGORY & (SNAPTARGET_BBOX_CATEGORY - 1)));
@@ -76,13 +78,6 @@ void Inkscape::SnapPreferences::_mapTargetToArrayIndex(Inkscape::SnapTargetType
default:
break;
}
- if (target == SNAPTARGET_RECT_CORNER) {
- target = SNAPTARGET_NODE_CUSP;
- } else if (target == SNAPTARGET_ELLIPSE_QUADRANT_POINT) {
- target = SNAPTARGET_NODE_SMOOTH;
- } else if (target == SNAPTARGET_PATH_GUIDE_INTERSECTION) {
- target = SNAPTARGET_PATH_INTERSECTION;
- }
return;
}
diff --git a/src/snap-preferences.h b/src/snap-preferences.h
index 71f6c1247..c2db0b432 100644
--- a/src/snap-preferences.h
+++ b/src/snap-preferences.h
@@ -45,6 +45,11 @@ public:
bool getStrictSnapping() const {return _strict_snapping;}
+ bool getSnapPerp() const {return _snap_perp;}
+ bool getSnapTang() const {return _snap_tang;}
+ void setSnapPerp(bool enabled) {_snap_perp = enabled;}
+ void setSnapTang(bool enabled) {_snap_tang = enabled;}
+
gdouble getGridTolerance() const {return _grid_tolerance;}
gdouble getGuideTolerance() const {return _guide_tolerance;}
gdouble getObjectTolerance() const {return _object_tolerance;}
@@ -84,6 +89,9 @@ private:
//(snapping to grids and guides is not affected by this)
bool _strict_snapping;
+ bool _snap_perp;
+ bool _snap_tang;
+
gdouble _grid_tolerance;
gdouble _guide_tolerance;
gdouble _object_tolerance;
diff --git a/src/snap.cpp b/src/snap.cpp
index f1197155b..4ca1ec476 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -10,7 +10,7 @@
*
* Copyright (C) 2006-2007 Johan Engelen <johan@shouraizou.nl>
* Copyrigth (C) 2004 Nathan Hurst
- * Copyright (C) 1999-2010 Authors
+ * Copyright (C) 1999-2012 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -391,22 +391,23 @@ Inkscape::SnappedPoint SnapManager::constrainedAngularSnap(Inkscape::SnapCandida
return sp;
}
-void SnapManager::guideFreeSnap(Geom::Point &p, SPGuideDragType drag_type, boost::optional<Geom::Point> origin_or_vector) const
+void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point &origin_or_vector, bool origin, bool freeze_angle) const
{
+ if (freeze_angle && origin) {
+ g_warning("Dear developer, when snapping guides you shouldn't ask me to freeze the guide's vector when you haven't specified one");
+ // You've supplied me with an origin instead of a vector
+ }
+
if (!snapprefs.getSnapEnabledGlobally() || snapprefs.getSnapPostponedGlobally() || !snapprefs.isTargetSnappable(Inkscape::SNAPTARGET_GUIDE)) {
return;
}
- Inkscape::SnapCandidatePoint candidate(p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN);
- if (drag_type == SP_DRAG_ROTATE) {
- candidate = Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_GUIDE);
- if (origin_or_vector) {
- candidate.addOrigin(*origin_or_vector);
- }
+ Inkscape::SnapCandidatePoint candidate(p, Inkscape::SNAPSOURCE_GUIDE);
+ if (origin) {
+ candidate.addOrigin(origin_or_vector);
} else {
- if (origin_or_vector) {
- candidate.addVector(*origin_or_vector);
- }
+ candidate = Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN);
+ candidate.addVector(Geom::rot90(origin_or_vector));
}
IntermSnapResults isr;
@@ -418,6 +419,13 @@ void SnapManager::guideFreeSnap(Geom::Point &p, SPGuideDragType drag_type, boost
Inkscape::SnappedPoint const s = findBestSnap(candidate, isr, false);
s.getPointIfSnapped(p);
+
+ if (!freeze_angle && s.getSnapped()) {
+ if (!Geom::are_near(s.getTangent(), Geom::Point(0,0))) { // If the tangent has been set ...
+ origin_or_vector = Geom::rot90(s.getTangent()); // then use it to update the normal of the guide
+ // PS: The tangent might not have been set if we snapped for example to a node
+ }
+ }
}
void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const
diff --git a/src/snap.h b/src/snap.h
index 8e7ab1872..3a8e18ad3 100644
--- a/src/snap.h
+++ b/src/snap.h
@@ -304,8 +304,14 @@ public:
* PS: SnapManager::setup() must have been called before calling this method,
*
* @param p Current position of the point on the guide that is to be snapped; will be overwritten by the position of the snap target if snapping has occurred.
+ * @param origin_or_vector Data used for tangential and perpendicular snapping. When rotating a guide the origin of the rotation is specified here, whereas when
+ * dragging a guide its vector is specified here
+ * @param origin If true then origin_or_vector contains an origin, other it contains a vector
+ * @param freeze_angle If true (in which case origin is false), then the vector specified in origin_or_vector will not be touched, i.e. the guide will
+ * in all circumstances keep its angle. Otherwise the vector in origin_or_vector can be updated, meaning that the guide might take on the angle of a curve that
+ * has been snapped too tangentially or perpendicularly
*/
- void guideFreeSnap(Geom::Point &p, SPGuideDragType drag_type, boost::optional<Geom::Point> origin_or_vector = boost::optional<Geom::Point>()) const;
+ void guideFreeSnap(Geom::Point &p, Geom::Point &origin_or_vector, bool origin, bool freeze_angle) const;
/**
* Wrapper method to make snapping of the guide origin a bit easier (i.e. simplifies the calling code).
@@ -313,10 +319,10 @@ public:
* PS: SnapManager::setup() must have been called before calling this method,
*
* @param p Current position of the point on the guide that is to be snapped; will be overwritten by the position of the snap target if snapping has occurred.
+ * @param guideline The guide that is currently being dragged
*/
void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const;
-
/**
* Apply a translation to a set of points and try to snap freely in 2 degrees-of-freedom.
*
diff --git a/src/snapped-curve.cpp b/src/snapped-curve.cpp
index 8fdf1d46f..b332fa8c1 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, int num_path, int num_segm, 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, Geom::OptRect target_bbox)
+Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, Geom::Point const &tangent, int num_path, int num_segm, 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, Geom::OptRect target_bbox)
{
_num_path = num_path;
_num_segm = num_segm;
@@ -24,6 +24,7 @@ Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, int num_p
_second_tolerance = 1;
_second_always_snap = false;
_point = snapped_point;
+ _tangent = tangent;
_at_intersection = false;
_fully_constrained = fully_constrained;
_source = source;
@@ -44,6 +45,7 @@ Inkscape::SnappedCurve::SnappedCurve()
_second_tolerance = 1;
_second_always_snap = false;
_point = Geom::Point(0,0);
+ _tangent = Geom::Point(0,0);
_at_intersection = false;
_fully_constrained = false;
_source = SNAPSOURCE_UNDEFINED;
diff --git a/src/snapped-curve.h b/src/snapped-curve.h
index 8b1080dc4..6bb8bfeca 100644
--- a/src/snapped-curve.h
+++ b/src/snapped-curve.h
@@ -25,7 +25,7 @@ class SnappedCurve : public SnappedPoint
{
public:
SnappedCurve();
- SnappedCurve(Geom::Point const &snapped_point, int num_path, int num_segm, 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, Geom::OptRect target_bbox);
+ SnappedCurve(Geom::Point const &snapped_point, Geom::Point const &tangent, int num_path, int num_segm, 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, Geom::OptRect target_bbox);
~SnappedCurve();
Inkscape::SnappedPoint intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Affine dt2doc) const; //intersect with another SnappedCurve
Inkscape::SnappedPoint intersect(SnappedLine const &line, Geom::Point const &p, Geom::Affine dt2doc) const; //intersect with a SnappedLine
diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp
index 72875995d..d155babd7 100644
--- a/src/snapped-point.cpp
+++ b/src/snapped-point.cpp
@@ -25,6 +25,7 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const
_second_tolerance = 1;
_second_always_snap = false;
_transformation = Geom::Point(1,1);
+ _tangent = Geom::Point(0,0);
_pointer_distance = Geom::infinity();
}
@@ -41,6 +42,7 @@ Inkscape::SnappedPoint::SnappedPoint(Inkscape::SnapCandidatePoint const &p, Snap
_second_tolerance = 1;
_second_always_snap = false;
_transformation = Geom::Point(1,1);
+ _tangent = Geom::Point(0,0);
_pointer_distance = Geom::infinity();
_target_bbox = p.getTargetBBox();
@@ -53,6 +55,7 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const
// tolerance should never be smaller than 1 px, as it is used for normalization in
// isOtherSnapBetter. We don't want a division by zero.
_transformation = Geom::Point(1,1);
+ _tangent = Geom::Point(0,0);
_pointer_distance = Geom::infinity();
_target_bbox = Geom::OptRect();
}
@@ -73,6 +76,7 @@ Inkscape::SnappedPoint::SnappedPoint()
_second_tolerance = 1;
_second_always_snap = false;
_transformation = Geom::Point(1,1);
+ _tangent = Geom::Point(0,0);
_pointer_distance = Geom::infinity();
_target_bbox = Geom::OptRect();
}
@@ -93,6 +97,7 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p)
_second_tolerance = 1;
_second_always_snap = false;
_transformation = Geom::Point(1,1);
+ _tangent = Geom::Point(0,0);
_pointer_distance = Geom::infinity();
_target_bbox = Geom::OptRect();
}
diff --git a/src/snapped-point.h b/src/snapped-point.h
index 7dc6edeca..7ab572e82 100644
--- a/src/snapped-point.h
+++ b/src/snapped-point.h
@@ -59,6 +59,7 @@ public:
*/
Geom::Point getPoint() const {return _point;}
void setPoint(Geom::Point const &p) {_point = p;}
+ Geom::Point getTangent() const {return _tangent;}
bool getAtIntersection() const {return _at_intersection;}
bool getFullyConstrained() const {return _fully_constrained;}
@@ -95,6 +96,7 @@ public:
protected:
Geom::Point _point; // Location of the snapped point
+ Geom::Point _tangent; // Tangent of the curve we snapped to, at 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 if we might have a set of points; -1 if we only have a single point)
SnapTargetType _target; // Describes to what we've snapped to
diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp
index ab525d368..a7d7c4b01 100644
--- a/src/sp-namedview.cpp
+++ b/src/sp-namedview.cpp
@@ -262,6 +262,8 @@ static void sp_namedview_build(SPObject *object, SPDocument *document, Inkscape:
object->readAttr( "inkscape:snap-grids" );
object->readAttr( "inkscape:snap-intersection-paths" );
object->readAttr( "inkscape:object-paths" );
+ object->readAttr( "inkscape:snap-perpendicular" );
+ object->readAttr( "inkscape:snap-tangential" );
object->readAttr( "inkscape:snap-path-clip" );
object->readAttr( "inkscape:snap-path-mask" );
object->readAttr( "inkscape:object-nodes" );
@@ -514,6 +516,14 @@ static void sp_namedview_set(SPObject *object, unsigned int key, const gchar *va
nv->snap_manager.snapprefs.setTargetSnappable(Inkscape::SNAPTARGET_PATH, value ? sp_str_to_bool(value) : FALSE);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
+ case SP_ATTR_INKSCAPE_SNAP_PERP:
+ nv->snap_manager.snapprefs.setSnapPerp(value ? sp_str_to_bool(value) : FALSE);
+ object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ case SP_ATTR_INKSCAPE_SNAP_TANG:
+ nv->snap_manager.snapprefs.setSnapTang(value ? sp_str_to_bool(value) : FALSE);
+ object->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ break;
case SP_ATTR_INKSCAPE_SNAP_PATH_CLIP:
nv->snap_manager.snapprefs.setTargetSnappable(Inkscape::SNAPTARGET_PATH_CLIP, value ? sp_str_to_bool(value) : FALSE);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index fa6ef2726..9e76a4534 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -123,6 +123,8 @@ DocumentProperties::DocumentProperties()
//---------------------------------------------------------------
_rcb_snclp(_("Snap to clip paths"), _("When snapping to paths, then also try snapping to clip paths"), "inkscape:snap-path-clip", _wr),
_rcb_snmsk(_("Snap to mask paths"), _("When snapping to paths, then also try snapping to mask paths"), "inkscape:snap-path-mask", _wr),
+ _rcb_perp(_("Snap perpendicularly"), _("When snapping to paths or guides, then also try snapping perpendicularly"), "inkscape:snap-perpendicular", _wr),
+ _rcb_tang(_("Snap tangentially"), _("When snapping to paths or guides, then also try snapping tangentially"), "inkscape:snap-tangential", _wr),
//---------------------------------------------------------------
#if WITH_GTKMM_2_22
_grids_label_crea("", Gtk::ALIGN_START),
@@ -294,6 +296,8 @@ void DocumentProperties::build_snap()
label_gr->set_markup (_("<b>Snap to grids</b>"));
Gtk::Label *label_gu = manage (new Gtk::Label);
label_gu->set_markup (_("<b>Snap to guides</b>"));
+ Gtk::Label *label_m = manage (new Gtk::Label);
+ label_m->set_markup (_("<b>Miscellaneous</b>"));
Gtk::Widget *const array[] =
{
@@ -306,7 +310,11 @@ void DocumentProperties::build_snap()
0, _rsu_sn._vbox,
0, 0,
label_gu, 0,
- 0, _rsu_gusn._vbox
+ 0, _rsu_gusn._vbox,
+ 0, 0,
+ label_m, 0,
+ 0, &_rcb_perp,
+ 0, &_rcb_tang
};
attach_all(_page_snap.table(), array, G_N_ELEMENTS(array));
@@ -1047,6 +1055,8 @@ void DocumentProperties::update()
_rsu_gusn.setValue (nv->snap_manager.snapprefs.getGuideTolerance());
_rcb_snclp.setActive (nv->snap_manager.snapprefs.isSnapButtonEnabled(Inkscape::SNAPTARGET_PATH_CLIP));
_rcb_snmsk.setActive (nv->snap_manager.snapprefs.isSnapButtonEnabled(Inkscape::SNAPTARGET_PATH_MASK));
+ _rcb_perp.setActive (nv->snap_manager.snapprefs.getSnapPerp());
+ _rcb_tang.setActive (nv->snap_manager.snapprefs.getSnapTang());
//-----------------------------------------------------------grids page
diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h
index 783dfa208..d4065f4ab 100644
--- a/src/ui/dialog/document-properties.h
+++ b/src/ui/dialog/document-properties.h
@@ -116,6 +116,8 @@ protected:
UI::Widget::ToleranceSlider _rsu_gusn;
UI::Widget::RegisteredCheckButton _rcb_snclp;
UI::Widget::RegisteredCheckButton _rcb_snmsk;
+ UI::Widget::RegisteredCheckButton _rcb_perp;
+ UI::Widget::RegisteredCheckButton _rcb_tang;
//---------------------------------------------------------------
Gtk::ComboBoxText _combo_avail;
Gtk::Button _link_btn;