Code

Refactor snapper and snapindicator (in order to enable the snapindicator in the selec...
authordvlierop2 <dvlierop2@users.sourceforge.net>
Mon, 7 Apr 2008 19:28:34 +0000 (19:28 +0000)
committerdvlierop2 <dvlierop2@users.sourceforge.net>
Mon, 7 Apr 2008 19:28:34 +0000 (19:28 +0000)
14 files changed:
src/context-fns.cpp
src/desktop-events.cpp
src/display/snap-indicator.cpp
src/display/snap-indicator.h
src/draw-context.cpp
src/gradient-drag.cpp
src/nodepath.cpp
src/pencil-context.cpp
src/rect-context.cpp
src/seltrans.cpp
src/snap.cpp
src/snap.h
src/snapped-point.cpp
src/snapped-point.h

index 32c7eef000cf194356f6e57000f6b8fc58c48235..d7333adbe18097520b16106508e2a912fc81b948 100644 (file)
@@ -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]);
index dc153e31d94826c6f3814b8e763745365e76cb24..5b6972c33b5368c27b952c620df39fea08c26007 100644 (file)
@@ -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();
                 }
index f5e754d902bd452c3999c65d5249d27f10b60c51..03fcad484027eab5b54da16e0376ace969282b39 100644 (file)
@@ -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
     }
 }
index 0395d400081da696e96021034b26d43098d88714..c17de0494a5409e97e7f57e1780f6dc67d61d9e5 100644 (file)
@@ -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:
index adcbc3b3c994346b98a852fadaad0fdea47a1ea1..42555f8d299a7bf139a83514adfb765a782e1f31 100644 (file)
@@ -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);
     }
 }
 
index 6c960ed280da584f4ae0fb17466fe87ceca3324e..7a7957856c8096f496bc2db5aa57e7ae88ec503d 100644 (file)
@@ -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);
             }
         }
     }
index 250970dec4025b83319d048ac92b0ff535dba520..d6dbb19b480c6236163a88317f91fd4c3e2b24fa 100644 (file)
@@ -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);
index d27d363f9690c8523011d5e4ed1341f21f212558..878651ade939b02fcb799c8abfcd215edbbd54af 100644 (file)
@@ -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!
index a25b39961dd406bc0b1b72e0b07b7e08c08e426f..1054a2c55850eca3d481cc513ac3ecf9acc80483 100644 (file)
@@ -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);
index 5ab99e147b5c76d517a70ce5dc1258564ce84dbc..d248d31522e55c5d3e48f485899502828bf5fadf 100644 (file)
@@ -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<SPItem*>(i->data));
         }
         
-        std::pair<NR::scale, bool> bb = std::make_pair(NR::scale(1,1), false); 
-        std::pair<NR::scale, bool> 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<NR::Coord, bool> bb = std::make_pair(NR_HUGE, false)
-        std::pair<NR::Coord, bool> 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<NR::Coord, bool> bb = m.freeSnapSkew(Inkscape::Snapper::SNAPPOINT_BBOX, _bbox_points, it, skew[dim_a], _origin, dim_b);
-        std::pair<NR::Coord, bool> 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<std::pair<NR::Point, bool> > s;
+        std::list<Inkscape::SnappedPoint> 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<std::pair<NR::Point, bool> >::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<Inkscape::SnappedPoint>::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) {
index 639e704b0a57b10d56c667163058ea6961751cc0..76bda92822f9a2cb708d34163049291a54df1373 100644 (file)
@@ -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<NR::Point, bool> SnapManager::_snapTransformed(
+Inkscape::SnappedPoint SnapManager::_snapTransformed(
     Inkscape::Snapper::PointType type,
     std::vector<NR::Point> const &points,
     std::list<SPItem const *> const &ignore,
@@ -365,7 +365,7 @@ std::pair<NR::Point, bool> SnapManager::_snapTransformed(
     ** Also used to globally disable all snapping 
     */
     if (SomeSnapperMightSnap() == false) {
-        return std::make_pair(transformation, false);
+        return Inkscape::SnappedPoint();
     }
     
     std::vector<NR::Point> transformed_points;
@@ -414,17 +414,17 @@ std::pair<NR::Point, bool> 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<NR::Point>::const_iterator j = transformed_points.begin();
 
-    //std::cout << std::endl;
-    
+    // std::cout << std::endl;
     for (std::vector<NR::Point>::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<NR::Point, bool> 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<NR::Point, bool> 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<NR::Point, bool> 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<NR::Point, bool> 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<NR::Point, bool> 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<NR::Point, bool> 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<NR::Point, bool> 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<NR::Point, bool> SnapManager::_snapTransformed(
  *  \return Snapped translation, if a snap occurred, and a flag indicating whether a snap occurred.
  */
 
-std::pair<NR::Point, bool> SnapManager::freeSnapTranslation(Inkscape::Snapper::PointType t,
-                                                            std::vector<NR::Point> const &p,
-                                                            std::list<SPItem const *> const &it,
-                                                            NR::Point const &tr) const
+Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::Snapper::PointType t,
+                                                        std::vector<NR::Point> const &p,
+                                                        std::list<SPItem const *> 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<NR::Point, bool> SnapManager::freeSnapTranslation(Inkscape::Snapper::P
  *  \return Snapped translation, if a snap occurred, and a flag indicating whether a snap occurred.
  */
 
-std::pair<NR::Point, bool> SnapManager::constrainedSnapTranslation(Inkscape::Snapper::PointType t,
-                                                                   std::vector<NR::Point> const &p,
-                                                                   std::list<SPItem const *> const &it,
-                                                                   Inkscape::Snapper::ConstraintLine const &c,
-                                                                   NR::Point const &tr) const
+Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::Snapper::PointType t,
+                                                               std::vector<NR::Point> const &p,
+                                                               std::list<SPItem const *> 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<NR::Point, bool> SnapManager::constrainedSnapTranslation(Inkscape::Sna
  *  \return Snapped scale, if a snap occurred, and a flag indicating whether a snap occurred.
  */
 
-std::pair<NR::scale, bool> SnapManager::freeSnapScale(Inkscape::Snapper::PointType t,
-                                                      std::vector<NR::Point> const &p,
-                                                      std::list<SPItem const *> const &it,
-                                                      NR::scale const &s,
-                                                      NR::Point const &o) const
+Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::Snapper::PointType t,
+                                                  std::vector<NR::Point> const &p,
+                                                  std::list<SPItem const *> 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<NR::scale, bool> SnapManager::freeSnapScale(Inkscape::Snapper::PointTy
  *  \return Snapped scale, if a snap occurred, and a flag indicating whether a snap occurred.
  */
 
-std::pair<NR::scale, bool> SnapManager::constrainedSnapScale(Inkscape::Snapper::PointType t,
-                                                             std::vector<NR::Point> const &p,
-                                                             std::list<SPItem const *> const &it,
-                                                             NR::scale const &s,
-                                                             NR::Point const &o) const
+Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::Snapper::PointType t,
+                                                         std::vector<NR::Point> const &p,
+                                                         std::list<SPItem const *> 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<NR::scale, bool> SnapManager::constrainedSnapScale(Inkscape::Snapper::
  *  \return Snapped stretch, if a snap occurred, and a flag indicating whether a snap occurred.
  */
 
-std::pair<NR::Coord, bool> SnapManager::constrainedSnapStretch(Inkscape::Snapper::PointType t,
-                                                        std::vector<NR::Point> const &p,
-                                                        std::list<SPItem const *> 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<NR::Point> const &p,
+                                                            std::list<SPItem const *> const &it,
+                                                            NR::Coord const &s,
+                                                            NR::Point const &o,
+                                                            NR::Dim2 d,
+                                                            bool u) const
 {
-   std::pair<NR::Point, bool> 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<NR::Coord, bool> SnapManager::constrainedSnapStretch(Inkscape::Snapper
  *  \return Snapped skew, if a snap occurred, and a flag indicating whether a snap occurred.
  */
 
-std::pair<NR::Coord, bool> SnapManager::freeSnapSkew(Inkscape::Snapper::PointType t,
-                                                     std::vector<NR::Point> const &p,
-                                                     std::list<SPItem const *> const &it,
-                                                     NR::Coord const &s,
-                                                     NR::Point const &o,
-                                                     NR::Dim2 d) const
+Inkscape::SnappedPoint SnapManager::freeSnapSkew(Inkscape::Snapper::PointType t,
+                                                 std::vector<NR::Point> const &p,
+                                                 std::list<SPItem const *> const &it,
+                                                 NR::Coord const &s,
+                                                 NR::Point const &o,
+                                                 NR::Dim2 d) const
 {
-   std::pair<NR::Point, bool> 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
index bdaa27ea8be380ad3d67b62b447ed576d4e7f6cf..8bab5b0cf1d951b7c8f23a0918e008cd4964a9ce 100644 (file)
@@ -13,6 +13,7 @@
  *
  * Copyright (C) 2006-2007 Johan Engelen <johan@shouraizou.nl>
  * 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<NR::Point> *unselected_nodes) const;
     
-    Inkscape::SnappedPoint freeSnap( Inkscape::Snapper::PointType t,
-                                      NR::Point const &p,
-                                      bool const &first_point,
-                                      std::vector<NR::Point> &points_to_snap,
-                                      std::list<SPItem const *> const &it,
-                                      std::vector<NR::Point> *unselected_nodes) const;
+    Inkscape::SnappedPoint freeSnap(Inkscape::Snapper::PointType t,
+                                    NR::Point const &p,
+                                    bool const &first_point,
+                                    std::vector<NR::Point> &points_to_snap,
+                                    std::list<SPItem const *> const &it,
+                                    std::vector<NR::Point> *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<NR::Point, bool> freeSnapTranslation(Inkscape::Snapper::PointType t,
-                                                   std::vector<NR::Point> const &p,
-                                                   std::list<SPItem const *> const &it,
-                                                   NR::Point const &tr) const;
-
-    std::pair<NR::Point, bool> constrainedSnapTranslation(Inkscape::Snapper::PointType t,
-                                                          std::vector<NR::Point> const &p,
-                                                          std::list<SPItem const *> const &it,
-                                                          Inkscape::Snapper::ConstraintLine const &c,
-                                                          NR::Point const &tr) const;
-
-    std::pair<NR::scale, bool> freeSnapScale(Inkscape::Snapper::PointType t,
-                                             std::vector<NR::Point> const &p,
-                                             std::list<SPItem const *> const &it,
-                                             NR::scale const &s,
-                                             NR::Point const &o) const;
-
-    std::pair<NR::scale, bool> constrainedSnapScale(Inkscape::Snapper::PointType t,
-                                                    std::vector<NR::Point> const &p,
-                                                    std::list<SPItem const *> const &it,
-                                                    NR::scale const &s,
-                                                    NR::Point const &o) const;
-
-    std::pair<NR::Coord, bool> constrainedSnapStretch(Inkscape::Snapper::PointType t,
+    Inkscape::SnappedPoint freeSnapTranslation(Inkscape::Snapper::PointType t,
                                                std::vector<NR::Point> const &p,
                                                std::list<SPItem const *> const &it,
-                                               NR::Coord const &s,
-                                               NR::Point const &o,
-                                               NR::Dim2 d,
-                                               bool uniform) const;
-
-    std::pair<NR::Coord, bool> freeSnapSkew(Inkscape::Snapper::PointType t,
-                                            std::vector<NR::Point> const &p,
-                                            std::list<SPItem const *> 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<NR::Point> const &p,
+                                                      std::list<SPItem const *> const &it,
+                                                      Inkscape::Snapper::ConstraintLine const &c,
+                                                      NR::Point const &tr) const;
+
+    Inkscape::SnappedPoint freeSnapScale(Inkscape::Snapper::PointType t,
+                                         std::vector<NR::Point> const &p,
+                                         std::list<SPItem const *> const &it,
+                                         NR::scale const &s,
+                                         NR::Point const &o) const;
+
+    Inkscape::SnappedPoint constrainedSnapScale(Inkscape::Snapper::PointType t,
+                                                std::vector<NR::Point> const &p,
+                                                std::list<SPItem const *> const &it,
+                                                NR::scale const &s,
+                                                NR::Point const &o) const;
+
+    Inkscape::SnappedPoint constrainedSnapStretch(Inkscape::Snapper::PointType t,
+                                                   std::vector<NR::Point> const &p,
+                                                   std::list<SPItem const *> 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<NR::Point> const &p,
+                                        std::list<SPItem const *> 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<NR::Point, bool> _snapTransformed(Inkscape::Snapper::PointType type,
-                                                std::vector<NR::Point> const &points,
-                                                std::list<SPItem const *> 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<NR::Point> const &points,
+                                            std::list<SPItem const *> 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;
 };
index 1ece54a5ddc9cbf21e001ef88bae0c2cacc13167..ae380b365871e8c28b98b3214206759a6e391f38 100644 (file)
@@ -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);
 }
 
 
index f0584812d8a9814b6106067b01e87b06c9528880..309e322a6ed9600253c05c18b70f4e2ba5d5c4bc 100644 (file)
@@ -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;
 };    
 
 }