Code

2geom update (rev. 1578); fixes node editing of some degenerate paths
authorcilix42 <cilix42@users.sourceforge.net>
Mon, 8 Sep 2008 22:20:36 +0000 (22:20 +0000)
committercilix42 <cilix42@users.sourceforge.net>
Mon, 8 Sep 2008 22:20:36 +0000 (22:20 +0000)
src/2geom/bezier-curve.h
src/2geom/convex-cover.cpp
src/2geom/convex-cover.h
src/2geom/path.cpp
src/2geom/path.h
src/2geom/pathvector.cpp
src/2geom/pathvector.h
src/nodepath.cpp
src/shape-editor.cpp

index 244328f8af7a8ec80b5592021063d709e5fed590..45d0b61f30b27aeaefc6e38506e866a28bb96dc4 100644 (file)
@@ -202,7 +202,9 @@ double LineSegment::nearestPoint(Point const& p, double from, double to) const
        Point ip = pointAt(from);
        Point fp = pointAt(to);
        Point v = fp - ip;
-       double t = dot( p - ip, v ) / L2sq(v);
+        double l2v = L2sq(v);
+        if(l2v == 0) return 0;
+       double t = dot( p - ip, v ) / l2v;
        if ( t <= 0 )           return from;
        else if ( t >= 1 )  return to;
        else                            return from + t*(to-from);
index 7dca7f0ebb8180c01f2c240fd7b80a3fe7643782..5b6d36c493776fbbec4e4231dd592a29c45433e8 100644 (file)
@@ -136,6 +136,8 @@ ConvexHull::graham_scan() {
 
 void
 ConvexHull::graham() {
+    if(is_degenerate()) // nothing to do
+        return;
     find_pivot();
     angle_sort();
     graham_scan();
index 71a47bb98eda11a6e70242b4094e186477e7d0f9..ea8718c5af5269acd8c4af1f0b56e2865c3f84b2 100644 (file)
@@ -152,6 +152,8 @@ template <class T> ConvexHull operator*(ConvexHull const &p, T const &m) {
     return pr;
 }
 
+ConvexHull clip(ConvexHull const & ch, Point n, double d);
+
 //TODO: reinstate
 /*class ConvexCover{
 public:
index ac45459bd419779d07b6037ad5eac3ee40f76989..c04d9d08d4c7d3ddf134ffce434f6d0fd61602f5 100644 (file)
@@ -226,6 +226,11 @@ double Path::nearestPoint(Point const &_point, double from, double to, double *d
        double eif, et = modf(to, &eif);
        unsigned int si = static_cast<unsigned int>(sif);
        unsigned int ei = static_cast<unsigned int>(eif);
+        if(sz == 0) {// naked moveto
+            if (distance_squared != NULL)
+                *distance_squared = distanceSq(_point, _path.initialPoint());
+            return 0;
+        }
        if ( si == sz )
        {
                --si;
index 04b77862c25c715327b8e214cff6ec93964f1cfa..1b59ea011d4a566a31662ca0c128ac6826ea8f8d 100644 (file)
@@ -306,7 +306,7 @@ public:
          {
                  THROW_RANGEERROR("parameter t out of bounds");
          }
-         if ( empty() ) return Point(0,0);
+         if ( empty() ) return initialPoint(); // naked moveto
          double k, lt = modf(t, &k);
          unsigned int i = static_cast<unsigned int>(k);
          if ( i == sz ) 
@@ -325,7 +325,7 @@ public:
          {
                  THROW_RANGEERROR("parameter t out of bounds");
          }
-         if ( empty() ) return 0;
+         if ( empty() ) return initialPoint()[d]; // naked moveto
          double k, lt = modf(t, &k);
          unsigned int i = static_cast<unsigned int>(k);
          if ( i == sz ) 
index 6d4e24c9fee595b6729d814e4e659832888037ca..39a00d8dc44f3803de14679a64233615a3a0e0b1 100644 (file)
@@ -90,19 +90,19 @@ Rect bounds_exact( PathVector const& pv )
 
 /* Note: undefined for empty pathvectors or pathvectors with empty paths.
  * */
-PathVectorPosition nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared)
+boost::optional<PathVectorPosition> nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared)
 {
-    PathVectorPosition retval;
+    boost::optional<PathVectorPosition> retval;
 
     double mindsq = infinity();
     unsigned int i = 0;
     for (Geom::PathVector::const_iterator pit = path_in.begin(); pit != path_in.end(); ++pit) {
         double dsq;
         double t = pit->nearestPoint(_point, &dsq);
+        //std::cout << t << "," << dsq << std::endl;
         if (dsq < mindsq) {
             mindsq = dsq;
-            retval.path_nr = i;
-            retval.t       = t;
+            retval = PathVectorPosition(i, t);
         }
 
         ++i;
@@ -114,6 +114,30 @@ PathVectorPosition nearestPoint(PathVector const & path_in, Point const& _point,
     return retval;
 }
 
+std::vector<PathVectorPosition> allNearestPoints(PathVector const & path_in, Point const& _point, double *distance_squared)
+{
+    std::vector<PathVectorPosition> retval;
+
+    double mindsq = infinity();
+    unsigned int i = 0;
+    for (Geom::PathVector::const_iterator pit = path_in.begin(); pit != path_in.end(); ++pit) {
+        double dsq;
+        double t = pit->nearestPoint(_point, &dsq);
+        if (dsq < mindsq) {
+            mindsq = dsq;
+            retval.push_back(PathVectorPosition(i, t));
+        }
+
+        ++i;
+    }
+
+    if (distance_squared) {
+        *distance_squared = mindsq;
+    }
+    return retval;
+
+}
+
 } // namespace Geom
 
 #endif // SEEN_GEOM_PATHVECTOR_CPP
index cec1c144a0ebcff0e3f1e3b6e162b6ebc0dbfd13..cdc774c557bb39540b93c8d8d2f6254c7ec6aa62 100644 (file)
@@ -108,8 +108,19 @@ struct PathVectorPosition {
     // pathvector[path_nr].pointAt(t) is the position
     unsigned int path_nr;
     double       t;
+    PathVectorPosition() {}
+    PathVectorPosition(unsigned int path_nr,
+                       double       t) : path_nr(path_nr), t(t) {}
 };
-PathVectorPosition nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared = NULL);
+boost::optional<PathVectorPosition> nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared = NULL);
+
+std::vector<PathVectorPosition> allNearestPoints(PathVector const & path_in, Point const& _point, double *distance_squared = NULL);
+
+inline
+Point pointAt(PathVector const & path_in, PathVectorPosition const pvp) {
+    return path_in[pvp.path_nr].pointAt(pvp.t);
+}
+
 
 
 } // end namespace Geom
index e049c40df15bd025f9beee813879d1732726a820..5345485e2fb682a86d0bced868765de0618649da 100644 (file)
@@ -1960,11 +1960,15 @@ sp_nodepath_select_segment_near_point(Inkscape::NodePath::Path *nodepath, NR::Po
 
     SPCurve *curve = create_curve(nodepath);   // perhaps we can use nodepath->curve here instead?
     Geom::PathVector const &pathv = curve->get_pathvector();
-    Geom::PathVectorPosition pvpos = Geom::nearestPoint(pathv, p);
+    boost::optional<Geom::PathVectorPosition> pvpos = Geom::nearestPoint(pathv, p);
+    if (!pvpos) {
+        g_print ("Possible error?\n");
+        return;
+    }
 
     // calculate index for nodepath's representation.
-    unsigned int segment_index = floor(pvpos.t) + 1;
-    for (unsigned int i = 0; i < pvpos.path_nr; ++i) {
+    unsigned int segment_index = floor(pvpos->t) + 1;
+    for (unsigned int i = 0; i < pvpos->path_nr; ++i) {
         segment_index += pathv[i].size() + 1;
         if (pathv[i].closed()) {
             segment_index += 1;
@@ -2004,13 +2008,17 @@ sp_nodepath_add_node_near_point(Inkscape::NodePath::Path *nodepath, NR::Point p)
 
     SPCurve *curve = create_curve(nodepath);   // perhaps we can use nodepath->curve here instead?
     Geom::PathVector const &pathv = curve->get_pathvector();
-    Geom::PathVectorPosition pvpos = Geom::nearestPoint(pathv, p);
+    boost::optional<Geom::PathVectorPosition> pvpos = Geom::nearestPoint(pathv, p);
+    if (!pvpos) {
+        g_print ("Possible error?\n");
+        return;
+    }
 
     // calculate index for nodepath's representation.
     double int_part;
-    double t = std::modf(pvpos.t, &int_part);
+    double t = std::modf(pvpos->t, &int_part);
     unsigned int segment_index = (unsigned int)int_part + 1;
-    for (unsigned int i = 0; i < pvpos.path_nr; ++i) {
+    for (unsigned int i = 0; i < pvpos->path_nr; ++i) {
         segment_index += pathv[i].size() + 1;
         if (pathv[i].closed()) {
             segment_index += 1;
index f7aefdabec85566f038a04c5738b3bb03910fe4b..32c20ace698a6fd1f751b71207563ed266b5f5d7 100644 (file)
@@ -366,9 +366,13 @@ bool ShapeEditor::is_over_stroke (NR::Point event_p, bool remember) {
 
     SPCurve *curve = this->nodepath->curve;   // not sure if np->curve is always up to date...
     Geom::PathVector const &pathv = curve->get_pathvector();
-    Geom::PathVectorPosition pvpos = Geom::nearestPoint(pathv, this->curvepoint_doc);
+    boost::optional<Geom::PathVectorPosition> pvpos = Geom::nearestPoint(pathv, this->curvepoint_doc);
+    if (!pvpos) {
+        g_print("Warning! Possible error?\n");
+        return false;
+    }
 
-    NR::Point nearest = pathv[pvpos.path_nr].pointAt(pvpos.t);
+    NR::Point nearest = pathv[pvpos->path_nr].pointAt(pvpos->t);
     NR::Point delta = nearest - this->curvepoint_doc;
 
     delta = desktop->d2w(delta);
@@ -385,9 +389,9 @@ bool ShapeEditor::is_over_stroke (NR::Point event_p, bool remember) {
     if (remember && close) {
         // calculate index for nodepath's representation.
         double int_part;
-        double t = std::modf(pvpos.t, &int_part);
+        double t = std::modf(pvpos->t, &int_part);
         unsigned int segment_index = (unsigned int)int_part + 1;
-        for (unsigned int i = 0; i < pvpos.path_nr; ++i) {
+        for (unsigned int i = 0; i < pvpos->path_nr; ++i) {
             segment_index += pathv[i].size() + 1;
             if (pathv[i].closed())
                 segment_index += 1;