summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 5c6c297)
raw | patch | inline | side by side (parent: 5c6c297)
author | mcecchetti <mcecchetti@users.sourceforge.net> | |
Mon, 26 May 2008 22:32:02 +0000 (22:32 +0000) | ||
committer | mcecchetti <mcecchetti@users.sourceforge.net> | |
Mon, 26 May 2008 22:32:02 +0000 (22:32 +0000) |
13 files changed:
src/2geom/CMakeLists.txt | patch | blob | history | |
src/2geom/Makefile_insert | patch | blob | history | |
src/2geom/bezier-curve.h | [new file with mode: 0644] | patch | blob |
src/2geom/curve-helpers.cpp | [new file with mode: 0644] | patch | blob |
src/2geom/curve.h | [new file with mode: 0644] | patch | blob |
src/2geom/curves.h | [new file with mode: 0644] | patch | blob |
src/2geom/elliptical-arc.cpp | patch | blob | history | |
src/2geom/elliptical-arc.h | [new file with mode: 0644] | patch | blob |
src/2geom/forward.h | patch | blob | history | |
src/2geom/hvlinesegment.h | [new file with mode: 0644] | patch | blob |
src/2geom/path.cpp | patch | blob | history | |
src/2geom/path.h | patch | blob | history | |
src/2geom/sbasis-curve.h | [new file with mode: 0644] | patch | blob |
index ac019419ddd93c152d4dc6a09ccd64e9fe261677..fc741fb4731398532a7f0f589f05bfefc913b9e2 100644 (file)
--- a/src/2geom/CMakeLists.txt
+++ b/src/2geom/CMakeLists.txt
basic-intersection.cpp
basic-intersection.h
bezier.h
+bezier-curve.h
bezier-to-sbasis.h
bezier-utils.cpp
bezier-utils.h
coord.h
crossing.cpp
crossing.h
+curve.h
+curves.h
+curve-helpers.cpp
d2.h
d2-sbasis.cpp
d2-sbasis.h
elliptical-arc.cpp
+elliptical-arc.h
exception.h
forward.h
geom.cpp
geom.h
+hvlinesegment.h
interval.h
isnan.h
linear.h
sbasis-2d.cpp
sbasis-2d.h
sbasis.cpp
+sbasis-curve.h
sbasis-geometric.cpp
sbasis-geometric.h
sbasis.h
index e2c0d6aa37fd4a54bb4d6dbfab40bcb2a4977137..c45dd806d2f003b2057fabd7f12a56a688cef4c4 100644 (file)
2geom_lib2geom_a_SOURCES = \\r
2geom/basic-intersection.cpp \\r
2geom/basic-intersection.h \\r
+ 2geom/bezier-curve.h \\r
2geom/bezier-to-sbasis.h \\r
2geom/bezier-utils.cpp \\r
2geom/bezier-utils.h \\r
2geom/coord.h \\r
2geom/crossing.cpp \\r
2geom/crossing.h \\r
+ 2geom/curve.h \\r
+ 2geom/curves.h \\r
+ 2geom/curve-helpers.cpp \\r
2geom/d2-sbasis.cpp \\r
2geom/d2-sbasis.h \\r
2geom/d2.h \\r
2geom/exception.h \\r
2geom/elliptical-arc.cpp \\r
+ 2geom/elliptical-arc.h \\r
2geom/forward.h \\r
2geom/geom.cpp \\r
2geom/geom.h \\r
+ 2geom/hvlinesegment.h \\r
2geom/interval.h \\r
2geom/isnan.h \\r
2geom/linear.h \\r
2geom/region.h \\r
2geom/sbasis-2d.cpp \\r
2geom/sbasis-2d.h \\r
+ 2geom/sbasis-curve.h \\r
2geom/sbasis-geometric.cpp \\r
2geom/sbasis-geometric.h \\r
2geom/sbasis-math.cpp \\r
diff --git a/src/2geom/bezier-curve.h b/src/2geom/bezier-curve.h
--- /dev/null
+++ b/src/2geom/bezier-curve.h
@@ -0,0 +1,240 @@
+/*
+ * Bezier-Curve
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#ifndef _2GEOM_BEZIER_CURVE_H_
+#define _2GEOM_BEZIER_CURVE_H_
+
+
+#include "curve.h"
+#include "sbasis-curve.h" // for non-native winding method
+#include "bezier.h"
+
+#include <algorithm>
+
+
+namespace Geom
+{
+
+
+
+template <unsigned order>
+class BezierCurve : public Curve {
+
+private:
+ D2<Bezier > inner;
+
+public:
+ template <unsigned required_degree>
+ static void assert_degree(BezierCurve<required_degree> const *) {}
+
+ BezierCurve() : inner(Bezier::Order(order), Bezier::Order(order)) {
+ }
+
+ explicit BezierCurve(D2<Bezier > const &x) : inner(x) {}
+
+ BezierCurve(Bezier x, Bezier y) : inner(x, y) {}
+
+ // default copy
+ // default assign
+
+ BezierCurve(Point c0, Point c1) {
+ assert_degree<1>(this);
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d]);
+ }
+
+ BezierCurve(Point c0, Point c1, Point c2) {
+ assert_degree<2>(this);
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d], c2[d]);
+ }
+
+ BezierCurve(Point c0, Point c1, Point c2, Point c3) {
+ assert_degree<3>(this);
+ for(unsigned d = 0; d < 2; d++)
+ inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]);
+ }
+
+ unsigned degree() const { return order; }
+
+ Curve *duplicate() const { return new BezierCurve(*this); }
+
+ Point initialPoint() const { return inner.at0(); }
+ Point finalPoint() const { return inner.at1(); }
+
+ bool isDegenerate() const { return inner.isConstant(); }
+
+ void setInitial(Point v) { setPoint(0, v); }
+ void setFinal(Point v) { setPoint(order, v); }
+
+ void setPoint(unsigned ix, Point v) { inner[X].setPoint(ix, v[X]); inner[Y].setPoint(ix, v[Y]); }
+ Point const operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
+
+ Rect boundsFast() const { return bounds_fast(inner); }
+ Rect boundsExact() const { return bounds_exact(inner); }
+ Rect boundsLocal(Interval i, unsigned deg) const {
+ if(i.min() == 0 && i.max() == 1) return boundsFast();
+ if(deg == 0) return bounds_local(inner, i);
+ // TODO: UUUUUUGGGLLY
+ if(deg == 1 && order > 1) return Rect(bounds_local(Geom::derivative(inner[X]), i),
+ bounds_local(Geom::derivative(inner[Y]), i));
+ return Rect(Interval(0,0), Interval(0,0));
+ }
+//TODO: local
+
+//TODO: implement next 3 natively
+ int winding(Point p) const {
+ return SBasisCurve(toSBasis()).winding(p);
+ }
+
+ std::vector<double>
+ 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]);
+ }
+ }
+ std::vector<Point> points() const { return bezier_points(inner); }
+
+ std::pair<BezierCurve<order>, BezierCurve<order> > subdivide(Coord t) const {
+ std::pair<Bezier, Bezier > sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
+ return std::pair<BezierCurve<order>, BezierCurve<order> >(
+ BezierCurve<order>(sx.first, sy.first),
+ BezierCurve<order>(sx.second, sy.second));
+ }
+
+ Curve *portion(double f, double t) const {
+ return new BezierCurve(Geom::portion(inner, f, t));
+ }
+
+ Curve *reverse() const {
+ return new BezierCurve(Geom::reverse(inner));
+ }
+
+ Curve *transformed(Matrix const &m) const {
+ BezierCurve *ret = new BezierCurve();
+ std::vector<Point> ps = points();
+ for(unsigned i = 0; i <= order; i++) ps[i] = ps[i] * m;
+ ret->setPoints(ps);
+ return ret;
+ }
+
+ Curve *derivative() const {
+ if(order > 1)
+ return new BezierCurve<order-1>(Geom::derivative(inner[X]), Geom::derivative(inner[Y]));
+ else if (order == 1) {
+ double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0];
+ return new BezierCurve<1>(Point(dx,dy),Point(dx,dy));
+ }
+ }
+
+ Point pointAt(double t) const { return inner.valueAt(t); }
+ std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const { return inner.valueAndDerivatives(t, n); }
+
+ double valueAt(double t, Dim2 d) const { return inner[d].valueAt(t); }
+
+ D2<SBasis> toSBasis() const {return inner.toSBasis(); }
+
+protected:
+ BezierCurve(Point c[]) {
+ Coord x[order+1], y[order+1];
+ for(unsigned i = 0; i <= order; i++) {
+ x[i] = c[i][X]; y[i] = c[i][Y];
+ }
+ inner = Bezier(x, y);
+ }
+};
+
+// BezierCurve<0> is meaningless; specialize it out
+template<> class BezierCurve<0> : public BezierCurve<1> { public: BezierCurve(); BezierCurve(Bezier x, Bezier y); };
+
+typedef BezierCurve<1> LineSegment;
+typedef BezierCurve<2> QuadraticBezier;
+typedef BezierCurve<3> CubicBezier;
+
+
+template<>
+inline
+double LineSegment::nearestPoint(Point const& p, double from, double to) const
+{
+ if ( from > to ) std::swap(from, to);
+ Point ip = pointAt(from);
+ Point fp = pointAt(to);
+ Point v = fp - ip;
+ double t = dot( p - ip, v ) / L2sq(v);
+ if ( t <= 0 ) return from;
+ else if ( t >= 1 ) return to;
+ else return from + t*(to-from);
+}
+
+inline
+Point middle_point(LineSegment const& _segment)
+{
+ return ( _segment.initialPoint() + _segment.finalPoint() ) / 2;
+}
+
+inline
+double length(LineSegment const& _segment)
+{
+ return distance(_segment.initialPoint(), _segment.finalPoint());
+}
+
+} // end namespace Geom
+
+
+#endif // _2GEOM_BEZIER_CURVE_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/2geom/curve-helpers.cpp b/src/2geom/curve-helpers.cpp
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#include "curve.h"
+#include "ord.h"
+
+
+namespace Geom
+{
+
+int CurveHelpers::root_winding(Curve const &c, Point p) {
+ std::vector<double> ts = c.roots(p[Y], Y);
+
+ if(ts.empty()) return 0;
+
+ double const fudge = 0.01; //fudge factor used on first and last
+
+ std::sort(ts.begin(), ts.end());
+
+ // winding determined by crossings at roots
+ int wind=0;
+ // previous time
+ double pt = ts.front() - fudge;
+ for ( std::vector<double>::iterator ti = ts.begin()
+ ; ti != ts.end()
+ ; ++ti )
+ {
+ double t = *ti;
+ if ( t <= 0. || t >= 1. ) continue; //skip endpoint roots
+ if ( c.valueAt(t, X) > p[X] ) { // root is ray intersection
+ // Get t of next:
+ std::vector<double>::iterator next = ti;
+ next++;
+ double nt;
+ if(next == ts.end()) nt = t + fudge; else nt = *next;
+
+ // Check before in time and after in time for positions
+ // Currently we're using the average times between next and previous segs
+ Cmp after_to_ray = cmp(c.valueAt((t + nt) / 2, Y), p[Y]);
+ Cmp before_to_ray = cmp(c.valueAt((t + pt) / 2, Y), p[Y]);
+ // if y is included, these will have opposite values, giving order.
+ Cmp dt = cmp(after_to_ray, before_to_ray);
+ if(dt != EQUAL_TO) //Should always be true, but yah never know..
+ wind += dt;
+ pt = t;
+ }
+ }
+
+ return wind;
+}
+
+
+} // end namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/2geom/curve.h b/src/2geom/curve.h
--- /dev/null
+++ b/src/2geom/curve.h
@@ -0,0 +1,129 @@
+/*
+ * Abstract Curve Type
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#ifndef _2GEOM_CURVE_H_
+#define _2GEOM_CURVE_H_
+
+
+#include "coord.h"
+#include "point.h"
+#include "interval.h"
+#include "nearest-point.h"
+#include "sbasis.h"
+#include "d2.h"
+#include "matrix.h"
+#include "exception.h"
+
+#include <vector>
+
+
+namespace Geom
+{
+
+class Curve;
+
+struct CurveHelpers {
+protected:
+ static int root_winding(Curve const &c, Point p);
+};
+
+class Curve : private CurveHelpers {
+public:
+ virtual ~Curve() {}
+
+ virtual Point initialPoint() const = 0;
+ virtual Point finalPoint() const = 0;
+
+ virtual bool isDegenerate() const = 0;
+
+ virtual Curve *duplicate() const = 0;
+
+ virtual Rect boundsFast() const = 0;
+ virtual Rect boundsExact() const = 0;
+ virtual Rect boundsLocal(Interval i, unsigned deg) const = 0;
+ Rect boundsLocal(Interval i) const { return boundsLocal(i, 0); }
+
+ virtual std::vector<double> roots(double v, Dim2 d) const = 0;
+
+ virtual int winding(Point p) const { return root_winding(*this, p); }
+
+ //mental: review these
+ virtual Curve *portion(double f, double t) const = 0;
+ virtual Curve *reverse() const { return portion(1, 0); }
+ virtual Curve *derivative() const = 0;
+
+ 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;
+
+ virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 1).front(); }
+ virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; }
+ virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const = 0;
+ virtual D2<SBasis> toSBasis() const = 0;
+};
+
+
+} // end namespace Geom
+
+
+#endif // _2GEOM_CURVE_H_
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/2geom/curves.h b/src/2geom/curves.h
--- /dev/null
+++ b/src/2geom/curves.h
@@ -0,0 +1,63 @@
+/*
+ * this file is only a helper header to include all curve types at once
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#ifndef _2GEOM_CURVES_H_
+#define _2GEOM_CURVES_H_
+
+
+#include "curve.h"
+#include "sbasis-curve.h"
+#include "bezier-curve.h"
+#include "hvlinesegment.h"
+#include "elliptical-arc.h"
+
+
+#endif // _2GEOM_CURVES_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+
index b4a882f093a6eb64ade3da8b838f2ba10370f908..55b23961b269d764ad61f5da493ead7cdcea4e60 100644 (file)
*/
-#include "path.h"
-#include "angle.h"
-
+#include "elliptical-arc.h"
+#include "bezier-curve.h"
#include "poly.h"
#include <cfloat>
diff --git a/src/2geom/elliptical-arc.h b/src/2geom/elliptical-arc.h
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Elliptical Arc - implementation of the svg elliptical arc path element
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#ifndef _2GEOM_ELLIPTICAL_ARC_H_
+#define _2GEOM_ELLIPTICAL_ARC_H_
+
+
+#include "curve.h"
+#include "angle.h"
+#include "utils.h"
+#include "sbasis-curve.h" // for non-native methods
+
+#include <algorithm>
+
+
+namespace Geom
+{
+
+class EllipticalArc : public Curve
+{
+ public:
+ EllipticalArc()
+ : 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);
+ }
+
+ EllipticalArc( 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();
+ }
+
+ 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 EllipticalArc(*this);
+ }
+
+ double center(unsigned int i) const
+ {
+ return m_center[i];
+ }
+
+ Point center() const
+ {
+ return m_center;
+ }
+
+ Point initialPoint() const
+ {
+ return m_initial_point;
+ }
+
+ Point finalPoint() const
+ {
+ return m_final_point;
+ }
+
+ double start_angle() const
+ {
+ return m_start_angle;
+ }
+
+ double end_angle() const
+ {
+ return m_end_angle;
+ }
+
+ double ray(unsigned int i) const
+ {
+ return (i == 0) ? m_rx : m_ry;
+ }
+
+ bool large_arc_flag() const
+ {
+ return m_large_arc;
+ }
+
+ bool sweep_flag() const
+ {
+ return m_sweep;
+ }
+
+ double rotation_angle() const
+ {
+ return m_rot_angle;
+ }
+
+ void setInitial( const Point _point)
+ {
+ m_initial_point = _point;
+ calculate_center_and_extreme_angles();
+ }
+
+ void setFinal( const Point _point)
+ {
+ m_final_point = _point;
+ calculate_center_and_extreme_angles();
+ }
+
+ void setExtremes( const Point& _initial_point, const Point& _final_point )
+ {
+ m_initial_point = _initial_point;
+ m_final_point = _final_point;
+ calculate_center_and_extreme_angles();
+ }
+
+ bool isDegenerate() const
+ {
+ return ( are_near(ray(X), 0) || are_near(ray(Y), 0) );
+ }
+
+ // TODO: native implementation of the following methods
+ Rect boundsFast() const
+ {
+ return 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>
+ allNearestPoints( Point const& p, double from = 0, double to = 1 ) const;
+
+ double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
+ {
+ if ( are_near(ray(X), ray(Y)) && are_near(center(), p) )
+ {
+ return from;
+ }
+ return allNearestPoints(p, from, to).front();
+ }
+
+ int winding(Point p) const
+ {
+ return SBasisCurve(toSBasis()).winding(p);
+ }
+
+ Curve *derivative() const;
+
+ Curve *transformed(Matrix const &m) const
+ {
+ return SBasisCurve(toSBasis()).transformed(m);
+ }
+
+ std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const;
+
+ D2<SBasis> toSBasis() const;
+
+ bool containsAngle(Coord angle) const;
+
+ double valueAtAngle(Coord t, Dim2 d) const;
+
+ Point pointAtAngle(Coord t) const
+ {
+ 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(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<EllipticalArc, EllipticalArc>
+ subdivide(Coord t) const
+ {
+ EllipticalArc* arc1 = static_cast<EllipticalArc*>(portion(0, t));
+ EllipticalArc* arc2 = static_cast<EllipticalArc*>(portion(t, 1));
+ assert( arc1 != NULL && arc2 != NULL);
+ std::pair<EllipticalArc, EllipticalArc> arc_pair(*arc1, *arc2);
+ delete arc1;
+ delete arc2;
+ return arc_pair;
+ }
+
+ Curve* portion(double f, double t) const;
+
+ // the arc is the same but traversed in the opposite direction
+ Curve* reverse() const
+ {
+ EllipticalArc* rarc = new EllipticalArc( *this );
+ rarc->m_sweep = !m_sweep;
+ rarc->m_initial_point = m_final_point;
+ rarc->m_final_point = m_initial_point;
+ rarc->m_start_angle = m_end_angle;
+ rarc->m_end_angle = m_start_angle;
+ return rarc;
+ }
+
+ double sweep_angle() const
+ {
+ Coord d = end_angle() - start_angle();
+ if ( !sweep_flag() ) d = -d;
+ if ( d < 0 )
+ d += 2*M_PI;
+ return d;
+ }
+
+ 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;
+ double m_start_angle, m_end_angle;
+ Point m_center;
+
+}; // end class EllipticalArc
+
+
+} // end namespace Geom
+
+#endif // _2GEOM_ELLIPTICAL_ARC_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/2geom/forward.h b/src/2geom/forward.h
index 5ed7ee1ffcc9541a37d7d418f5549aeb109cb2d8..52fd3525e324280439ad5589b55b35d38b8cdb7a 100644 (file)
--- a/src/2geom/forward.h
+++ b/src/2geom/forward.h
typedef BezierCurve<3> CubicBezier;
class EllipticalArc;
+class HLineSegment;
+class VLineSegment;
+
typedef double Coord;
class Point;
diff --git a/src/2geom/hvlinesegment.h b/src/2geom/hvlinesegment.h
--- /dev/null
@@ -0,0 +1,507 @@
+/*
+ * Horizontal and Vertical Line Segment
+ *
+ * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+#ifndef _2GEOM_HVLINESEGMENT_H_
+#define _2GEOM_HVLINESEGMENT_H_
+
+
+#include "bezier-curve.h"
+
+
+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 ( 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]);
+ }
+
+ std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const
+ {
+ std::vector<Point> result;
+ if ( n > 0)
+ result.push_back(pointAt(t));
+ if (n > 1)
+ {
+ double x = finalPoint()[X] - initialPoint()[X];
+ result.push_back( Point(x, 0) );
+ }
+ return result;
+ }
+
+ D2<SBasis> toSBasis() const
+ {
+ return m_line_seg.toSBasis();
+ }
+
+ private:
+ 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 ( 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]);
+ }
+
+ std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const
+ {
+ std::vector<Point> result;
+ if ( n > 0)
+ result.push_back(pointAt(t));
+ if (n > 1)
+ {
+ double y = finalPoint()[Y] - initialPoint()[Y];
+ result.push_back( Point(0, y) );
+ }
+ return result;
+ }
+
+ D2<SBasis> toSBasis() const
+ {
+ return m_line_seg.toSBasis();
+ }
+
+ private:
+ LineSegment m_line_seg;
+
+}; // end class VLineSegment
+
+
+
+} // end namespace Geom
+
+
+#endif // _2GEOM_HVLINESEGMENT_H_
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/2geom/path.cpp b/src/2geom/path.cpp
index 3effa93746d833f276a5a0e6e9c109664de9a90a..7176130e9ce2bd0a179f9b2b5a2d2188510a43f3 100644 (file)
--- a/src/2geom/path.cpp
+++ b/src/2geom/path.cpp
/*
* Path - Series of continuous curves
- *
- * Copyright 2007 MenTaLguY <mental@rydia.net>
- *
- * This library is free software; you can redistribute it and/or
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
- *
+ *
* You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
+ * You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
- *
+ *
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
- *
+ *
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*/
-#include "path.h"
-
-#include "ord.h"
-
-namespace Geom {
-
-
-int CurveHelpers::root_winding(Curve const &c, Point p) {
- std::vector<double> ts = c.roots(p[Y], Y);
-
- if(ts.empty()) return 0;
-
- double const fudge = 0.01; //fudge factor used on first and last
- std::sort(ts.begin(), ts.end());
- // winding determined by crossings at roots
- int wind=0;
- // previous time
- double pt = ts.front() - fudge;
- for ( std::vector<double>::iterator ti = ts.begin()
- ; ti != ts.end()
- ; ++ti )
- {
- double t = *ti;
- if ( t <= 0. || t >= 1. ) continue; //skip endpoint roots
- if ( c.valueAt(t, X) > p[X] ) { // root is ray intersection
- // Get t of next:
- std::vector<double>::iterator next = ti;
- next++;
- double nt;
- if(next == ts.end()) nt = t + fudge; else nt = *next;
-
- // Check before in time and after in time for positions
- // Currently we're using the average times between next and previous segs
- Cmp after_to_ray = cmp(c.valueAt((t + nt) / 2, Y), p[Y]);
- Cmp before_to_ray = cmp(c.valueAt((t + pt) / 2, Y), p[Y]);
- // if y is included, these will have opposite values, giving order.
- Cmp dt = cmp(after_to_ray, before_to_ray);
- if(dt != EQUAL_TO) //Should always be true, but yah never know..
- wind += dt;
- pt = t;
- }
- }
-
- return wind;
-}
+#include "path.h"
-template<>
-inline
-double LineSegment::nearestPoint(Point const& p, double from, double to) const
+namespace Geom
{
- if ( from > to ) std::swap(from, to);
- Point ip = pointAt(from);
- Point fp = pointAt(to);
- Point v = fp - ip;
- double t = dot( p - ip, v ) / L2sq(v);
- if ( t <= 0 ) return from;
- else if ( t >= 1 ) return to;
- else return from + t*(to-from);
-}
-
void Path::swap(Path &other) {
std::swap(curves_, other.curves_);
diff --git a/src/2geom/path.h b/src/2geom/path.h
index abed8604ab963243492b2df0bb3f773a2832ab89..670d4c1251eeb0c23fe97195a49055712290ee60 100644 (file)
--- a/src/2geom/path.h
+++ b/src/2geom/path.h
* the specific language governing rights and limitations.
*/
-#ifndef SEEN_GEOM_PATH_H
-#define SEEN_GEOM_PATH_H
-
-#include "point.h"
-#include "angle.h"
-#include <iterator>
-#include <algorithm>
-#include "exception.h"
-#include "d2.h"
-#include "matrix.h"
-#include "bezier.h"
-#include "crossing.h"
-#include "utils.h"
-#include "nearest-point.h"
-
-namespace Geom {
-
-class Curve;
-
-struct CurveHelpers {
-protected:
- static int root_winding(Curve const &c, Point p);
-};
-
-class Curve : private CurveHelpers {
-public:
- virtual ~Curve() {}
-
- virtual Point initialPoint() const = 0;
- virtual Point finalPoint() const = 0;
-
- virtual bool isDegenerate() const = 0;
-
- virtual Curve *duplicate() const = 0;
-
- virtual Rect boundsFast() const = 0;
- virtual Rect boundsExact() const = 0;
- virtual Rect boundsLocal(Interval i, unsigned deg) const = 0;
- Rect boundsLocal(Interval i) const { return boundsLocal(i, 0); }
-
- virtual std::vector<double> roots(double v, Dim2 d) const = 0;
-
- virtual int winding(Point p) const { return root_winding(*this, p); }
-
- //mental: review these
- virtual Curve *portion(double f, double t) const = 0;
- virtual Curve *reverse() const { return portion(1, 0); }
- virtual Curve *derivative() const = 0;
-
- 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;
-
- virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 1).front(); }
- virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; }
- virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const = 0;
- virtual D2<SBasis> toSBasis() const = 0;
-};
-
-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()) {}
- Curve *duplicate() const { return new SBasisCurve(*this); }
-
- Point initialPoint() const { return inner.at0(); }
- Point finalPoint() const { return inner.at1(); }
- bool isDegenerate() const { return inner.isConstant(); }
- Point pointAt(Coord t) const { return inner.valueAt(t); }
- std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const {
- return inner.valueAndDerivatives(t, n);
- }
- double valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); }
-
- void setInitial(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][0] = v[d]; } }
- void setFinal(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][1] = v[d]; } }
-
- Rect boundsFast() const { return bounds_fast(inner); }
- Rect boundsExact() const { return bounds_exact(inner); }
- 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));
- }
-
- Curve *transformed(Matrix const &m) const {
- return new SBasisCurve(inner * m);
- }
-
- Curve *derivative() const {
- return new SBasisCurve(Geom::derivative(inner));
- }
-
- D2<SBasis> toSBasis() const { return inner; }
-
-};
-
-template <unsigned order>
-class BezierCurve : public Curve {
-
-private:
- D2<Bezier > inner;
-
-public:
- template <unsigned required_degree>
- static void assert_degree(BezierCurve<required_degree> const *) {}
-
- BezierCurve() : inner(Bezier::Order(order), Bezier::Order(order)) {
- }
- explicit BezierCurve(D2<Bezier > const &x) : inner(x) {}
- BezierCurve(Bezier x, Bezier y) : inner(x, y) {}
- // default copy
- // default assign
-
- BezierCurve(Point c0, Point c1) {
- assert_degree<1>(this);
- for(unsigned d = 0; d < 2; d++)
- inner[d] = Bezier(c0[d], c1[d]);
- }
-
- BezierCurve(Point c0, Point c1, Point c2) {
- assert_degree<2>(this);
- for(unsigned d = 0; d < 2; d++)
- inner[d] = Bezier(c0[d], c1[d], c2[d]);
- }
-
- BezierCurve(Point c0, Point c1, Point c2, Point c3) {
- assert_degree<3>(this);
- for(unsigned d = 0; d < 2; d++)
- inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]);
- }
-
- unsigned degree() const { return order; }
-
- Curve *duplicate() const { return new BezierCurve(*this); }
-
- Point initialPoint() const { return inner.at0(); }
- Point finalPoint() const { return inner.at1(); }
-
- bool isDegenerate() const { return inner.isConstant(); }
-
- void setInitial(Point v) { setPoint(0, v); }
- void setFinal(Point v) { setPoint(order, v); }
-
- void setPoint(unsigned ix, Point v) { inner[X].setPoint(ix, v[X]); inner[Y].setPoint(ix, v[Y]); }
- Point const operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
-
- Rect boundsFast() const { return bounds_fast(inner); }
- Rect boundsExact() const { return bounds_exact(inner); }
- Rect boundsLocal(Interval i, unsigned deg) const {
- if(i.min() == 0 && i.max() == 1) return boundsFast();
- if(deg == 0) return bounds_local(inner, i);
- // TODO: UUUUUUGGGLLY
- if(deg == 1 && order > 1) return Rect(bounds_local(Geom::derivative(inner[X]), i),
- bounds_local(Geom::derivative(inner[Y]), i));
- return Rect(Interval(0,0), Interval(0,0));
- }
-//TODO: local
-
-//TODO: implement next 3 natively
- int winding(Point p) const {
- return SBasisCurve(toSBasis()).winding(p);
- }
-
- std::vector<double>
- 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]);
- }
- }
- std::vector<Point> points() const { return bezier_points(inner); }
-
- std::pair<BezierCurve<order>, BezierCurve<order> > subdivide(Coord t) const {
- std::pair<Bezier, Bezier > sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
- return std::pair<BezierCurve<order>, BezierCurve<order> >(
- BezierCurve<order>(sx.first, sy.first),
- BezierCurve<order>(sx.second, sy.second));
- }
-
- Curve *portion(double f, double t) const {
- return new BezierCurve(Geom::portion(inner, f, t));
- }
-
- Curve *reverse() const {
- return new BezierCurve(Geom::reverse(inner));
- }
-
- Curve *transformed(Matrix const &m) const {
- BezierCurve *ret = new BezierCurve();
- std::vector<Point> ps = points();
- for(unsigned i = 0; i <= order; i++) ps[i] = ps[i] * m;
- ret->setPoints(ps);
- return ret;
- }
-
- Curve *derivative() const {
- if(order > 1)
- return new BezierCurve<order-1>(Geom::derivative(inner[X]), Geom::derivative(inner[Y]));
- else if (order == 1) {
- double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0];
- return new BezierCurve<1>(Point(dx,dy),Point(dx,dy));
- }
- }
-
- Point pointAt(double t) const { return inner.valueAt(t); }
- std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const { return inner.valueAndDerivatives(t, n); }
-
- double valueAt(double t, Dim2 d) const { return inner[d].valueAt(t); }
-
- D2<SBasis> toSBasis() const {return inner.toSBasis(); }
-
-protected:
- BezierCurve(Point c[]) {
- Coord x[order+1], y[order+1];
- for(unsigned i = 0; i <= order; i++) {
- x[i] = c[i][X]; y[i] = c[i][Y];
- }
- inner = Bezier(x, y);
- }
-};
-
-// BezierCurve<0> is meaningless; specialize it out
-template<> class BezierCurve<0> : public BezierCurve<1> { public: BezierCurve(); BezierCurve(Bezier x, Bezier y); };
+#ifndef SEEN_GEOM_PATH_H
+#define SEEN_GEOM_PATH_H
-typedef BezierCurve<1> LineSegment;
-typedef BezierCurve<2> QuadraticBezier;
-typedef BezierCurve<3> CubicBezier;
-template<>
-double LineSegment::nearestPoint(Point const& p, double from, double to) const;
+#include "curves.h"
+#include <iterator>
-class EllipticalArc : public Curve
+namespace Geom
{
- public:
- EllipticalArc()
- : 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);
- }
-
- EllipticalArc( 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();
- }
-
- 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 EllipticalArc(*this);
- }
-
- double center(unsigned int i) const
- {
- return m_center[i];
- }
-
- Point center() const
- {
- return m_center;
- }
-
- Point initialPoint() const
- {
- return m_initial_point;
- }
-
- Point finalPoint() const
- {
- return m_final_point;
- }
-
- double start_angle() const
- {
- return m_start_angle;
- }
-
- double end_angle() const
- {
- return m_end_angle;
- }
-
- double ray(unsigned int i) const
- {
- return (i == 0) ? m_rx : m_ry;
- }
-
- bool large_arc_flag() const
- {
- return m_large_arc;
- }
-
- bool sweep_flag() const
- {
- return m_sweep;
- }
-
- double rotation_angle() const
- {
- return m_rot_angle;
- }
-
- void setInitial( const Point _point)
- {
- m_initial_point = _point;
- calculate_center_and_extreme_angles();
- }
-
- void setFinal( const Point _point)
- {
- m_final_point = _point;
- calculate_center_and_extreme_angles();
- }
-
- void setExtremes( const Point& _initial_point, const Point& _final_point )
- {
- m_initial_point = _initial_point;
- m_final_point = _final_point;
- calculate_center_and_extreme_angles();
- }
-
- bool isDegenerate() const
- {
- return ( are_near(ray(X), 0) || are_near(ray(Y), 0) );
- }
-
- // TODO: native implementation of the following methods
- Rect boundsFast() const
- {
- return 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>
- allNearestPoints( Point const& p, double from = 0, double to = 1 ) const;
-
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const
- {
- if ( are_near(ray(X), ray(Y)) && are_near(center(), p) )
- {
- return from;
- }
- return allNearestPoints(p, from, to).front();
- }
-
- int winding(Point p) const
- {
- return SBasisCurve(toSBasis()).winding(p);
- }
-
- Curve *derivative() const;
-
- Curve *transformed(Matrix const &m) const
- {
- return SBasisCurve(toSBasis()).transformed(m);
- }
-
- std::vector<Point> pointAndDerivatives(Coord t, unsigned int n) const;
-
- D2<SBasis> toSBasis() const;
-
- bool containsAngle(Coord angle) const;
-
- double valueAtAngle(Coord t, Dim2 d) const;
-
- Point pointAtAngle(Coord t) const
- {
- 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(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<EllipticalArc, EllipticalArc>
- subdivide(Coord t) const
- {
- EllipticalArc* arc1 = static_cast<EllipticalArc*>(portion(0, t));
- EllipticalArc* arc2 = static_cast<EllipticalArc*>(portion(t, 1));
- assert( arc1 != NULL && arc2 != NULL);
- std::pair<EllipticalArc, EllipticalArc> arc_pair(*arc1, *arc2);
- delete arc1;
- delete arc2;
- return arc_pair;
- }
-
- Curve* portion(double f, double t) const;
-
- // the arc is the same but traversed in the opposite direction
- Curve* reverse() const
- {
- EllipticalArc* rarc = new EllipticalArc( *this );
- rarc->m_sweep = !m_sweep;
- rarc->m_initial_point = m_final_point;
- rarc->m_final_point = m_initial_point;
- rarc->m_start_angle = m_end_angle;
- rarc->m_end_angle = m_start_angle;
- return rarc;
- }
-
- double sweep_angle() const
- {
- Coord d = end_angle() - start_angle();
- if ( !sweep_flag() ) d = -d;
- if ( d < 0 )
- d += 2*M_PI;
- return d;
- }
-
- 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;
- double m_start_angle, m_end_angle;
- Point m_center;
-
-}; // end class EllipticalArc
-
-
-
template <typename IteratorImpl>
class BaseIterator
Sequence curves_;
LineSegment *final_;
bool closed_;
-};
+
+}; // end class Path
inline static Piecewise<D2<SBasis> > paths_to_pw(std::vector<Path> paths) {
Piecewise<D2<SBasis> > ret = paths[0].toPwSb();
};
*/
-}
+} // end namespace Geom
namespace std {
a.swap(b);
}
-}
+} // end namespace std
+
#endif // SEEN_GEOM_PATH_H
+
+
+
/*
Local Variables:
mode:c++
diff --git a/src/2geom/sbasis-curve.h b/src/2geom/sbasis-curve.h
--- /dev/null
+++ b/src/2geom/sbasis-curve.h
@@ -0,0 +1,121 @@
+/*
+ * Simmetric Power Bais Curve
+ *
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
+ *
+ * Copyright 2007-2008 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+
+
+
+#ifndef _2GEOM_SBASIS_CURVE_H_
+#define _2GEOM_SBASIS_CURVE_H_
+
+
+#include "curve.h"
+
+
+namespace Geom
+{
+
+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()) {}
+ Curve *duplicate() const { return new SBasisCurve(*this); }
+
+ Point initialPoint() const { return inner.at0(); }
+ Point finalPoint() const { return inner.at1(); }
+ bool isDegenerate() const { return inner.isConstant(); }
+ Point pointAt(Coord t) const { return inner.valueAt(t); }
+ std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const {
+ return inner.valueAndDerivatives(t, n);
+ }
+ double valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); }
+
+ void setInitial(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][0] = v[d]; } }
+ void setFinal(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][1] = v[d]; } }
+
+ Rect boundsFast() const { return bounds_fast(inner); }
+ Rect boundsExact() const { return bounds_exact(inner); }
+ 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));
+ }
+
+ Curve *transformed(Matrix const &m) const {
+ return new SBasisCurve(inner * m);
+ }
+
+ Curve *derivative() const {
+ return new SBasisCurve(Geom::derivative(inner));
+ }
+
+ D2<SBasis> toSBasis() const { return inner; }
+
+};
+
+
+} // end namespace Geom
+
+
+#endif // _2GEOM_SBASIS_CURVE_H_
+
+
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :