Code

update to 2geom rev. 1507
authorjohanengelen <johanengelen@users.sourceforge.net>
Fri, 25 Jul 2008 21:03:44 +0000 (21:03 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Fri, 25 Jul 2008 21:03:44 +0000 (21:03 +0000)
25 files changed:
src/2geom/convex-cover.cpp
src/2geom/convex-cover.h
src/2geom/coord.h
src/2geom/hvlinesegment.h
src/2geom/interval.h
src/2geom/matrix.cpp
src/2geom/path.cpp
src/2geom/path.h
src/2geom/pathvector.cpp
src/2geom/pathvector.h
src/2geom/svg-path.h
src/display/inkscape-cairo.cpp
src/extension/internal/latex-pstricks.cpp
src/extension/internal/odf.cpp
src/extension/internal/pov-out.cpp
src/extension/internal/ps.cpp
src/helper/geom.cpp
src/livarot/PathCutting.cpp
src/live_effects/lpe-copy_rotate.cpp
src/live_effects/lpe-offset.cpp
src/live_effects/lpe-spiro.cpp
src/nodepath.cpp
src/sp-path.cpp
src/sp-polygon.cpp
src/svg/svg-path.cpp

index 7127a7c097ec5a6132d3a4f446f57716b3dcf6d0..7dca7f0ebb8180c01f2c240fd7b80a3fe7643782 100644 (file)
@@ -433,6 +433,66 @@ ConvexHull graham_merge(ConvexHull a, ConvexHull b) {
     }
 }*/
 
+double ConvexHull::centroid_and_area(Geom::Point& centroid) const {
+    const unsigned n = boundary.size();
+    if (n < 2)
+        return 0;
+    if(n < 3) {
+        centroid = (boundary[0] + boundary[1])/2;
+        return 0;
+    }
+    Geom::Point centroid_tmp(0,0);
+    double atmp = 0;
+    for (unsigned i = n-1, j = 0; j < n; i = j, j++) {
+        const double ai = -cross(boundary[j], boundary[i]);
+        atmp += ai;
+        centroid_tmp += (boundary[j] + boundary[i])*ai; // first moment.
+    }
+    if (atmp != 0) {
+        centroid = centroid_tmp / (3 * atmp);
+    }
+    return atmp / 2;
+}
+
+// TODO: This can be made lg(n) using golden section/fibonacci search three starting points, say 0,
+// n/2, n-1 construct a new point, say (n/2 + n)/2 throw away the furthest boundary point iterate
+// until interval is a single value
+Point const * ConvexHull::furthest(Point direction) const {
+    Point const * p = &boundary[0];
+    double d = dot(*p, direction);
+    for(unsigned i = 1; i < boundary.size(); i++) {
+        double dd = dot(boundary[i], direction);
+        if(d < dd) {
+            p = &boundary[i];
+            d = dd;
+        }
+    }
+    return p;
+}
+
+
+// returns (a, (b,c)), three points which define the narrowest diameter of the hull as the pair of
+// lines going through b,c, and through a, parallel to b,c TODO: This can be made linear time by
+// moving point tc incrementally from the previous value (it can only move in one direction).  It
+// is currently n*O(furthest)
+double ConvexHull::narrowest_diameter(Point &a, Point &b, Point &c) {
+    Point tb = boundary.back();
+    double d = INFINITY;
+    for(unsigned i = 0; i < boundary.size(); i++) {
+        Point tc = boundary[i];
+        Point n = -rot90(tb-tc);
+        Point ta = *furthest(n);
+        double td = dot(n, ta-tb)/dot(n,n);
+        if(td < d) {
+            a = ta;
+            b = tb;
+            c = tc;
+            d = td;
+        }
+        tb = tc;
+    }
+    return d;
+}
 
 };
 
index 1fe86e40d85b4215f7ba60ae70d536b4a91133c4..71a47bb98eda11a6e70242b4094e186477e7d0f9 100644 (file)
@@ -106,13 +106,18 @@ public:
     bool is_degenerate() const;
     
     // area of the convex hull
-    double area() const;
+    double centroid_and_area(Geom::Point& centroid) const;
+    double area() const {
+        Point tmp;
+        return centroid_and_area(tmp);
+    }
     
     // furthest point in a direction (lg time) 
     Point const * furthest(Point direction) const;
 
     bool is_left(Point p, int n);
     int find_left(Point p);
+    double narrowest_diameter(Point &a, Point &b, Point &c);
 };
 
 // do two convex hulls intersect?
index b2c2a4766f5bbba23c50d4b56d78dc8148707f24..99e249e29435c11927f1ad1754fc913c5f9ee9f7 100644 (file)
@@ -32,6 +32,7 @@
 #define SEEN_Geom_COORD_H
 
 #include <cmath>
+#include <limits>
 
 namespace Geom {
 
@@ -45,7 +46,8 @@ namespace Geom {
 typedef double Coord;
 
 const Coord EPSILON = 1e-5; //1e-18;
-const Coord COORD_HUGE = 1e18;
+
+inline Coord infinity() {  return std::numeric_limits<Coord>::infinity();  }
 
 //IMPL: NearConcept
 inline bool are_near(Coord a, Coord b, double eps=EPSILON) { return fabs(a-b) <= eps; }
index a34c5a962dc0060dac8492c0b0d0094ba3be0711..66de31d70364b8ef4f0071d51db8bd7385e20042 100644 (file)
@@ -41,208 +41,212 @@ namespace Geom
 class HLineSegment : public Curve
 {
   public:
-       HLineSegment()
-       {}
-       
-       HLineSegment(Coord _x0, Coord _x1, Coord _y)
-               : m_line_seg(Point(_x0, _y), Point(_x1, _y))
-       {
-       }
-       
-       HLineSegment(Point const& _p, double _length)
-               : m_line_seg(_p, Point(_p[X] + _length, _p[Y]))
-       {
-       }
-       
-       HLineSegment(Point const& _p0, Point const& _p1)
-               : m_line_seg(_p0, _p1)
-       {
-               if ( _p0[Y] != _p1[Y] )
-               {
-                       THROW_RANGEERROR("HLineSegment::HLineSegment passed points should "
-                                                "have the same Y value");
-               }
-       }
-       
-       Curve* duplicate() const
-       {
-               return new HLineSegment(*this);
-       }
-       
-       bool isDegenerate() const
-       {
-               return m_line_seg.isDegenerate();
-       }
-       
-       Point initialPoint() const
-       {
-               return m_line_seg.initialPoint();
-       }
-       
-       Point finalPoint() const 
-       {
-               return m_line_seg.finalPoint();
-       }
-       
-       Coord getY()
-       {
-               return initialPoint()[Y];
-       }
-       
-       void setInitial(Point _p) 
-       { 
-               m_line_seg.setInitial( Point(_p[X], initialPoint()[Y]) ); 
-       }
-       
-       void setFinal(Point _p) 
-       { 
-               m_line_seg.setFinal( Point(_p[X], finalPoint()[Y]) ); 
-       }
-       
-       void setX0(Coord _x)
-       {
-               m_line_seg.setInitial( Point(_x, initialPoint()[Y]) );
-       }
-       
-       void setX1(Coord _x)
-       {
-               m_line_seg.setFinal( Point(_x, finalPoint()[Y]) );
-       }
-       
-       void setY(Coord _y)
-       {
-               m_line_seg.setInitial( Point(initialPoint()[X], _y) );
-               m_line_seg.setFinal( Point(finalPoint()[X], _y) );
-       }
-
-       Rect boundsFast() const
-       {
-               return boundsExact();
-       }
-       
-       Rect boundsExact() const
-       {
-               return Rect( initialPoint(), finalPoint() );
-       }
-       
-       Rect boundsLocal(Interval i, unsigned deg) const
-       {
-               return m_line_seg.boundsLocal(i, deg);
-       }
-       
-       int winding(Point p) const
-       {
-               return m_line_seg.winding(p);
-       }
-       
-       std::vector<double>
-       roots(double v, Dim2 d) const
-       {
-               if (d < 0 || d > 1)
-               {
-                       THROW_RANGEERROR("dimension argument out of range");
-               }
-               std::vector<double> result;
-               if (d == X)
-               {
-                       if ( v >= initialPoint()[X] && v <= finalPoint()[X] )
-                       {
-                               double t = 0;
-                               if (!isDegenerate())
-                                       t = (v - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]);
-                               result.push_back(t);
-                       }
-               }
-               else
-               {
-                       if (v == initialPoint()[Y])
-                       {
-                               if (!isDegenerate())
-                                       THROW_INFINITESOLUTIONS(0);
-                               result.push_back(0);
-                       }
-               }
-               return result;
-       }
-       
-       double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
-       {
-               if ( from > to ) std::swap(from, to);
-               double xfrom = pointAt(from)[X];
-               double xto = pointAt(to)[X];
-               if ( xfrom > xto )
-               {
-                   std::swap(xfrom, xto);
-                   std::swap(from, to);
-               }
-               if ( p[X] > xfrom && p[X] < xto )
-               {
-                       return (p[X] - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]);
-               }
-               else if ( p[X] <= xfrom )
-                       return from;
-               else
-                       return to;
-       }
-       
-       std::pair<HLineSegment, HLineSegment> subdivide(Coord t) const
-       {
-               std::pair<HLineSegment, HLineSegment> result;
-               Point p = pointAt(t);
-               result.first.setInitial(initialPoint());
-               result.first.setFinal(p);
-               result.second.setInitial(p);
-               result.second.setFinal(finalPoint());
-               return result;
-       }
-       
-       Curve* portion(double f, double t) const
-       {
-               Point ip = pointAt(f);
-               Point ep = pointAt(t);
-               return new HLineSegment(ip[X], ep[X], ip[Y]);
-       }
-       
-       Curve* reverse() const
-       {
-               return 
-               new HLineSegment(finalPoint()[X], initialPoint()[X], initialPoint()[Y]);
-       }
-       
-       Curve* transformed(Matrix const & m) const
-       {
-               Point ip = initialPoint() * m;
-               Point ep = finalPoint() * m;
-               return new LineSegment(ip, ep);
-       }
-       
-       Curve* derivative() const
-       {
-               double x = finalPoint()[X] - initialPoint()[X];
-               return new HLineSegment(x, x, 0);
-       }
-       
-       Point pointAt(double t) const
-       {
-               if ( t < 0 || t > 1 )
-                       THROW_RANGEERROR("domain parameter out of range");
-               double x = initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]);
-               return Point(x, initialPoint()[Y]);
-       }
-       
-       double valueAt(double t, Dim2 d) const
-       {
-               if (d < 0 || d > 1)
-               {
-                       THROW_RANGEERROR("dimension argument out of range");
-               }
-               if ( t < 0 || t > 1 )
-                       THROW_RANGEERROR("domain parameter out of range");
-               
-               if (d == Y) return initialPoint()[Y];
-               
-               return initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]);
-       }
+    HLineSegment()
+    {}
+
+    HLineSegment(Coord _x0, Coord _x1, Coord _y)
+        : m_line_seg(Point(_x0, _y), Point(_x1, _y))
+    {
+    }
+
+    HLineSegment(Point const& _p, double _length)
+        : m_line_seg(_p, Point(_p[X] + _length, _p[Y]))
+    {
+    }
+
+    HLineSegment(Point const& _p0, Point const& _p1)
+        : m_line_seg(_p0, _p1)
+    {
+        if ( _p0[Y] != _p1[Y] )
+        {
+            THROW_RANGEERROR("HLineSegment::HLineSegment passed points should "
+                             "have the same Y value");
+        }
+    }
+
+    Curve* duplicate() const
+    {
+        return new HLineSegment(*this);
+    }
+
+    bool isDegenerate() const
+    {
+        return m_line_seg.isDegenerate();
+    }
+
+    Point initialPoint() const
+    {
+        return m_line_seg.initialPoint();
+    }
+
+    Point finalPoint() const
+    {
+        return m_line_seg.finalPoint();
+    }
+
+    Coord getY()
+    {
+        return initialPoint()[Y];
+    }
+
+    void setInitial(Point _p)
+    {
+        m_line_seg.setInitial( Point(_p[X], initialPoint()[Y]) );
+    }
+
+    void setFinal(Point _p)
+    {
+        m_line_seg.setFinal( Point(_p[X], finalPoint()[Y]) );
+    }
+
+    void setX0(Coord _x)
+    {
+        m_line_seg.setInitial( Point(_x, initialPoint()[Y]) );
+    }
+
+    void setX1(Coord _x)
+    {
+        m_line_seg.setFinal( Point(_x, finalPoint()[Y]) );
+    }
+
+    void setY(Coord _y)
+    {
+        m_line_seg.setInitial( Point(initialPoint()[X], _y) );
+        m_line_seg.setFinal( Point(finalPoint()[X], _y) );
+    }
+
+    Rect boundsFast() const
+    {
+        return boundsExact();
+    }
+
+    Rect boundsExact() const
+    {
+        return Rect( initialPoint(), finalPoint() );
+    }
+
+    Rect boundsLocal(Interval i, unsigned deg) const
+    {
+        return m_line_seg.boundsLocal(i, deg);
+    }
+
+    int winding(Point p) const
+    {
+        return m_line_seg.winding(p);
+    }
+
+    std::vector<double>
+    roots(double v, Dim2 d) const
+    {
+        if (d < 0 || d > 1)
+        {
+            THROW_RANGEERROR("dimension argument out of range");
+        }
+        std::vector<double> result;
+        if (d == X)
+        {
+            if ( v >= initialPoint()[X] && v <= finalPoint()[X] )
+            {
+                double t = 0;
+                if (!isDegenerate())
+                    t = (v - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]);
+                result.push_back(t);
+            }
+        }
+        else
+        {
+            if (v == initialPoint()[Y])
+            {
+                if (!isDegenerate())
+                    THROW_INFINITESOLUTIONS(0);
+                result.push_back(0);
+            }
+        }
+        return result;
+    }
+
+    double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
+    {
+        if ( from > to ) std::swap(from, to);
+        double xfrom = pointAt(from)[X];
+        double xto = pointAt(to)[X];
+        if ( xfrom > xto )
+        {
+            std::swap(xfrom, xto);
+            std::swap(from, to);
+        }
+        if ( p[X] > xfrom && p[X] < xto )
+        {
+            return (p[X] - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]);
+        }
+        else if ( p[X] <= xfrom )
+            return from;
+        else
+            return to;
+    }
+
+    std::pair<HLineSegment, HLineSegment> subdivide(Coord t) const
+    {
+        std::pair<HLineSegment, HLineSegment> result;
+        Point p = pointAt(t);
+        result.first.setInitial(initialPoint());
+        result.first.setFinal(p);
+        result.second.setInitial(p);
+        result.second.setFinal(finalPoint());
+        return result;
+    }
+
+    Curve* portion(double f, double t) const
+    {
+        Point ip = pointAt(f);
+        Point ep = pointAt(t);
+        return new HLineSegment(ip[X], ep[X], ip[Y]);
+    }
+
+    Curve* reverse() const
+    {
+        return
+        new HLineSegment(finalPoint()[X], initialPoint()[X], initialPoint()[Y]);
+    }
+
+    Curve* transformed(Matrix const & m) const
+    {
+        Point ip = initialPoint() * m;
+        Point ep = finalPoint() * m;
+        if (m.onlyScaleAndTranslation()) {
+            return new HLineSegment(ip[X], ep[X], ip[Y]);
+        } else {
+            return new LineSegment(ip, ep);
+        }
+    }
+
+    Curve* derivative() const
+    {
+        double x = finalPoint()[X] - initialPoint()[X];
+        return new HLineSegment(x, x, 0);
+    }
+
+    Point pointAt(double t) const
+    {
+        if ( t < 0 || t > 1 )
+            THROW_RANGEERROR("domain parameter out of range");
+        double x = initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]);
+        return Point(x, initialPoint()[Y]);
+    }
+
+    double valueAt(double t, Dim2 d) const
+    {
+        if (d < 0 || d > 1)
+        {
+            THROW_RANGEERROR("dimension argument out of range");
+        }
+        if ( t < 0 || t > 1 )
+            THROW_RANGEERROR("domain parameter out of range");
+
+        if (d == Y) return initialPoint()[Y];
+
+        return initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]);
+    }
 
     std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const
     {
@@ -262,222 +266,226 @@ class HLineSegment : public Curve
         return result;
     }
 
-       D2<SBasis> toSBasis() const
-       {
-               return m_line_seg.toSBasis();
-       }
-       
+    D2<SBasis> toSBasis() const
+    {
+        return m_line_seg.toSBasis();
+    }
+
   private:
-       LineSegment m_line_seg;
-       
+    LineSegment m_line_seg;
+
 };  // end class HLineSegment
 
 
 class VLineSegment : public Curve
 {
   public:
-       VLineSegment()
-       {}
-       
-       VLineSegment(Coord _x, Coord _y0, Coord _y1)
-               : m_line_seg(Point(_x, _y0), Point(_x, _y1))
-       {
-       }
-       
-       VLineSegment(Point const& _p, double _length)
-               : m_line_seg(_p, Point(_p[X], _p[Y] + _length))
-       {
-       }
-       
-       VLineSegment(Point const& _p0, Point const& _p1)
-               : m_line_seg(_p0, _p1)
-       {
-               if ( _p0[X] != _p1[X] )
-               {
-                       THROW_RANGEERROR("VLineSegment::VLineSegment passed points should "
-                                                "have the same X value");
-               }
-       }
-       
-       Curve* duplicate() const
-       {
-               return new VLineSegment(*this);
-       }
-       
-       bool isDegenerate() const
-       {
-               return m_line_seg.isDegenerate();
-       }
-       
-       Point initialPoint() const
-       {
-               return m_line_seg.initialPoint();
-       }
-       
-       Point finalPoint() const 
-       {
-               return m_line_seg.finalPoint();
-       }
-       
-       Coord getX()
-       {
-               return initialPoint()[X];
-       }
-       
-       void setInitial(Point _p) 
-       { 
-               m_line_seg.setInitial( Point(initialPoint()[X], _p[Y]) ); 
-       }
-       
-       void setFinal(Point _p) 
-       { 
-               m_line_seg.setFinal( Point(finalPoint()[X], _p[Y]) ); 
-       }
-       
-       void setY0(Coord _y)
-       {
-               m_line_seg.setInitial( Point(initialPoint()[X], _y) );
-       }
-       
-       void setY1(Coord _y)
-       {
-               m_line_seg.setFinal( Point(finalPoint()[Y], _y) );
-       }
-       
-       void setX(Coord _x)
-       {
-               m_line_seg.setInitial( Point(_x, initialPoint()[Y]) );
-               m_line_seg.setFinal( Point(_x, finalPoint()[Y]) );
-       }
-
-       Rect boundsFast() const
-       {
-               return boundsExact();
-       }
-       
-       Rect boundsExact() const
-       {
-               return Rect( initialPoint(), finalPoint() );
-       }
-       
-       Rect boundsLocal(Interval i, unsigned deg) const
-       {
-               return m_line_seg.boundsLocal(i, deg);
-       }
-       
-       int winding(Point p) const
-       {
-               return m_line_seg.winding(p);
-       }
-       
-       std::vector<double>
-       roots(double v, Dim2 d) const
-       {
-               if (d < 0 || d > 1)
-               {
-                       THROW_RANGEERROR("dimension argument out of range");
-               }
-               std::vector<double> result;
-               if (d == Y)
-               {
-                       if ( v >= initialPoint()[Y] && v <= finalPoint()[Y] )
-                       {
-                               double t = 0;
-                               if (!isDegenerate())
-                                       t = (v - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]);
-                               result.push_back(t);
-                       }
-               }
-               else
-               {
-                       if (v == initialPoint()[X])
-                       {
-                               if (!isDegenerate())
-                                       THROW_INFINITESOLUTIONS(0);
-                               result.push_back(0);
-                       }
-               }
-               return result;
-       }
-       
-       double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
-       {
-               if ( from > to ) std::swap(from, to);
-               double yfrom = pointAt(from)[Y];
-               double yto = pointAt(to)[Y];
-               if (yfrom > yto)
-               {
-                   std::swap(yfrom, yto);
-                   std::swap(from, to);
-               }
-               if ( p[Y] > yfrom && p[Y] < yto )
-               {
-                       return (p[Y] - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]);
-               }
-               else if ( p[Y] <= yfrom )
-                       return from;
-               else
-                       return to;
-       }
-       
-       std::pair<VLineSegment, VLineSegment> subdivide(Coord t) const
-       {
-               std::pair<VLineSegment, VLineSegment> result;
-               Point p = pointAt(t);
-               result.first.setInitial(initialPoint());
-               result.first.setFinal(p);
-               result.second.setInitial(p);
-               result.second.setFinal(finalPoint());
-               return result;
-       }
-       
-       Curve* portion(double f, double t) const
-       {
-               Point ip = pointAt(f);
-               Point ep = pointAt(t);
-               return new VLineSegment(ip[X], ip[Y], ep[Y]);
-       }
-       
-       Curve* reverse() const
-       {
-               return 
-               new VLineSegment(initialPoint()[X], finalPoint()[Y], initialPoint()[Y]);
-       }
-       
-       Curve* transformed(Matrix const & m) const
-       {
-               Point ip = initialPoint() * m;
-               Point ep = finalPoint() * m;
-               return new LineSegment(ip, ep);
-       }
-       
-       Curve* derivative() const
-       {
-               double y = finalPoint()[Y] - initialPoint()[Y];
-               return new VLineSegment(0, y, y);
-       }
-       
-       Point pointAt(double t) const
-       {
-               if ( t < 0 || t > 1 )
-                       THROW_RANGEERROR("domain parameter out of range");
-               double y = initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]);
-               return Point(initialPoint()[X], y);
-       }
-       
-       double valueAt(double t, Dim2 d) const
-       {
-               if (d < 0 || d > 1)
-               {
-                       THROW_RANGEERROR("dimension argument out of range");
-               }
-               if ( t < 0 || t > 1 )
-                       THROW_RANGEERROR("domain parameter out of range");
-               
-               if (d == X) return initialPoint()[X];
-               
-               return initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]);
-       }
+    VLineSegment()
+    {}
+
+    VLineSegment(Coord _x, Coord _y0, Coord _y1)
+        : m_line_seg(Point(_x, _y0), Point(_x, _y1))
+    {
+    }
+
+    VLineSegment(Point const& _p, double _length)
+        : m_line_seg(_p, Point(_p[X], _p[Y] + _length))
+    {
+    }
+
+    VLineSegment(Point const& _p0, Point const& _p1)
+        : m_line_seg(_p0, _p1)
+    {
+        if ( _p0[X] != _p1[X] )
+        {
+            THROW_RANGEERROR("VLineSegment::VLineSegment passed points should "
+                             "have the same X value");
+        }
+    }
+
+    Curve* duplicate() const
+    {
+        return new VLineSegment(*this);
+    }
+
+    bool isDegenerate() const
+    {
+        return m_line_seg.isDegenerate();
+    }
+
+    Point initialPoint() const
+    {
+        return m_line_seg.initialPoint();
+    }
+
+    Point finalPoint() const
+    {
+        return m_line_seg.finalPoint();
+    }
+
+    Coord getX()
+    {
+        return initialPoint()[X];
+    }
+
+    void setInitial(Point _p)
+    {
+        m_line_seg.setInitial( Point(initialPoint()[X], _p[Y]) );
+    }
+
+    void setFinal(Point _p)
+    {
+        m_line_seg.setFinal( Point(finalPoint()[X], _p[Y]) );
+    }
+
+    void setY0(Coord _y)
+    {
+        m_line_seg.setInitial( Point(initialPoint()[X], _y) );
+    }
+
+    void setY1(Coord _y)
+    {
+        m_line_seg.setFinal( Point(finalPoint()[Y], _y) );
+    }
+
+    void setX(Coord _x)
+    {
+        m_line_seg.setInitial( Point(_x, initialPoint()[Y]) );
+        m_line_seg.setFinal( Point(_x, finalPoint()[Y]) );
+    }
+
+    Rect boundsFast() const
+    {
+        return boundsExact();
+    }
+
+    Rect boundsExact() const
+    {
+        return Rect( initialPoint(), finalPoint() );
+    }
+
+    Rect boundsLocal(Interval i, unsigned deg) const
+    {
+        return m_line_seg.boundsLocal(i, deg);
+    }
+
+    int winding(Point p) const
+    {
+        return m_line_seg.winding(p);
+    }
+
+    std::vector<double>
+    roots(double v, Dim2 d) const
+    {
+        if (d < 0 || d > 1)
+        {
+            THROW_RANGEERROR("dimension argument out of range");
+        }
+        std::vector<double> result;
+        if (d == Y)
+        {
+            if ( v >= initialPoint()[Y] && v <= finalPoint()[Y] )
+            {
+                double t = 0;
+                if (!isDegenerate())
+                    t = (v - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]);
+                result.push_back(t);
+            }
+        }
+        else
+        {
+            if (v == initialPoint()[X])
+            {
+                if (!isDegenerate())
+                    THROW_INFINITESOLUTIONS(0);
+                result.push_back(0);
+            }
+        }
+        return result;
+    }
+
+    double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
+    {
+        if ( from > to ) std::swap(from, to);
+        double yfrom = pointAt(from)[Y];
+        double yto = pointAt(to)[Y];
+        if (yfrom > yto)
+        {
+            std::swap(yfrom, yto);
+            std::swap(from, to);
+        }
+        if ( p[Y] > yfrom && p[Y] < yto )
+        {
+            return (p[Y] - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]);
+        }
+        else if ( p[Y] <= yfrom )
+            return from;
+        else
+            return to;
+    }
+
+    std::pair<VLineSegment, VLineSegment> subdivide(Coord t) const
+    {
+        std::pair<VLineSegment, VLineSegment> result;
+        Point p = pointAt(t);
+        result.first.setInitial(initialPoint());
+        result.first.setFinal(p);
+        result.second.setInitial(p);
+        result.second.setFinal(finalPoint());
+        return result;
+    }
+
+    Curve* portion(double f, double t) const
+    {
+        Point ip = pointAt(f);
+        Point ep = pointAt(t);
+        return new VLineSegment(ip[X], ip[Y], ep[Y]);
+    }
+
+    Curve* reverse() const
+    {
+        return
+        new VLineSegment(initialPoint()[X], finalPoint()[Y], initialPoint()[Y]);
+    }
+
+    Curve* transformed(Matrix const & m) const
+    {
+        Point ip = initialPoint() * m;
+        Point ep = finalPoint() * m;
+        if (m.onlyScaleAndTranslation()) {
+            return new VLineSegment(ip[X], ip[Y], ep[Y]);
+        } else {
+            return new LineSegment(ip, ep);
+        }
+    }
+
+    Curve* derivative() const
+    {
+        double y = finalPoint()[Y] - initialPoint()[Y];
+        return new VLineSegment(0, y, y);
+    }
+
+    Point pointAt(double t) const
+    {
+        if ( t < 0 || t > 1 )
+            THROW_RANGEERROR("domain parameter out of range");
+        double y = initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]);
+        return Point(initialPoint()[X], y);
+    }
+
+    double valueAt(double t, Dim2 d) const
+    {
+        if (d < 0 || d > 1)
+        {
+            THROW_RANGEERROR("dimension argument out of range");
+        }
+        if ( t < 0 || t > 1 )
+            THROW_RANGEERROR("domain parameter out of range");
+
+        if (d == X) return initialPoint()[X];
+
+        return initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]);
+    }
 
     std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const
     {
@@ -497,14 +505,14 @@ class VLineSegment : public Curve
         return result;
     }
 
-       D2<SBasis> toSBasis() const
-       {
-               return m_line_seg.toSBasis();
-       }
-       
+    D2<SBasis> toSBasis() const
+    {
+        return m_line_seg.toSBasis();
+    }
+
   private:
-       LineSegment m_line_seg;
-       
+    LineSegment m_line_seg;
+
 }; // end class VLineSegment
 
 
@@ -512,7 +520,7 @@ class VLineSegment : public Curve
 }  // end namespace Geom
 
 
-#endif // _2GEOM_HVLINESEGMENT_H_ 
+#endif // _2GEOM_HVLINESEGMENT_H_
 
 
 /*
index 9887c044ffaa0dd8bc754aab9b2b9c394698a657..74e03aec9924c63234cbb01cc22b290a6eccad4d 100644 (file)
 namespace Geom {
 
 /* Although an Interval where _b[0] > _b[1] is considered empty, for proper functioning of other methods,
- * a proper empty Interval is [+COORD_HUGE, -COORD_HUGE]. Then, expandTo(p) will set the interval to [p,p].
+ * a proper empty Interval is [+infinity, -infinity]. Then, expandTo(p) will set the interval to [p,p].
  */
 class Interval {
 private:
     Coord _b[2];
 
 public:
-    // The default constructor creates an empty interval, that ranges from +COORD_HUGE to -COORD_HUGE.
+    // The default constructor creates an empty interval, that ranges from +infinity to -infinity.
     // Doing an expandTo(p) on this empty interval will correctly set the whole interval to [p,p].
-    explicit Interval() { _b[0] = +COORD_HUGE;  _b[1] = -COORD_HUGE; }
+    explicit Interval() { _b[0] = +infinity();  _b[1] = -infinity(); }
     explicit Interval(Coord u) { _b[0] = _b[1] = u; }
     /* When creating an Interval using the constructor specifying the exact range, the created interval
      * will be [u,v] when u<=v ; and will be [v,u] when v < u !!!
index d25cc8f7e2151c313072ba1fda5793e31e5e5719..6286de86e6feb838de332a410ef36498b2d54318 100644 (file)
@@ -128,7 +128,7 @@ bool Matrix::isTranslation(Coord const eps) const {
  \return A bool representing yes/no.
  */
 bool Matrix::isScale(Coord const eps) const {
-    return !are_near(_c[0], 1.0, eps) || !are_near(_c[3], 1.0, eps) &&  //NOTE: these are the diags, and the next line opposite diags
+    return (!are_near(_c[0], 1.0, eps) || !are_near(_c[3], 1.0, eps)) &&  //NOTE: these are the diags, and the next line opposite diags
            are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && 
            are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps);
 }
index d39b3ca9235f16b546a564a88b6a1187e448689a..5f321d5175be09153fc29c132393de6056800fe2 100644 (file)
@@ -194,7 +194,7 @@ Path::allNearestPoints(Point const& _point, double from, double to) const
        return all_nearest;     
 }
 
-double Path::nearestPoint(Point const& _point, double from, double to) const
+double Path::nearestPoint(Point const &_point, double from, double to, double *distance_squared) const
 {
        if ( from > to ) std::swap(from, to);
        const Path& _path = *this;
@@ -220,10 +220,11 @@ double Path::nearestPoint(Point const& _point, double from, double to) const
        }
        if ( si == ei )
        {
-               double nearest =
-                       _path[si].nearestPoint(_point, st, et);
+               double nearest = _path[si].nearestPoint(_point, st, et);
+        *distance_squared = distanceSq(_point, _path[si].pointAt(nearest));
                return si + nearest;
        }
+
        double t;
        double nearest = _path[si].nearestPoint(_point, st);
        unsigned int ni = si;
@@ -254,8 +255,13 @@ double Path::nearestPoint(Point const& _point, double from, double to) const
                {
                        nearest = t;
                        ni = ei;
+                       mindistsq = dsq;
                }
        }
+
+    if (distance_squared) {
+        *distance_squared = mindistsq;
+    }
        return ni + nearest;
 }
 
index f391c9c249cd933ba27401d7eef61c9bbbbf0d32..ab91038a6816999378affc97236c5add8e6f29a0 100644 (file)
@@ -39,7 +39,8 @@
 
 
 #include <boost/shared_ptr.hpp>
-#include <2geom/curves.h>
+#include <2geom/curve.h>
+#include <2geom/bezier-curve.h>
 
 #include <iterator>
 #include <algorithm>
@@ -357,13 +358,13 @@ public:
   }
   
   
-  double nearestPoint(Point const& _point, double from, double to) const;
+  double nearestPoint(Point const& _point, double from, double to, double *distance_squared = NULL) const;
   
-  double nearestPoint(Point const& _point) const
+  double nearestPoint(Point const& _point, double *distance_squared = NULL) const
   {
          unsigned int sz = size();
          if ( closed() ) ++sz;
-         return nearestPoint(_point, 0, sz);
+         return nearestPoint(_point, 0, sz, distance_squared);
   }
    
   void appendPortionTo(Path &p, double f, double t) const;
index 1e0a20003c61b6e9f9893695e6a261f0d1bc7ce4..6d4e24c9fee595b6729d814e4e659832888037ca 100644 (file)
@@ -88,6 +88,32 @@ Rect bounds_exact( PathVector const& pv )
     return bound;
 }
 
+/* Note: undefined for empty pathvectors or pathvectors with empty paths.
+ * */
+PathVectorPosition nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared)
+{
+    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.path_nr = i;
+            retval.t       = t;
+        }
+
+        ++i;
+    }
+
+    if (distance_squared) {
+        *distance_squared = mindsq;
+    }
+    return retval;
+}
+
 } // namespace Geom
 
 #endif // SEEN_GEOM_PATHVECTOR_CPP
index 14d1efdfa3dfbba92e04d0a7626b068cd314dd13..23843c52dfeb7c74fc4f099f520a208e98a04fc2 100644 (file)
@@ -92,7 +92,16 @@ PathVector reverse_paths_and_order (PathVector const & path_in);
 
 Rect bounds_fast( PathVector const & pv );
 Rect bounds_exact( PathVector const & pv );
-}
+
+struct PathVectorPosition {
+    // pathvector[path_nr].pointAt(t) is the position
+    unsigned int path_nr;
+    double       t;
+};
+PathVectorPosition nearestPoint(PathVector const & path_in, Point const& _point, double *distance_squared = NULL);
+
+
+} // end namespace Geom
 
 #endif // SEEN_GEOM_PATHVECTOR_H
 
index 666a249af6906ad2b10b69bd987336b6d9426993..6da5afb7e37e15104dd8a226ffce23e19e1942e6 100644 (file)
@@ -32,6 +32,7 @@
 #define SEEN_SVG_PATH_H
 
 #include <2geom/path.h>
+#include <2geom/curves.h>
 #include <iterator>
 
 namespace Geom {
index f2892491aec05811f1b0b0efeddd8d4d97fd013a..d077abbd280f623e06d643203e492d082a6255e3 100644 (file)
@@ -22,6 +22,8 @@
 #include "nr-arena.h"
 #include "sp-canvas.h"
 #include <2geom/pathvector.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 #include <2geom/matrix.h>
 #include <2geom/point.h>
 #include <2geom/path.h>
index 343684c2e35d5c64e9f91e5cf6cef56a9f2718a9..9909d743685fdc7d5961ce805cd9ff2dce746dfe 100644 (file)
@@ -29,6 +29,8 @@
 #include <libnr/nr-matrix-fns.h>
 #include <2geom/pathvector.h>
 #include <2geom/sbasis-to-bezier.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 
 #include "sp-item.h"
 
index e4570c59a6897e6648237daea227f4e5326eee1c..2a71eabca4ec3f489c06259ded10dd2a20b5050b 100644 (file)
@@ -52,6 +52,8 @@
 #include <style.h>
 #include "display/curve.h"
 #include <2geom/pathvector.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 #include <2geom/transforms.h>
 #include <helper/geom.h>
 #include "extension/system.h"
index 2ccbfd0f2a2d932c19f6f77f1e2e31d82079d832..d1a8e833c808a5ff41b252abe24bf032e5e2436b 100644 (file)
@@ -30,6 +30,8 @@
 #include <extension/system.h>
 #include <2geom/pathvector.h>
 #include <2geom/rect.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 #include "helper/geom.h"
 #include <io/sys.h>
 
index aec3cf9511b47e2f0f40ea1e14407ce6a5dd15ab..7ee28f87a5ef4877eae4e29c9f9312662015d242 100644 (file)
@@ -78,6 +78,8 @@
 #include <cmath>
 
 #include <2geom/sbasis-to-bezier.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 
 /*
 using std::atof;
index f94881e0c36c7a68cdb7d1574886602def205ae9..dcb7b3eb49a014a21cf03b356532b93fe676964e 100644 (file)
@@ -15,6 +15,8 @@
 #include <typeinfo>
 #include <2geom/pathvector.h>
 #include <2geom/path.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 #include <2geom/transforms.h>
 #include <2geom/rect.h>
 #include <2geom/coord.h>
index 0ad6171c1b57a8ecf5fc657cd61a960a451399a6..e84f85e0a81ea310d620c568dee89d4a0e7aca2d 100644 (file)
@@ -26,6 +26,7 @@
 #include <2geom/point.h>
 #include <2geom/matrix.h>
 #include <2geom/sbasis-to-bezier.h>
+#include <2geom/curves.h>
 #include "../display/canvas-bpath.h"
 
 void  Path::DashPolyline(float head,float tail,float body,int nbD,float *dashs,bool stPlain,float stOffset)
index 1eedfa3a71bc0d85f3e7ac8f49ac908db2959e6c..948da335ad9841dac1301e91525aaf48d047818f 100644 (file)
@@ -19,6 +19,7 @@
 #include <2geom/path.h>
 #include <2geom/transforms.h>
 #include <2geom/d2-sbasis.h>
+#include <2geom/angle.h>
 
 namespace Inkscape {
 namespace LivePathEffect {
index 68d61603d6ba8fa56086e1d7c5726ecc36987a66..027eda23f25d846cc60553431e9e5847fb54b15d 100644 (file)
@@ -19,7 +19,7 @@
 #include <2geom/path.h>
 #include <2geom/piecewise.h>
 #include <2geom/sbasis-geometric.h>
-#include <2geom/elliptical-arc.h>
+#include <2geom/svg-elliptical-arc.h>
 #include <2geom/transforms.h>
 
 namespace Inkscape {
index 54c15cd96fb70bf8c236ce62f5b73b06bd357782..276ed7b0b7ae1117da63b12b5030dc50ffde66ff 100644 (file)
@@ -11,6 +11,8 @@
 #include <typeinfo>
 #include <2geom/pathvector.h>
 #include <2geom/matrix.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 #include "helper/geom-nodetype.h"
 
 #include "live_effects/bezctx.h"
index 387cf1b0a3308ea848714bd7789ffa12093f0748..c62fb2c0f6859929d25f36d8231c0f43ee444a7c 100644 (file)
@@ -23,6 +23,8 @@
 #include <glibmm/i18n.h>
 #include <2geom/pathvector.h>
 #include <2geom/sbasis-to-bezier.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 #include "helper/units.h"
 #include "knot.h"
 #include "inkscape.h"
index 0867cc3ad008cf40bd96073975d389e1da105dbb..654edcc610a88410c741fc2bb38bdab60f96e973 100644 (file)
@@ -25,6 +25,8 @@
 #include <libnr/nr-path.h>
 #include <libnr/nr-matrix-fns.h>
 #include <2geom/pathvector.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 
 #include "svg/svg.h"
 #include "xml/repr.h"
index 04046a47d81982a3ad07b26d5a616f110d0a6a85..fddc9d1dba7d712e0971d638dfa0056d93d62075 100644 (file)
@@ -19,6 +19,8 @@
 #include "display/curve.h"
 #include <glibmm/i18n.h>
 #include <2geom/pathvector.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
 #include "svg/stringstream.h"
 #include "xml/repr.h"
 #include "document.h"
index b280da07aa26b4d6dd120e8a144f5482e4940591..12b2825779ebd2550c857aabec09e3f11a4b73dc 100644 (file)
 
 #include <2geom/pathvector.h>
 #include <2geom/path.h>
+#include <2geom/curves.h>
 #include <2geom/sbasis-to-bezier.h>
 #include <2geom/svg-path.h>
 #include <2geom/svg-path-parser.h>
 #include <2geom/exception.h>
 
+
 /* This module parses an SVG path element into an RsvgBpathDef.
 
    At present, there is no support for <marker> or any other contextual