summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d383167)
raw | patch | inline | side by side (parent: d383167)
author | Diederik van Lierop <mailat-signdiedenrezidotnl> | |
Sun, 7 Nov 2010 20:16:45 +0000 (21:16 +0100) | ||
committer | Diederik van Lierop <mailat-signdiedenrezidotnl> | |
Sun, 7 Nov 2010 20:16:45 +0000 (21:16 +0100) |
src/draw-context.cpp | patch | blob | history | |
src/gradient-drag.cpp | patch | blob | history | |
src/seltrans.cpp | patch | blob | history | |
src/snap.cpp | patch | blob | history | |
src/snap.h | patch | blob | history |
diff --git a/src/draw-context.cpp b/src/draw-context.cpp
index ca68b3f6df0fe66aa0b9beed444c584ee6a8c752..66a2309b2e949e6f1629ea8b7518d8b811cb2388 100644 (file)
--- a/src/draw-context.cpp
+++ b/src/draw-context.cpp
#include "sp-namedview.h"
#include "live_effects/lpe-patternalongpath.h"
#include "style.h"
-#include "util/mathfns.h"
static void sp_draw_context_class_init(SPDrawContextClass *klass);
static void sp_draw_context_init(SPDrawContext *dc);
@@ -477,43 +476,26 @@ void spdc_endpoint_snap_rotation(SPEventContext const *const ec, Geom::Point &p,
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
unsigned const snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12));
+ SnapManager &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager;
+ m.setup(SP_EVENT_CONTEXT_DESKTOP(ec));
- if (snaps > 0) { // 0 means no snapping
- // p is at an arbitrary angle. Now we should snap this angle to specific increments.
- // For this we'll calculate the closest two angles, one at each side of the current angle
- Geom::Line y_axis(Geom::Point(0, 0), Geom::Point(0, 1));
- Geom::Line p_line(o, p);
- double angle = Geom::angle_between(y_axis, p_line);
- double angle_incr = M_PI / snaps;
- double angle_ceil = round_to_upper_multiple_plus(angle, angle_incr);
- double angle_floor = round_to_lower_multiple_plus(angle, angle_incr);
- // We have to angles now. The constrained snapper will try each of them and return the closest
- // But first we should setup the snapper
-
- SnapManager &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager;
- m.setup(SP_EVENT_CONTEXT_DESKTOP(ec));
- bool snap_enabled = m.snapprefs.getSnapEnabledGlobally();
- if (state & GDK_SHIFT_MASK) {
- // SHIFT disables all snapping, except the angular snapping. After all, the user explicitly asked for angular
- // snapping by pressing CTRL, otherwise we wouldn't have arrived here. But although we temporarily disable
- // the snapping here, we must still call for a constrained snap in order to apply the constraints (i.e. round
- // to the nearest angle increment)
- m.snapprefs.setSnapEnabledGlobally(false);
- }
-
- // Now do the snapping...
- std::vector<Inkscape::Snapper::SnapConstraint> constraints;
- constraints.push_back(Inkscape::Snapper::SnapConstraint(Geom::Line(o, angle_ceil - M_PI/2)));
- constraints.push_back(Inkscape::Snapper::SnapConstraint(Geom::Line(o, angle_floor - M_PI/2)));
+ bool snap_enabled = m.snapprefs.getSnapEnabledGlobally();
+ if (state & GDK_SHIFT_MASK) {
+ // SHIFT disables all snapping, except the angular snapping. After all, the user explicitly asked for angular
+ // snapping by pressing CTRL, otherwise we wouldn't have arrived here. But although we temporarily disable
+ // the snapping here, we must still call for a constrained snap in order to apply the constraints (i.e. round
+ // to the nearest angle increment)
+ m.snapprefs.setSnapEnabledGlobally(false);
+ }
- Inkscape::SnappedPoint sp = m.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE), constraints);
- p = sp.getPoint();
+ Inkscape::SnappedPoint dummy = m.constrainedAngularSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE), boost::optional<Geom::Point>(), o, snaps);
+ p = dummy.getPoint();
- m.unSetup();
- if (state & GDK_SHIFT_MASK) {
- m.snapprefs.setSnapEnabledGlobally(snap_enabled); // restore the original setting
- }
+ if (state & GDK_SHIFT_MASK) {
+ m.snapprefs.setSnapEnabledGlobally(snap_enabled); // restore the original setting
}
+
+ m.unSetup();
}
diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp
index 32aa7c084ee63c53eb1447ebe3036a4824c1b65f..d5ab64794cb33ad544bc56c102c6afd073273ebe 100644 (file)
--- a/src/gradient-drag.cpp
+++ b/src/gradient-drag.cpp
return server;
}
-static
-boost::optional<Geom::Point>
-get_snap_vector (Geom::Point p, Geom::Point o, double snap, double initial)
-{
- double r = L2 (p - o);
- if (r < 1e-3) {
- return boost::optional<Geom::Point>();
- }
-
- double angle = atan2 (p - o);
- // snap angle to snaps increments, starting from initial:
- double a_snapped = initial + floor((angle - initial)/snap + 0.5) * snap;
- // calculate the new position and subtract p to get the vector:
- return (o + r * Geom::Point(cos(a_snapped), sin(a_snapped)) - p);
-}
-
static void
gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gpointer data)
{
@@ -645,15 +629,17 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp
}
}
- m.setup(desktop);
if (!((state & GDK_SHIFT_MASK) || (state & GDK_CONTROL_MASK))) {
+ m.setup(desktop);
Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE));
+ m.unSetup();
if (s.getSnapped()) {
p = s.getPoint();
sp_knot_moveto (knot, p);
}
} else if (state & GDK_CONTROL_MASK) {
SnappedConstraints sc;
+ Inkscape::SnapCandidatePoint scp = Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
unsigned snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12));
/* 0 means no snapping. */
@@ -699,40 +685,40 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp
dr_snap = dragger->point_original;
}
- boost::optional<Geom::Point> snap_vector;
+ // dr_snap contains the origin of the gradient, whereas p will be the new endpoint which we will try to snap now
+ Inkscape::SnappedPoint sp;
if (dr_snap.isFinite()) {
+ m.setup(desktop);
if (state & GDK_MOD1_MASK) {
// with Alt, snap to the original angle and its perpendiculars
- snap_vector = get_snap_vector (p, dr_snap, M_PI/2, Geom::atan2 (dragger->point_original - dr_snap));
+ sp = m.constrainedAngularSnap(scp, dragger->point_original, dr_snap, 2);
} else {
// with Ctrl, snap to M_PI/snaps
- snap_vector = get_snap_vector (p, dr_snap, M_PI/snaps, 0);
- }
- if (snap_vector) {
- Inkscape::Snapper::SnapConstraint cl(dr_snap, p + *snap_vector - dr_snap);
- Inkscape::SnappedPoint s = m.constrainedSnap(Inkscape::SnapCandidatePoint(p + *snap_vector, Inkscape::SNAPSOURCE_OTHER_HANDLE), cl);
- if (s.getSnapped()) {
- s.setTransformation(s.getPoint() - p);
- sc.points.push_back(s);
- } else {
- Inkscape::SnappedPoint dummy(p + *snap_vector, Inkscape::SNAPSOURCE_OTHER_HANDLE, 0, Inkscape::SNAPTARGET_CONSTRAINED_ANGLE, Geom::L2(*snap_vector), 10000, true, true, false);
- dummy.setTransformation(*snap_vector);
- sc.points.push_back(dummy);
- }
+ sp = m.constrainedAngularSnap(scp, boost::optional<Geom::Point>(), dr_snap, snaps);
}
+ m.unSetup();
+ sc.points.push_back(sp);
}
}
- Inkscape::SnappedPoint bsp = m.findBestSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_OTHER_HANDLE), sc, true); // snap indicator will be displayed if needed
-
- if (bsp.getSnapped()) {
- p += bsp.getTransformation();
- sp_knot_moveto (knot, p);
+ m.setup(desktop, false); // turn of the snap indicator temporarily
+ Inkscape::SnappedPoint bsp = m.findBestSnap(scp, sc, true);
+ m.unSetup();
+ if (!bsp.getSnapped()) {
+ // If we didn't truly snap to an object or to a grid, then we will still have to look for the
+ // closest projection onto one of the constraints. findBestSnap() will not do this for us
+ for (std::list<Inkscape::SnappedPoint>::const_iterator i = sc.points.begin(); i != sc.points.end(); i++) {
+ if (i == sc.points.begin() || (Geom::L2((*i).getPoint() - p) < Geom::L2(bsp.getPoint() - p))) {
+ bsp.setPoint((*i).getPoint());
+ bsp.setTarget(Inkscape::SNAPTARGET_CONSTRAINED_ANGLE);
+ }
+ }
}
+ //p = sc.points.front().getPoint();
+ p = bsp.getPoint();
+ sp_knot_moveto (knot, p);
}
- m.unSetup();
-
drag->keep_selection = (bool) g_list_find(drag->selected, dragger);
bool scale_radial = (state & GDK_CONTROL_MASK) && (state & GDK_SHIFT_MASK);
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index 9a1fdf4adcd8d8b6d45c15cf730a8a41ce2d88b5..7ea2a86c05bc356b2a6585f203a8072272ea27fa 100644 (file)
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -1656,6 +1656,7 @@ void Inkscape::SelTrans::_keepClosestPointOnly(std::vector<Inkscape::SnapCandida
}
}
+ closest_point.setSourceNum(-1);
points.clear();
points.push_back(closest_point);
}
diff --git a/src/snap.cpp b/src/snap.cpp
index 1f37536007ed5bd4a0ae10c2f35d401217753528..46bd01f4d5996e06e5d04ee735634fed1ce0567f 100644 (file)
--- a/src/snap.cpp
+++ b/src/snap.cpp
#include "sp-guide.h"
#include "preferences.h"
#include "event-context.h"
+#include "util/mathfns.h"
using std::vector;
/**
@@ -471,12 +472,8 @@ Inkscape::SnappedPoint SnapManager::multipleConstrainedSnaps(Inkscape::SnapCandi
}
if (result.getSnapped()) {
- // only change the snap indicator if we really snapped to something
- if (_snapindicator && _desktop) {
- _desktop->snapindicator->set_new_snaptarget(result);
- }
if (snap_mouse) {
- // We still have to apply the constraint, because so far we only tried a freeSnap
+ // If "snap_mouse" then we still have to apply the constraint, because so far we only tried a freeSnap
Geom::Point result_closest;
for (std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator c = constraints.begin(); c != constraints.end(); c++) {
// Project the mouse pointer onto the constraint; In case we don't snap then we will
@@ -506,6 +503,55 @@ Inkscape::SnappedPoint SnapManager::multipleConstrainedSnaps(Inkscape::SnapCandi
return no_snap;
}
+/**
+ * \brief Try to snap a point to something at a specific angle
+ *
+ * When drawing a straight line or modifying a gradient, it will snap to specific angle increments
+ * if CTRL is being pressed. This method will enforce this angular constraint (even if there is nothing
+ * to snap to)
+ *
+ * \param p Source point to be snapped
+ * \param p_ref Optional original point, relative to which the angle should be calculated. If empty then
+ * the angle will be calculated relative to the y-axis
+ * \param snaps Number of angular increments per PI radians; E.g. if snaps = 2 then we will snap every PI/2 = 90 degrees
+ */
+
+Inkscape::SnappedPoint SnapManager::constrainedAngularSnap(Inkscape::SnapCandidatePoint const &p,
+ boost::optional<Geom::Point> const &p_ref,
+ Geom::Point const &o,
+ unsigned const snaps) const
+{
+ Inkscape::SnappedPoint sp;
+ if (snaps > 0) { // 0 means no angular snapping
+ // p is at an arbitrary angle. Now we should snap this angle to specific increments.
+ // For this we'll calculate the closest two angles, one at each side of the current angle
+ Geom::Line y_axis(Geom::Point(0, 0), Geom::Point(0, 1));
+ Geom::Line p_line(o, p.getPoint());
+ double angle = Geom::angle_between(y_axis, p_line);
+ double angle_incr = M_PI / snaps;
+ double angle_offset = 0;
+ if (p_ref) {
+ Geom::Line p_line_ref(o, *p_ref);
+ angle_offset = Geom::angle_between(y_axis, p_line_ref);
+ }
+ double angle_ceil = round_to_upper_multiple_plus(angle, angle_incr, angle_offset);
+ double angle_floor = round_to_lower_multiple_plus(angle, angle_incr, angle_offset);
+ // We have two angles now. The constrained snapper will try each of them and return the closest
+
+ // Now do the snapping...
+ std::vector<Inkscape::Snapper::SnapConstraint> constraints;
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(Geom::Line(o, angle_ceil - M_PI/2)));
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(Geom::Line(o, angle_floor - M_PI/2)));
+ sp = multipleConstrainedSnaps(p, constraints); // Constraints will always be applied, even if we didn't snap
+ if (!sp.getSnapped()) { // If we haven't snapped then we only had the constraint applied;
+ sp.setTarget(Inkscape::SNAPTARGET_CONSTRAINED_ANGLE);
+ }
+ } else {
+ sp = freeSnap(p);
+ }
+ return sp;
+}
+
/**
* \brief Try to snap a point of a guide to another guide or to a node
*
diff --git a/src/snap.h b/src/snap.h
index 0f27017a5619c403703f3a592120808da4cc9ce0..3c9af7d515ab84011a04af3ef0381087ca36547e 100644 (file)
--- a/src/snap.h
+++ b/src/snap.h
std::vector<Inkscape::Snapper::SnapConstraint> const &constraints,
Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
+ Inkscape::SnappedPoint constrainedAngularSnap(Inkscape::SnapCandidatePoint const &p,
+ boost::optional<Geom::Point> const &p_ref,
+ Geom::Point const &o,
+ unsigned const snaps) const;
+
void guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SPGuideDragType drag_type) const;
void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const;