Code

make tolerance range exponential
[inkscape.git] / src / pencil-context.cpp
index ae3a2fa48dcb10980b6136bab98f4b867d2f0eb8..397a5a0ffb0d7cb52f3f6c51b58424c782c5d762 100644 (file)
@@ -62,6 +62,8 @@ static void fit_and_split(SPPencilContext *pc);
 
 
 static SPDrawContextClass *pencil_parent_class;
+static NR::Point pencil_drag_origin_w(0, 0);
+static bool pencil_within_tolerance = false;
 
 /**
  * Register SPPencilContext class with Gdk and return its type number.
@@ -222,6 +224,9 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
         /* Test whether we hit any anchor. */
         SPDrawAnchor *anchor = spdc_test_inside(pc, button_w);
 
+        pencil_drag_origin_w = NR::Point(bevent.x,bevent.y);
+        pencil_within_tolerance = true;
+
         switch (pc->state) {
             case SP_PENCIL_CONTEXT_ADDLINE:
                 /* Current segment will be finished with release */
@@ -248,7 +253,7 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
                         desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new path"));
                         SnapManager &m = desktop->namedview->snap_manager;
                         m.setup(desktop);
-                        p = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, p).getPoint();
+                        m.freeSnapReturnByRef(Inkscape::Snapper::SNAPPOINT_NODE, p);
                     } else if (selection->singleItem() && SP_IS_PATH(selection->singleItem())) {
                         desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Appending to selected path"));
                     }
@@ -297,6 +302,19 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev
     /* Test whether we hit any anchor. */
     SPDrawAnchor *anchor = spdc_test_inside(pc, NR::Point(mevent.x, mevent.y));
 
+    if (pencil_within_tolerance) {
+        gint const tolerance = prefs_get_int_attribute_limited("options.dragtolerance",
+                                                               "value", 0, 0, 100);
+        if ( NR::LInfty( NR::Point(mevent.x,mevent.y) - pencil_drag_origin_w ) < tolerance ) {
+            return FALSE;   // Do not drag if we're within tolerance from origin.
+        }
+    }
+
+    // Once the user has moved farther than tolerance from the original location
+    // (indicating they intend to move the object, not click), then always process the
+    // motion notify coordinates as given (no snapping back to origin)
+    pencil_within_tolerance = false;
+
     switch (pc->state) {
         case SP_PENCIL_CONTEXT_ADDLINE:
             /* Set red endpoint */
@@ -325,8 +343,7 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev
                 } else if ((mevent.state & GDK_SHIFT_MASK) == 0) {
                     SnapManager &m = dt->namedview->snap_manager;
                     m.setup(dt, NULL);
-                    Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, p);
-                    p = s.getPoint();
+                    m.freeSnapReturnByRef(Inkscape::Snapper::SNAPPOINT_NODE, p);
                 }
                 if ( pc->npoints != 0 ) { // buttonpress may have happened before we entered draw context!
                     spdc_add_freehand_point(pc, p, mevent.state);
@@ -571,9 +588,8 @@ spdc_set_endpoint(SPPencilContext *const pc, NR::Point const p)
 static void
 spdc_finish_endpoint(SPPencilContext *const pc)
 {
-    if ( ( SP_CURVE_LENGTH(pc->red_curve) != 2 )
-         || ( SP_CURVE_SEGMENT(pc->red_curve, 0)->c(3) ==
-              SP_CURVE_SEGMENT(pc->red_curve, 1)->c(3)   ) )
+    if ( ( pc->red_curve->is_empty() )
+         || ( pc->red_curve->first_point() == pc->red_curve->second_point()   ) )
     {
         pc->red_curve->reset();
         sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), NULL);
@@ -610,9 +626,9 @@ fit_and_split(SPPencilContext *pc)
 {
     g_assert( pc->npoints > 1 );
 
-    double const tolerance_sq = square( NR::expansion(pc->desktop->w2d())
-                                        * prefs_get_double_attribute_limited("tools.freehand.pencil",
-                                                                             "tolerance", 10.0, 1.0, 100.0) );
+    double const tol = prefs_get_double_attribute_limited("tools.freehand.pencil",                                                                             "tolerance", 10.0, 1.0, 100.0);
+    double const tolerance_sq = 0.02 * square( NR::expansion(pc->desktop->w2d()) * tol) 
+        * exp(0.2*tol - 2);
 
     NR::Point b[4];
     g_assert(is_zero(pc->req_tangent)
@@ -636,12 +652,11 @@ fit_and_split(SPPencilContext *pc)
 
         /* Set up direction of next curve. */
         {
-            NArtBpath const &last_seg = *pc->red_curve->last_bpath();
-            pc->p[0] = last_seg.c(3);
+            Geom::CubicBezier const * last_seg = dynamic_cast<Geom::CubicBezier const *>(pc->red_curve->last_segment());
+            g_assert( last_seg );      // Relevance: validity of (*last_seg)[2]
+            pc->p[0] = last_seg->finalPoint();
             pc->npoints = 1;
-            g_assert( last_seg.code == NR_CURVETO );
-            /* Relevance: validity of last_seg.c(2). */
-            NR::Point const req_vec( pc->p[0] - last_seg.c(2) );
+            NR::Point const req_vec( pc->p[0] - (*last_seg)[2] );
             pc->req_tangent = ( ( NR::is_zero(req_vec) || !in_svg_plane(req_vec) )
                                 ? NR::Point(0, 0)
                                 : NR::unit_vector(req_vec) );