From 6bd282f1511dc25162bbc6c63f42aa218f40ef17 Mon Sep 17 00:00:00 2001 From: cilix42 Date: Mon, 8 Sep 2008 22:20:36 +0000 Subject: [PATCH] 2geom update (rev. 1578); fixes node editing of some degenerate paths --- src/2geom/bezier-curve.h | 4 +++- src/2geom/convex-cover.cpp | 2 ++ src/2geom/convex-cover.h | 2 ++ src/2geom/path.cpp | 5 +++++ src/2geom/path.h | 4 ++-- src/2geom/pathvector.cpp | 32 ++++++++++++++++++++++++++++---- src/2geom/pathvector.h | 13 ++++++++++++- src/nodepath.cpp | 20 ++++++++++++++------ src/shape-editor.cpp | 12 ++++++++---- 9 files changed, 76 insertions(+), 18 deletions(-) diff --git a/src/2geom/bezier-curve.h b/src/2geom/bezier-curve.h index 244328f8a..45d0b61f3 100644 --- a/src/2geom/bezier-curve.h +++ b/src/2geom/bezier-curve.h @@ -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); diff --git a/src/2geom/convex-cover.cpp b/src/2geom/convex-cover.cpp index 7dca7f0eb..5b6d36c49 100644 --- a/src/2geom/convex-cover.cpp +++ b/src/2geom/convex-cover.cpp @@ -136,6 +136,8 @@ ConvexHull::graham_scan() { void ConvexHull::graham() { + if(is_degenerate()) // nothing to do + return; find_pivot(); angle_sort(); graham_scan(); diff --git a/src/2geom/convex-cover.h b/src/2geom/convex-cover.h index 71a47bb98..ea8718c5a 100644 --- a/src/2geom/convex-cover.h +++ b/src/2geom/convex-cover.h @@ -152,6 +152,8 @@ template ConvexHull operator*(ConvexHull const &p, T const &m) { return pr; } +ConvexHull clip(ConvexHull const & ch, Point n, double d); + //TODO: reinstate /*class ConvexCover{ public: diff --git a/src/2geom/path.cpp b/src/2geom/path.cpp index ac45459bd..c04d9d08d 100644 --- a/src/2geom/path.cpp +++ b/src/2geom/path.cpp @@ -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(sif); unsigned int ei = static_cast(eif); + if(sz == 0) {// naked moveto + if (distance_squared != NULL) + *distance_squared = distanceSq(_point, _path.initialPoint()); + return 0; + } if ( si == sz ) { --si; diff --git a/src/2geom/path.h b/src/2geom/path.h index 04b77862c..1b59ea011 100644 --- a/src/2geom/path.h +++ b/src/2geom/path.h @@ -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(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(k); if ( i == sz ) diff --git a/src/2geom/pathvector.cpp b/src/2geom/pathvector.cpp index 6d4e24c9f..39a00d8dc 100644 --- a/src/2geom/pathvector.cpp +++ b/src/2geom/pathvector.cpp @@ -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 nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared) { - PathVectorPosition retval; + boost::optional 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 allNearestPoints(PathVector const & path_in, Point const& _point, double *distance_squared) +{ + std::vector 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 diff --git a/src/2geom/pathvector.h b/src/2geom/pathvector.h index cec1c144a..cdc774c55 100644 --- a/src/2geom/pathvector.h +++ b/src/2geom/pathvector.h @@ -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 nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared = NULL); + +std::vector 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 diff --git a/src/nodepath.cpp b/src/nodepath.cpp index e049c40df..5345485e2 100644 --- a/src/nodepath.cpp +++ b/src/nodepath.cpp @@ -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 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 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; diff --git a/src/shape-editor.cpp b/src/shape-editor.cpp index f7aefdabe..32c20ace6 100644 --- a/src/shape-editor.cpp +++ b/src/shape-editor.cpp @@ -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 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; -- 2.30.2