diff options
| author | Johan B. C. Engelen <jbc.engelen@swissonline.ch> | 2008-05-10 20:20:11 +0000 |
|---|---|---|
| committer | johanengelen <johanengelen@users.sourceforge.net> | 2008-05-10 20:20:11 +0000 |
| commit | 711043c7ca9bd675133e9bb1c1a3ec05c83cbeba (patch) | |
| tree | 9395fdf4cc57a8192fc0ebe506dd0f5b9db0d9d3 /src/2geom/path.h | |
| parent | Do not show/edit image URL for data URIs. (diff) | |
| download | inkscape-711043c7ca9bd675133e9bb1c1a3ec05c83cbeba.tar.gz inkscape-711043c7ca9bd675133e9bb1c1a3ec05c83cbeba.zip | |
update to latest 2geom. this adds gsl dependency, doesn't seem to make inskape executable bigger
(bzr r5649)
Diffstat (limited to 'src/2geom/path.h')
| -rw-r--r-- | src/2geom/path.h | 211 |
1 files changed, 157 insertions, 54 deletions
diff --git a/src/2geom/path.h b/src/2geom/path.h index 414d69755..ed15260fc 100644 --- a/src/2geom/path.h +++ b/src/2geom/path.h @@ -44,6 +44,7 @@ #include "bezier.h" #include "crossing.h" #include "utils.h" +#include "nearest-point.h" namespace Geom { @@ -81,6 +82,19 @@ public: virtual void setInitial(Point v) = 0; virtual void setFinal(Point v) = 0; + + virtual + double nearestPoint( Point const& p, double from = 0, double to = 1 ) const + { + return nearest_point(p, toSBasis(), from, to); + } + + virtual + std::vector<double> + allNearestPoints( Point const& p, double from = 0, double to = 1 ) const + { + return all_nearest_points(p, toSBasis(), from, to); + } virtual Curve *transformed(Matrix const &m) const = 0; @@ -91,9 +105,11 @@ public: }; class SBasisCurve : public Curve { + private: SBasisCurve(); D2<SBasis> inner; + public: explicit SBasisCurve(D2<SBasis> const &sb) : inner(sb) {} explicit SBasisCurve(Curve const &other) : inner(other.toSBasis()) {} @@ -116,6 +132,17 @@ public: Rect boundsLocal(Interval i, unsigned deg) const { return bounds_local(inner, i, deg); } std::vector<double> roots(double v, Dim2 d) const { return Geom::roots(inner[d] - v); } + + double nearestPoint( Point const& p, double from = 0, double to = 1 ) const + { + return nearest_point(p, inner, from, to); + } + + std::vector<double> + allNearestPoints( Point const& p, double from = 0, double to = 1 ) const + { + return all_nearest_points(p, inner, from, to); + } Curve *portion(double f, double t) const { return new SBasisCurve(Geom::portion(inner, f, t)); @@ -135,8 +162,10 @@ public: template <unsigned order> class BezierCurve : public Curve { + private: D2<Bezier > inner; + public: template <unsigned required_degree> static void assert_degree(BezierCurve<required_degree> const *) {} @@ -205,7 +234,12 @@ public: roots(double v, Dim2 d) const { return (inner[d] - v).roots(); } - + + double nearestPoint( Point const& p, double from = 0, double to = 1 ) const + { + return Curve::nearestPoint(p, from, to); + } + void setPoints(std::vector<Point> ps) { for(unsigned i = 0; i <= order; i++) { setPoint(i, ps[i]); @@ -269,6 +303,8 @@ typedef BezierCurve<1> LineSegment; typedef BezierCurve<2> QuadraticBezier; typedef BezierCurve<3> CubicBezier; +template<> +double LineSegment::nearestPoint(Point const& p, double from, double to) const; @@ -276,7 +312,13 @@ class SVGEllipticalArc : public Curve { public: SVGEllipticalArc() - {} + : m_initial_point(Point(0,0)), m_final_point(Point(0,0)), + m_rx(0), m_ry(0), m_rot_angle(0), + m_large_arc(true), m_sweep(true) + { + m_start_angle = m_end_angle = 0; + m_center = Point(0,0); + } SVGEllipticalArc( Point _initial_point, double _rx, double _ry, double _rot_angle, bool _large_arc, bool _sweep, @@ -286,24 +328,30 @@ class SVGEllipticalArc : public Curve m_rx(_rx), m_ry(_ry), m_rot_angle(_rot_angle), m_large_arc(_large_arc), m_sweep(_sweep) { - //assert( (ray(X) >= 0) && (ray(Y) >= 0) ); - if ( are_near(initialPoint(), finalPoint()) ) - { - m_start_angle = m_end_angle = 0; - m_center = initialPoint(); - } - else - { calculate_center_and_extreme_angles(); - } } + void set( Point _initial_point, double _rx, double _ry, + double _rot_angle, bool _large_arc, bool _sweep, + Point _final_point + ) + { + m_initial_point = _initial_point; + m_final_point = _final_point; + m_rx = _rx; + m_ry = _ry; + m_rot_angle = _rot_angle; + m_large_arc = _large_arc; + m_sweep = _sweep; + calculate_center_and_extreme_angles(); + } + Curve* duplicate() const { return new SVGEllipticalArc(*this); } - double center(Dim2 i) const + double center(unsigned int i) const { return m_center[i]; } @@ -333,7 +381,7 @@ class SVGEllipticalArc : public Curve return m_end_angle; } - double ray(Dim2 i) const + double ray(unsigned int i) const { return (i == 0) ? m_rx : m_ry; } @@ -374,28 +422,34 @@ class SVGEllipticalArc : public Curve bool isDegenerate() const { - return are_near(initialPoint(), finalPoint()); + return ( are_near(ray(X), 0) || are_near(ray(Y), 0) ); } // TODO: native implementation of the following methods Rect boundsFast() const { - return SBasisCurve(toSBasis()).boundsFast(); + return boundsExact(); } - Rect boundsExact() const - { - return SBasisCurve(toSBasis()).boundsExact(); - } + Rect boundsExact() const; Rect boundsLocal(Interval i, unsigned int deg) const { return SBasisCurve(toSBasis()).boundsLocal(i, deg); } - std::vector<double> roots(double v, Dim2 d) const + std::vector<double> roots(double v, Dim2 d) const; + + std::vector<double> + allNearestPoints( Point const& p, double from = 0, double to = 1 ) const; + + double nearestPoint( Point const& p, double from = 0, double to = 1 ) const { - return SBasisCurve(toSBasis()).roots(v, d); + if ( are_near(ray(X), ray(Y)) && are_near(center(), p) ) + { + return from; + } + return allNearestPoints(p, from, to).front(); } int winding(Point p) const @@ -403,36 +457,43 @@ class SVGEllipticalArc : public Curve return SBasisCurve(toSBasis()).winding(p); } - Curve *derivative() const - { - return SBasisCurve(toSBasis()).derivative(); - } + Curve *derivative() const; Curve *transformed(Matrix const &m) const { return SBasisCurve(toSBasis()).transformed(m); } - std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const - { - return SBasisCurve(toSBasis()).pointAndDerivatives(t, n); - } + std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const; D2<SBasis> toSBasis() const; - double valueAt(Coord t, Dim2 d) const; - - Point pointAt(Coord t) const + bool containsAngle(Coord angle) const; + + double valueAtAngle(Coord t, Dim2 d) const; + + Point pointAtAngle(Coord t) const { - Coord tt = from_01_to_02PI(t); double sin_rot_angle = std::sin(rotation_angle()); double cos_rot_angle = std::cos(rotation_angle()); Matrix m( ray(X) * cos_rot_angle, ray(X) * sin_rot_angle, -ray(Y) * sin_rot_angle, ray(Y) * cos_rot_angle, center(X), center(Y) ); - Point p( std::cos(tt), std::sin(tt) ); + Point p( std::cos(t), std::sin(t) ); return p * m; } + + double valueAt(Coord t, Dim2 d) const + { + Coord tt = map_to_02PI(t); + return valueAtAngle(tt, d); + } + + Point pointAt(Coord t) const + { + Coord tt = map_to_02PI(t); + return pointAtAngle(tt); + } std::pair<SVGEllipticalArc, SVGEllipticalArc> subdivide(Coord t) const @@ -460,7 +521,6 @@ class SVGEllipticalArc : public Curve return rarc; } - private: double sweep_angle() const { Coord d = end_angle() - start_angle(); @@ -469,12 +529,12 @@ class SVGEllipticalArc : public Curve d += 2*M_PI; return d; } - - Coord from_01_to_02PI(Coord t) const; - - void calculate_center_and_extreme_angles() throw(RangeError); private: + Coord map_to_02PI(Coord t) const; + Coord map_to_01(Coord angle) const; + void calculate_center_and_extreme_angles(); + private: Point m_initial_point, m_final_point; double m_rx, m_ry, m_rot_angle; bool m_large_arc, m_sweep; @@ -657,20 +717,42 @@ public: return ret; } - Point pointAt(double t) const { - if(empty()) return Point(0,0); - double i, f = modf(t, &i); - if(i == size() && f == 0) { i--; } - assert(i >= 0 && i <= size()); - return (*this)[unsigned(i)].pointAt(f); + Point pointAt(double t) const + { + unsigned int sz = size(); + if ( closed() ) ++sz; + if ( t < 0 || t > sz ) + { + THROW_RANGEERROR("parameter t out of bounds"); + } + if ( empty() ) return Point(0,0); + double k, lt = modf(t, &k); + unsigned int i = static_cast<unsigned int>(k); + if ( i == sz ) + { + --i; + lt = 1; + } + return (*this)[i].pointAt(lt); } - double valueAt(double t, Dim2 d) const { - if(empty()) return 0; - double i, f = modf(t, &i); - if(i == size() && f == 0) { i--; } - assert(i >= 0 && i <= size()); - return (*this)[unsigned(i)].valueAt(f, d); + double valueAt(double t, Dim2 d) const + { + unsigned int sz = size(); + if ( closed() ) ++sz; + if ( t < 0 || t > sz ) + { + THROW_RANGEERROR("parameter t out of bounds"); + } + if ( empty() ) return 0; + double k, lt = modf(t, &k); + unsigned int i = static_cast<unsigned int>(k); + if ( i == sz ) + { + --i; + lt = 1; + } + return (*this)[i].valueAt(lt, d); } std::vector<double> roots(double v, Dim2 d) const { @@ -682,7 +764,28 @@ public: } return res; } - + + std::vector<double> + allNearestPoints(Point const& _point, double from, double to) const; + + std::vector<double> + allNearestPoints(Point const& _point) const + { + unsigned int sz = size(); + if ( closed() ) ++sz; + return allNearestPoints(_point, 0, sz); + } + + + double nearestPoint(Point const& _point, double from, double to) const; + + double nearestPoint(Point const& _point) const + { + unsigned int sz = size(); + if ( closed() ) ++sz; + return nearestPoint(_point, 0, sz); + } + void appendPortionTo(Path &p, double f, double t) const; Path portion(double f, double t) const { @@ -704,7 +807,7 @@ public: } return ret; } - + void insert(iterator pos, Curve const &curve) { Sequence source(1, curve.duplicate()); try { @@ -909,7 +1012,7 @@ class PathPortion : public Curve { Rect boundsFast() const { return actualPath().boundsFast; } Rect boundsExact() const { return actualPath().boundsFast; } - Rect boundsLocal(Interval i) const { throwNotImplemented(); } + Rect boundsLocal(Interval i) const { THROW_NOTIMPLEMENTED(); } std::vector<double> roots(double v, Dim2 d) const = 0; |
