summaryrefslogtreecommitdiffstats
path: root/src/2geom/path.h
diff options
context:
space:
mode:
authorJohan B. C. Engelen <jbc.engelen@swissonline.ch>2008-05-10 20:20:11 +0000
committerjohanengelen <johanengelen@users.sourceforge.net>2008-05-10 20:20:11 +0000
commit711043c7ca9bd675133e9bb1c1a3ec05c83cbeba (patch)
tree9395fdf4cc57a8192fc0ebe506dd0f5b9db0d9d3 /src/2geom/path.h
parentDo not show/edit image URL for data URIs. (diff)
downloadinkscape-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.h211
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;