From: dvlierop2 Date: Mon, 7 Apr 2008 19:28:34 +0000 (+0000) Subject: Refactor snapper and snapindicator (in order to enable the snapindicator in the selec... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=c2f971415f07fbf4825e88523d6f964e0a5b1873;p=inkscape.git Refactor snapper and snapindicator (in order to enable the snapindicator in the selector tool) --- diff --git a/src/context-fns.cpp b/src/context-fns.cpp index 32c7eef00..d7333adbe 100644 --- a/src/context-fns.cpp +++ b/src/context-fns.cpp @@ -190,9 +190,9 @@ NR::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item, p[1] = snappoint.getPoint(); } - if (snappoint.getDistance() < NR_HUGE) { + if (snappoint.getSnapped()) { // this does not work well enough yet. -// desktop->snapindicator->set_new_snappoint(snappoint.getPoint().to_2geom()); +// desktop->snapindicator->set_new_snappoint(snappoint); } p[0] = sp_desktop_dt2root_xy_point(desktop, p[0]); diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp index dc153e31d..5b6972c33 100644 --- a/src/desktop-events.cpp +++ b/src/desktop-events.cpp @@ -150,8 +150,8 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge desktop->set_coordinate_status(event_dt); desktop->setPosition (event_dt); - if (snappoint.getDistance() < NR_HUGE) { - desktop->snapindicator->set_new_snappoint(snappoint.getPoint().to_2geom()); + if (snappoint.getSnapped()) { + desktop->snapindicator->set_new_snappoint(snappoint); } else { desktop->snapindicator->remove_snappoint(); } @@ -254,8 +254,8 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data) desktop->set_coordinate_status(motion_dt); desktop->setPosition (motion_dt); - if (snappoint.getDistance() < NR_HUGE) { - desktop->snapindicator->set_new_snappoint(snappoint.getPoint().to_2geom()); + if (snappoint.getSnapped()) { + desktop->snapindicator->set_new_snappoint(snappoint); } else { desktop->snapindicator->remove_snappoint(); } diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index f5e754d90..03fcad484 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -32,11 +32,11 @@ SnapIndicator::~SnapIndicator() } void -SnapIndicator::set_new_snappoint(Geom::Point p) +SnapIndicator::set_new_snappoint(Inkscape::SnappedPoint const p) { remove_snappoint(); - bool enabled = false; // TODO add preference for snap indicator. + bool enabled = true; // TODO add preference for snap indicator. if (enabled) { // TODO add many different kinds of snap indicator :-) SPCanvasItem * canvasitem = sp_canvas_item_new( sp_desktop_tempgroup (desktop), @@ -48,7 +48,9 @@ SnapIndicator::set_new_snappoint(Geom::Point p) "mode", SP_KNOT_MODE_XOR, "shape", SP_KNOT_SHAPE_CROSS, NULL ); - SP_CTRL(canvasitem)->moveto ( p ); + + + SP_CTRL(canvasitem)->moveto(p.getPoint()); tempitem = desktop->add_temporary_canvasitem(canvasitem, 1000); // TODO add preference for snap indicator timeout } } diff --git a/src/display/snap-indicator.h b/src/display/snap-indicator.h index 0395d4000..c17de0494 100644 --- a/src/display/snap-indicator.h +++ b/src/display/snap-indicator.h @@ -14,7 +14,7 @@ #include "forward.h" #include "display/display-forward.h" -#include <2geom/point.h> +#include "snapped-point.h" namespace Inkscape { namespace Display { @@ -24,7 +24,7 @@ public: SnapIndicator(SPDesktop *desktop); virtual ~SnapIndicator(); - void set_new_snappoint(Geom::Point p); + void set_new_snappoint(Inkscape::SnappedPoint const p); void remove_snappoint(); protected: diff --git a/src/draw-context.cpp b/src/draw-context.cpp index adcbc3b3c..42555f8d2 100644 --- a/src/draw-context.cpp +++ b/src/draw-context.cpp @@ -358,8 +358,8 @@ void spdc_endpoint_snap_rotation(SPEventContext const *const ec, NR::Point &p, N Inkscape::SnappedPoint const s = m.constrainedSnap( Inkscape::Snapper::SNAPPOINT_NODE, p, Inkscape::Snapper::ConstraintLine(best), NULL ); p = s.getPoint(); - if (s.getDistance() < NR_HUGE) { - SP_EVENT_CONTEXT_DESKTOP(ec)->snapindicator->set_new_snappoint(p.to_2geom()); + if (s.getSnapped()) { + SP_EVENT_CONTEXT_DESKTOP(ec)->snapindicator->set_new_snappoint(s); } } } @@ -375,8 +375,8 @@ void spdc_endpoint_snap_free(SPEventContext const * const ec, NR::Point& p, guin SnapManager const &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager; Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, p, NULL); p = s.getPoint(); - if (s.getDistance() < NR_HUGE) { - SP_EVENT_CONTEXT_DESKTOP(ec)->snapindicator->set_new_snappoint(p.to_2geom()); + if (s.getSnapped()) { + SP_EVENT_CONTEXT_DESKTOP(ec)->snapindicator->set_new_snappoint(s); } } diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 6c960ed28..7a7957856 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -584,32 +584,34 @@ gr_knot_moved_handler(SPKnot *knot, NR::Point const *ppointer, guint state, gpoi // Try snapping to the grid or guides SnapManager const &m = dragger->parent->desktop->namedview->snap_manager; Inkscape::SnappedPoint s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, p, NULL); - if (s.getDistance() < 1e6) { + if (s.getSnapped()) { p = s.getPoint(); sp_knot_moveto (knot, &p); - dragger->parent->desktop->snapindicator->set_new_snappoint(p.to_2geom()); + dragger->parent->desktop->snapindicator->set_new_snappoint(s); } else { bool was_snapped = false; - Geom::Point snapped_to; + double dist = NR_HUGE; // No snapping so far, let's see if we need to snap to any of the levels for (guint i = 0; i < dragger->parent->hor_levels.size(); i++) { - if (fabs(p[NR::Y] - dragger->parent->hor_levels[i]) < snap_dist) { + dist = fabs(p[NR::Y] - dragger->parent->hor_levels[i]); + if (dist < snap_dist) { p[NR::Y] = dragger->parent->hor_levels[i]; - snapped_to = p.to_2geom(); + s = Inkscape::SnappedPoint(p, dist, snap_dist, false); was_snapped = true; sp_knot_moveto (knot, &p); } } for (guint i = 0; i < dragger->parent->vert_levels.size(); i++) { - if (fabs(p[NR::X] - dragger->parent->vert_levels[i]) < snap_dist) { + dist = fabs(p[NR::X] - dragger->parent->vert_levels[i]); + if (dist < snap_dist) { p[NR::X] = dragger->parent->vert_levels[i]; - snapped_to = p.to_2geom(); + s = Inkscape::SnappedPoint(p, dist, snap_dist, false); was_snapped = true; sp_knot_moveto (knot, &p); } } if (was_snapped) { - dragger->parent->desktop->snapindicator->set_new_snappoint(snapped_to); + dragger->parent->desktop->snapindicator->set_new_snappoint(s); } } } diff --git a/src/nodepath.cpp b/src/nodepath.cpp index 250970dec..d6dbb19b4 100644 --- a/src/nodepath.cpp +++ b/src/nodepath.cpp @@ -54,6 +54,7 @@ #include "live_effects/parameter/parameter.h" #include "util/mathfns.h" #include "display/snap-indicator.h" +#include "snapped-point.h" class NR::Matrix; @@ -1102,7 +1103,7 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath, NR::Coord best = NR_HUGE; NR::Point delta(dx, dy); NR::Point best_pt = delta; - NR::Point best_abs(NR_HUGE, NR_HUGE); + Inkscape::SnappedPoint best_abs; if (snap) { @@ -1129,13 +1130,13 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath, Inkscape::SnappedPoint s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, n->pos + delta, SP_PATH(n->subpath->nodepath->item), &unselected_nodes); if (s.getDistance() < best) { best = s.getDistance(); - best_abs = s.getPoint(); - best_pt = best_abs - n->pos; + best_abs = s; + best_pt = s.getPoint() - n->pos; } } - if (best_abs[NR::X] < NR_HUGE) { - nodepath->desktop->snapindicator->set_new_snappoint(best_abs.to_2geom()); + if (best_abs.getSnapped()) { + nodepath->desktop->snapindicator->set_new_snappoint(best_abs); } } @@ -3576,8 +3577,8 @@ static gboolean node_handle_request(SPKnot *knot, NR::Point *p, guint /*state*/, s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, *p, n->subpath->nodepath->item); } *p = s.getPoint(); - if (s.getDistance() < NR_HUGE) { - n->subpath->nodepath->desktop->snapindicator->set_new_snappoint((*p).to_2geom()); + if (s.getSnapped()) { + n->subpath->nodepath->desktop->snapindicator->set_new_snappoint(s); } sp_node_adjust_handle(n, -which); diff --git a/src/pencil-context.cpp b/src/pencil-context.cpp index d27d363f9..878651ade 100644 --- a/src/pencil-context.cpp +++ b/src/pencil-context.cpp @@ -327,8 +327,8 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev SnapManager const &m = dt->namedview->snap_manager; Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, p, NULL); p = s.getPoint(); - if (s.getDistance() < NR_HUGE) { - dt->snapindicator->set_new_snappoint(p.to_2geom()); + if (s.getSnapped()) { + dt->snapindicator->set_new_snappoint(s); } } if ( pc->npoints != 0 ) { // buttonpress may have happened before we entered draw context! diff --git a/src/rect-context.cpp b/src/rect-context.cpp index a25b39961..1054a2c55 100644 --- a/src/rect-context.cpp +++ b/src/rect-context.cpp @@ -310,8 +310,8 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent SnapManager const &m = desktop->namedview->snap_manager; Inkscape::SnappedPoint s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, button_dt, rc->item); rc->center = s.getPoint(); - if (s.getDistance() < NR_HUGE) { - desktop->snapindicator->set_new_snappoint(s.getPoint().to_2geom()); + if (s.getSnapped()) { + desktop->snapindicator->set_new_snappoint(s); } sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), @@ -344,8 +344,8 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent SnapManager const &m = desktop->namedview->snap_manager; Inkscape::SnappedPoint s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, motion_dt, rc->item); motion_dt = s.getPoint(); - if (s.getDistance() < NR_HUGE) { - desktop->snapindicator->set_new_snappoint(s.getPoint().to_2geom()); + if (s.getSnapped()) { + desktop->snapindicator->set_new_snappoint(s); } sp_rect_drag(*rc, motion_dt, event->motion.state); diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 5ab99e147..d248d3152 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -50,6 +50,7 @@ #include "xml/repr.h" #include "mod360.h" #include "2geom/angle.h" +#include "display/snap-indicator.h" #include "isnan.h" //temp fix. make sure included last @@ -916,8 +917,7 @@ gboolean Inkscape::SelTrans::scaleRequest(NR::Point &pt, guint state) it.push_back(reinterpret_cast(i->data)); } - std::pair bb = std::make_pair(NR::scale(1,1), false); - std::pair sn = std::make_pair(NR::scale(1,1), false); + Inkscape::SnappedPoint bb, sn; NR::Coord bd(NR_HUGE); NR::Coord sd(NR_HUGE); @@ -940,31 +940,33 @@ gboolean Inkscape::SelTrans::scaleRequest(NR::Point &pt, guint state) /* Choose the smaller difference in scale. Since s[X] == s[Y] we can ** just compare difference in s[X]. */ - bd = bb.second ? fabs(bb.first[NR::X] - default_scale[NR::X]) : NR_HUGE; - sd = sn.second ? fabs(sn.first[NR::X] - geom_scale[NR::X]) : NR_HUGE; + bd = bb.getSnapped() ? fabs(bb.getTransformation()[NR::X] - default_scale[NR::X]) : NR_HUGE; + sd = sn.getSnapped() ? fabs(sn.getTransformation()[NR::X] - geom_scale[NR::X]) : NR_HUGE; } else { /* Scale aspect ratio is unlocked */ bb = m.freeSnapScale(Snapper::SNAPPOINT_BBOX, _bbox_points, it, default_scale, _origin_for_bboxpoints); sn = m.freeSnapScale(Snapper::SNAPPOINT_NODE, _snap_points, it, geom_scale, _origin_for_specpoints); /* Pick the snap that puts us closest to the original scale */ - bd = bb.second ? fabs(NR::L2(bb.first.point()) - NR::L2(default_scale.point())) : NR_HUGE; - sd = sn.second ? fabs(NR::L2(sn.first.point()) - NR::L2(geom_scale.point())) : NR_HUGE; + bd = bb.getSnapped() ? fabs(NR::L2(bb.getTransformation()) - NR::L2(default_scale.point())) : NR_HUGE; + sd = sn.getSnapped() ? fabs(NR::L2(sn.getTransformation()) - NR::L2(geom_scale.point())) : NR_HUGE; } - if (!(bb.second || sn.second)) { + if (!(bb.getSnapped() || sn.getSnapped())) { // We didn't snap at all! Don't update the handle position, just calculate the new transformation _calcAbsAffineDefault(default_scale); } else if (bd < sd) { // We snapped the bbox (which is either visual or geometric) - default_scale = bb.first; + _desktop->snapindicator->set_new_snappoint(bb); + default_scale = NR::scale(bb.getTransformation()); // Calculate the new transformation and update the handle position pt = _calcAbsAffineDefault(default_scale); } else { + _desktop->snapindicator->set_new_snappoint(sn); // We snapped the special points (e.g. nodes), which are not at the visual bbox // The handle location however (pt) might however be at the visual bbox, so we // will have to calculate pt taking the stroke width into account - geom_scale = sn.first; + geom_scale = NR::scale(sn.getTransformation()); pt = _calcAbsAffineGeom(geom_scale); } } @@ -1030,8 +1032,8 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, NR:: SnapManager const &m = _desktop->namedview->snap_manager; - std::pair bb = std::make_pair(NR_HUGE, false); - std::pair sn = std::make_pair(NR_HUGE, false); + Inkscape::SnappedPoint bb, sn; + g_assert(bb.getSnapped() == false); // Check initialization to catch any regression NR::Coord bd(NR_HUGE); NR::Coord sd(NR_HUGE); @@ -1040,15 +1042,15 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, NR:: bb = m.constrainedSnapStretch(Snapper::SNAPPOINT_BBOX, _bbox_points, it, default_scale[axis], _origin_for_bboxpoints, axis, symmetrical); sn = m.constrainedSnapStretch(Snapper::SNAPPOINT_NODE, _snap_points, it, geom_scale[axis], _origin_for_specpoints, axis, symmetrical); - if (bb.second) { + if (bb.getSnapped()) { // We snapped the bbox (which is either visual or geometric) - bd = fabs(bb.first - default_scale[axis]); - default_scale[axis] = bb.first; + bd = fabs(bb.getTransformation()[axis] - default_scale[axis]); + default_scale[axis] = bb.getTransformation()[axis]; } - if (sn.second) { - sd = fabs(sn.first - geom_scale[axis]); - geom_scale[axis] = sn.first; + if (sn.getSnapped()) { + sd = fabs(sn.getTransformation()[axis] - geom_scale[axis]); + geom_scale[axis] = sn.getTransformation()[axis]; } if (symmetrical) { @@ -1058,13 +1060,15 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, NR:: geom_scale[perp] = fabs(geom_scale[axis]); } - if (!(bb.second || sn.second)) { + if (!(bb.getSnapped() || sn.getSnapped())) { // We didn't snap at all! Don't update the handle position, just calculate the new transformation _calcAbsAffineDefault(default_scale); } else if (bd < sd) { + _desktop->snapindicator->set_new_snappoint(bb); // Calculate the new transformation and update the handle position pt = _calcAbsAffineDefault(default_scale); } else { + _desktop->snapindicator->set_new_snappoint(sn); // We snapped the special points (e.g. nodes), which are not at the visual bbox // The handle location however (pt) might however be at the visual bbox, so we // will have to calculate pt taking the stroke width into account @@ -1155,14 +1159,22 @@ gboolean Inkscape::SelTrans::skewRequest(SPSelTransHandle const &handle, NR::Poi SnapManager const &m = _desktop->namedview->snap_manager; - std::pair bb = m.freeSnapSkew(Inkscape::Snapper::SNAPPOINT_BBOX, _bbox_points, it, skew[dim_a], _origin, dim_b); - std::pair sn = m.freeSnapSkew(Inkscape::Snapper::SNAPPOINT_NODE, _snap_points, it, skew[dim_a], _origin, dim_b); + //TODO: While skewing, scaling in the opposite direction by integer multiples is also allowed. This is not handled though by freeSnapSkew / _snapTransformed yet! + //TODO: We need a constrainedSnapSkew instead of a freeSnapSkew + Inkscape::SnappedPoint bb = m.freeSnapSkew(Inkscape::Snapper::SNAPPOINT_BBOX, _bbox_points, it, skew[dim_a], _origin, dim_b); + Inkscape::SnappedPoint sn = m.freeSnapSkew(Inkscape::Snapper::SNAPPOINT_NODE, _snap_points, it, skew[dim_a], _origin, dim_b); - if (bb.second || sn.second) { + if (bb.getSnapped() || sn.getSnapped()) { // We snapped something, so change the skew to reflect it - NR::Coord const bd = bb.second ? bb.first : NR_HUGE; - NR::Coord const sd = sn.second ? sn.first : NR_HUGE; - skew[dim_a] = std::min(bd, sd); + NR::Coord const bd = bb.getSnapped() ? bb.getTransformation()[dim_b] : NR_HUGE; + NR::Coord const sd = sn.getSnapped() ? sn.getTransformation()[dim_b] : NR_HUGE; + if (bd < sd) { + _desktop->snapindicator->set_new_snappoint(bb); + skew[dim_a] = bd; + } else { + _desktop->snapindicator->set_new_snappoint(sn); + skew[dim_a] = sd; + } } } @@ -1380,7 +1392,7 @@ void Inkscape::SelTrans::moveTo(NR::Point const &xy, guint state) */ /* This will be our list of possible translations */ - std::list > s; + std::list s; if (control) { @@ -1419,16 +1431,22 @@ void Inkscape::SelTrans::moveTo(NR::Point const &xy, guint state) } /* Pick one */ - NR::Coord best = NR_HUGE; - for (std::list >::const_iterator i = s.begin(); i != s.end(); i++) { - if (i->second) { - NR::Coord const m = NR::L2(i->first); - if (m < best) { - best = m; - dxy = i->first; + Inkscape::SnappedPoint best_snapped_point; + g_assert(best_snapped_point.getDistance() == NR_HUGE); + for (std::list::const_iterator i = s.begin(); i != s.end(); i++) { + if (i->getSnapped()) { + // std::cout << "moveTo() -> snapped to point: " << i->getPoint() << " with transformation: " << i->getTransformation(); + if (i->getDistance() < best_snapped_point.getDistance()) { + best_snapped_point = *i; + dxy = i->getTransformation(); + // std::cout << " SEL"; } + //std::cout << std::endl; } } + if (best_snapped_point.getSnapped()) { + _desktop->snapindicator->set_new_snappoint(best_snapped_point); + } } if (control) { diff --git a/src/snap.cpp b/src/snap.cpp index 639e704b0..76bda9282 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -344,7 +344,7 @@ Inkscape::SnappedPoint SnapManager::guideSnap(NR::Point const &p, * \param uniform true if the transformation should be uniform; only applicable for stretching and scaling. */ -std::pair SnapManager::_snapTransformed( +Inkscape::SnappedPoint SnapManager::_snapTransformed( Inkscape::Snapper::PointType type, std::vector const &points, std::list const &ignore, @@ -365,7 +365,7 @@ std::pair SnapManager::_snapTransformed( ** Also used to globally disable all snapping */ if (SomeSnapperMightSnap() == false) { - return std::make_pair(transformation, false); + return Inkscape::SnappedPoint(); } std::vector transformed_points; @@ -414,17 +414,17 @@ std::pair SnapManager::_snapTransformed( NR::Coord best_metric = NR_HUGE; NR::Coord best_second_metric = NR_HUGE; NR::Point best_scale_metric(NR_HUGE, NR_HUGE); - bool best_at_intersection = false; - bool best_always_snap = false; + Inkscape::SnappedPoint best_snapped_point; + g_assert(best_snapped_point.getAlwaysSnap() == false); // Check initialization of snapped point + g_assert(best_snapped_point.getAtIntersection() == false); std::vector::const_iterator j = transformed_points.begin(); - //std::cout << std::endl; - + // std::cout << std::endl; for (std::vector::const_iterator i = points.begin(); i != points.end(); i++) { /* Snap it */ - Inkscape::SnappedPoint snapped; + Inkscape::SnappedPoint snapped_point; if (constrained) { Inkscape::Snapper::ConstraintLine dedicated_constraint = constraint; @@ -439,9 +439,9 @@ std::pair SnapManager::_snapTransformed( if (transformation_type == SCALE && !uniform) { g_warning("Non-uniform constrained scaling is not supported!"); } - snapped = constrainedSnap(type, *j, i == points.begin(), transformed_points, dedicated_constraint, ignore); + snapped_point = constrainedSnap(type, *j, i == points.begin(), transformed_points, dedicated_constraint, ignore); } else { - snapped = freeSnap(type, *j, i == points.begin(), transformed_points, ignore, NULL); + snapped_point = freeSnap(type, *j, i == points.begin(), transformed_points, ignore, NULL); } NR::Point result; @@ -449,16 +449,16 @@ std::pair SnapManager::_snapTransformed( NR::Coord second_metric = NR_HUGE; NR::Point scale_metric(NR_HUGE, NR_HUGE); - if (snapped.getDistance() < NR_HUGE) { + if (snapped_point.getSnapped()) { /* We snapped. Find the transformation that describes where the snapped point has ** ended up, and also the metric for this transformation. */ - NR::Point const a = (snapped.getPoint() - origin); // vector to snapped point + NR::Point const a = (snapped_point.getPoint() - origin); // vector to snapped point NR::Point const b = (*i - origin); // vector to original point switch (transformation_type) { case TRANSLATION: - result = snapped.getPoint() - *i; + result = snapped_point.getPoint() - *i; /* Consider the case in which a box is almost aligned with a grid in both * horizontal and vertical directions. The distance to the intersection of * the grid lines will always be larger then the distance to a single grid @@ -468,8 +468,8 @@ std::pair SnapManager::_snapTransformed( * distance is defined as the distance to the nearest line of the intersection, * and not to the intersection itself! */ - metric = snapped.getDistance(); //used to be: metric = NR::L2(result); - second_metric = snapped.getSecondDistance(); + metric = snapped_point.getDistance(); //used to be: metric = NR::L2(result); + second_metric = snapped_point.getSecondDistance(); break; case SCALE: { @@ -506,7 +506,7 @@ std::pair SnapManager::_snapTransformed( metric = std::abs(result[dim] - transformation[dim]); break; case SKEW: - result[dim] = (snapped.getPoint()[dim] - (*i)[dim]) / ((*i)[1 - dim] - origin[1 - dim]); + result[dim] = (snapped_point.getPoint()[dim] - (*i)[dim]) / ((*i)[1 - dim] - origin[1 - dim]); metric = std::abs(result[dim] - transformation[dim]); break; default: @@ -519,8 +519,12 @@ std::pair SnapManager::_snapTransformed( if (fabs(scale_metric[index]) < fabs(best_scale_metric[index])) { best_transformation[index] = result[index]; best_scale_metric[index] = fabs(scale_metric[index]); - //std::cout << "SEL "; - } //else { std::cout << " ";} + // When scaling, we're considering the best transformation in each direction separately + // Therefore two different snapped points might together make a single best transformation + // We will however return only a single snapped point (e.g. to display the snapping indicator) + best_snapped_point = snapped_point; + // std::cout << "SEL "; + } // else { std::cout << " ";} } if (uniform) { if (best_scale_metric[0] < best_scale_metric[1]) { @@ -532,24 +536,23 @@ std::pair SnapManager::_snapTransformed( } } best_metric = std::min(best_scale_metric[0], best_scale_metric[1]); - //std::cout << "P_orig = " << (*i) << " | scale_metric = " << scale_metric << " | distance = " << snapped.getDistance() << " | P_snap = " << snapped.getPoint() << std::endl; + // std::cout << "P_orig = " << (*i) << " | scale_metric = " << scale_metric << " | distance = " << snapped_point.getDistance() << " | P_snap = " << snapped_point.getPoint() << std::endl; } else { bool const c1 = metric < best_metric; - bool const c2 = metric == best_metric && snapped.getAtIntersection() == true && best_at_intersection == false; - bool const c3a = metric == best_metric && snapped.getAtIntersection() == true && best_at_intersection == true; + bool const c2 = metric == best_metric && snapped_point.getAtIntersection() == true && best_snapped_point.getAtIntersection() == false; + bool const c3a = metric == best_metric && snapped_point.getAtIntersection() == true && best_snapped_point.getAtIntersection() == true; bool const c3b = second_metric < best_second_metric; - bool const c4 = snapped.getAlwaysSnap() == true && best_always_snap == false; - bool const c4n = snapped.getAlwaysSnap() == false && best_always_snap == true; + bool const c4 = snapped_point.getAlwaysSnap() == true && best_snapped_point.getAlwaysSnap() == false; + bool const c4n = snapped_point.getAlwaysSnap() == false && best_snapped_point.getAlwaysSnap() == true; if ((c1 || c2 || (c3a && c3b) || c4) && !c4n) { best_transformation = result; best_metric = metric; best_second_metric = second_metric; - best_at_intersection = snapped.getAtIntersection(); - best_always_snap = snapped.getAlwaysSnap(); - //std::cout << "SEL "; - } //else { std::cout << " ";} - //std::cout << "P_orig = " << (*i) << " | metric = " << metric << " | distance = " << snapped.getDistance() << " | second metric = " << second_metric << " | P_snap = " << snapped.getPoint() << std::endl; + best_snapped_point = snapped_point; + // std::cout << "SEL "; + } // else { std::cout << " ";} + // std::cout << "P_orig = " << (*i) << " | metric = " << metric << " | distance = " << snapped_point.getDistance() << " | second metric = " << second_metric << " | P_snap = " << snapped_point.getPoint() << std::endl; } } @@ -569,9 +572,11 @@ std::pair SnapManager::_snapTransformed( } } + best_snapped_point.setTransformation(best_transformation); // Using " < 1e6" instead of " < NR_HUGE" for catching some rounding errors - // These rounding errors might be caused by NRRects, see bug #1584301 - return std::make_pair(best_transformation, best_metric < 1e6); + // These rounding errors might be caused by NRRects, see bug #1584301 + best_snapped_point.setDistance(best_metric < 1e6 ? best_metric : NR_HUGE); + return best_snapped_point; } @@ -586,14 +591,12 @@ std::pair SnapManager::_snapTransformed( * \return Snapped translation, if a snap occurred, and a flag indicating whether a snap occurred. */ -std::pair SnapManager::freeSnapTranslation(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::Point const &tr) const +Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::Point const &tr) const { - return _snapTransformed( - t, p, it, false, NR::Point(), TRANSLATION, tr, NR::Point(), NR::X, false - ); + return _snapTransformed(t, p, it, false, NR::Point(), TRANSLATION, tr, NR::Point(), NR::X, false); } @@ -610,15 +613,13 @@ std::pair SnapManager::freeSnapTranslation(Inkscape::Snapper::P * \return Snapped translation, if a snap occurred, and a flag indicating whether a snap occurred. */ -std::pair SnapManager::constrainedSnapTranslation(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - Inkscape::Snapper::ConstraintLine const &c, - NR::Point const &tr) const +Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + Inkscape::Snapper::ConstraintLine const &c, + NR::Point const &tr) const { - return _snapTransformed( - t, p, it, true, c, TRANSLATION, tr, NR::Point(), NR::X, false - ); + return _snapTransformed(t, p, it, true, c, TRANSLATION, tr, NR::Point(), NR::X, false); } @@ -634,15 +635,13 @@ std::pair SnapManager::constrainedSnapTranslation(Inkscape::Sna * \return Snapped scale, if a snap occurred, and a flag indicating whether a snap occurred. */ -std::pair SnapManager::freeSnapScale(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::scale const &s, - NR::Point const &o) const +Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::scale const &s, + NR::Point const &o) const { - return _snapTransformed( - t, p, it, false, NR::Point(), SCALE, NR::Point(s[NR::X], s[NR::Y]), o, NR::X, false - ); + return _snapTransformed(t, p, it, false, NR::Point(), SCALE, NR::Point(s[NR::X], s[NR::Y]), o, NR::X, false); } @@ -659,16 +658,14 @@ std::pair SnapManager::freeSnapScale(Inkscape::Snapper::PointTy * \return Snapped scale, if a snap occurred, and a flag indicating whether a snap occurred. */ -std::pair SnapManager::constrainedSnapScale(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::scale const &s, - NR::Point const &o) const +Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::scale const &s, + NR::Point const &o) const { // When constrained scaling, only uniform scaling is supported. - return _snapTransformed( - t, p, it, true, NR::Point(), SCALE, NR::Point(s[NR::X], s[NR::Y]), o, NR::X, true - ); + return _snapTransformed(t, p, it, true, NR::Point(), SCALE, NR::Point(s[NR::X], s[NR::Y]), o, NR::X, true); } @@ -686,19 +683,15 @@ std::pair SnapManager::constrainedSnapScale(Inkscape::Snapper:: * \return Snapped stretch, if a snap occurred, and a flag indicating whether a snap occurred. */ -std::pair SnapManager::constrainedSnapStretch(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::Coord const &s, - NR::Point const &o, - NR::Dim2 d, - bool u) const +Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::Coord const &s, + NR::Point const &o, + NR::Dim2 d, + bool u) const { - std::pair const r = _snapTransformed( - t, p, it, true, NR::Point(), STRETCH, NR::Point(s, s), o, d, u - ); - - return std::make_pair(r.first[d], r.second); + return _snapTransformed(t, p, it, true, NR::Point(), STRETCH, NR::Point(s, s), o, d, u); } @@ -715,18 +708,14 @@ std::pair SnapManager::constrainedSnapStretch(Inkscape::Snapper * \return Snapped skew, if a snap occurred, and a flag indicating whether a snap occurred. */ -std::pair SnapManager::freeSnapSkew(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::Coord const &s, - NR::Point const &o, - NR::Dim2 d) const +Inkscape::SnappedPoint SnapManager::freeSnapSkew(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::Coord const &s, + NR::Point const &o, + NR::Dim2 d) const { - std::pair const r = _snapTransformed( - t, p, it, false, NR::Point(), SKEW, NR::Point(s, s), o, d, false - ); - - return std::make_pair(r.first[d], r.second); + return _snapTransformed(t, p, it, false, NR::Point(), SKEW, NR::Point(s, s), o, d, false); } Inkscape::SnappedPoint SnapManager::findBestSnap(NR::Point const &p, SnappedConstraints &sc, bool constrained) const diff --git a/src/snap.h b/src/snap.h index bdaa27ea8..8bab5b0cf 100644 --- a/src/snap.h +++ b/src/snap.h @@ -13,6 +13,7 @@ * * Copyright (C) 2006-2007 Johan Engelen * Copyright (C) 2000-2002 Lauris Kaplinski + * Copyright (C) 2000-2008 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -56,12 +57,12 @@ public: SPItem const *it, std::vector *unselected_nodes) const; - Inkscape::SnappedPoint freeSnap( Inkscape::Snapper::PointType t, - NR::Point const &p, - bool const &first_point, - std::vector &points_to_snap, - std::list const &it, - std::vector *unselected_nodes) const; + Inkscape::SnappedPoint freeSnap(Inkscape::Snapper::PointType t, + NR::Point const &p, + bool const &first_point, + std::vector &points_to_snap, + std::list const &it, + std::vector *unselected_nodes) const; Inkscape::SnappedPoint constrainedSnap(Inkscape::Snapper::PointType t, NR::Point const &p, @@ -78,43 +79,43 @@ public: Inkscape::SnappedPoint guideSnap(NR::Point const &p, NR::Point const &guide_normal) const; - std::pair freeSnapTranslation(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::Point const &tr) const; - - std::pair constrainedSnapTranslation(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - Inkscape::Snapper::ConstraintLine const &c, - NR::Point const &tr) const; - - std::pair freeSnapScale(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::scale const &s, - NR::Point const &o) const; - - std::pair constrainedSnapScale(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::scale const &s, - NR::Point const &o) const; - - std::pair constrainedSnapStretch(Inkscape::Snapper::PointType t, + Inkscape::SnappedPoint freeSnapTranslation(Inkscape::Snapper::PointType t, std::vector const &p, std::list const &it, - NR::Coord const &s, - NR::Point const &o, - NR::Dim2 d, - bool uniform) const; - - std::pair freeSnapSkew(Inkscape::Snapper::PointType t, - std::vector const &p, - std::list const &it, - NR::Coord const &s, - NR::Point const &o, - NR::Dim2 d) const; + NR::Point const &tr) const; + + Inkscape::SnappedPoint constrainedSnapTranslation(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + Inkscape::Snapper::ConstraintLine const &c, + NR::Point const &tr) const; + + Inkscape::SnappedPoint freeSnapScale(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::scale const &s, + NR::Point const &o) const; + + Inkscape::SnappedPoint constrainedSnapScale(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::scale const &s, + NR::Point const &o) const; + + Inkscape::SnappedPoint constrainedSnapStretch(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::Coord const &s, + NR::Point const &o, + NR::Dim2 d, + bool uniform) const; + + Inkscape::SnappedPoint freeSnapSkew(Inkscape::Snapper::PointType t, + std::vector const &p, + std::list const &it, + NR::Coord const &s, + NR::Point const &o, + NR::Dim2 d) const; Inkscape::SnappedPoint guideSnap(NR::Point const &p, Inkscape::ObjectSnapper::DimensionToSnap const snap_dim) const; @@ -177,16 +178,16 @@ private: bool _intersectionLS; bool _snap_enabled_globally; //Toggles ALL snapping - std::pair _snapTransformed(Inkscape::Snapper::PointType type, - std::vector const &points, - std::list const &ignore, - bool constrained, - Inkscape::Snapper::ConstraintLine const &constraint, - Transformation transformation_type, - NR::Point const &transformation, - NR::Point const &origin, - NR::Dim2 dim, - bool uniform) const; + Inkscape::SnappedPoint _snapTransformed(Inkscape::Snapper::PointType type, + std::vector const &points, + std::list const &ignore, + bool constrained, + Inkscape::Snapper::ConstraintLine const &constraint, + Transformation transformation_type, + NR::Point const &transformation, + NR::Point const &origin, + NR::Dim2 dim, + bool uniform) const; Inkscape::SnappedPoint findBestSnap(NR::Point const &p, SnappedConstraints &sc, bool constrained) const; }; diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp index 1ece54a5d..ae380b365 100644 --- a/src/snapped-point.cpp +++ b/src/snapped-point.cpp @@ -19,12 +19,14 @@ Inkscape::SnappedPoint::SnappedPoint(NR::Point p, NR::Coord d, NR::Coord t, bool _second_distance = NR_HUGE; _second_tolerance = 0; _second_always_snap = false; + _transformation = NR::Point(1,1); } Inkscape::SnappedPoint::SnappedPoint(NR::Point p, NR::Coord d, NR::Coord t, bool a, bool at_intersection, NR::Coord d2, NR::Coord t2, bool a2) : _point(p), _at_intersection(at_intersection), _distance(d), _tolerance(t), _always_snap(a), _second_distance(d2), _second_tolerance(t2), _second_always_snap(a2) { + _transformation = NR::Point(1,1); } Inkscape::SnappedPoint::SnappedPoint() @@ -37,6 +39,7 @@ Inkscape::SnappedPoint::SnappedPoint() _second_distance = NR_HUGE; _second_tolerance = 0; _second_always_snap = false; + _transformation = NR::Point(1,1); } diff --git a/src/snapped-point.h b/src/snapped-point.h index f0584812d..309e322a6 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -31,6 +31,7 @@ public: ~SnappedPoint(); NR::Coord getDistance() const; + void setDistance(NR::Coord d) {_distance = d;} NR::Coord getTolerance() const; bool getAlwaysSnap() const; NR::Coord getSecondDistance() const; @@ -38,6 +39,9 @@ public: bool getSecondAlwaysSnap() const; NR::Point getPoint() const; bool getAtIntersection() const {return _at_intersection;} + bool getSnapped() const {return _distance < NR_HUGE;} + NR::Point getTransformation() const {return _transformation;} + void setTransformation(NR::Point t) {_transformation = t;} protected: NR::Point _point; // Location of the snapped point @@ -59,6 +63,8 @@ protected: NR::Coord _second_tolerance; /* If true then "Always snap" is on */ bool _second_always_snap; + /* The transformation (translation, scale, skew, or stretch) from the original point to the snapped point */ + NR::Point _transformation; }; }