diff --git a/src/2geom/d2.h b/src/2geom/d2.h
index 696ad0191411b04f5ddc5f2b7e1ef79cb61b7111..b2a0f886694ef36658efbffa1e5e98bada92b87e 100644 (file)
--- a/src/2geom/d2.h
+++ b/src/2geom/d2.h
-/*\r
- * d2.h - Lifts one dimensional objects into 2d \r
- *\r
- * Copyright 2007 Michael Sloan <mgsloan@gmail.com>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it either under the terms of the GNU Lesser General Public\r
- * License version 2.1 as published by the Free Software Foundation\r
- * (the "LGPL") or, at your option, under the terms of the Mozilla\r
- * Public License Version 1.1 (the "MPL"). If you do not alter this\r
- * notice, a recipient may use your version of this file under either\r
- * the MPL or the LGPL.\r
- *\r
- * You should have received a copy of the LGPL along with this library\r
- * in the file COPYING-LGPL-2.1; if not, output to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- * You should have received a copy of the MPL along with this library\r
- * in the file COPYING-MPL-1.1\r
- *\r
- * The contents of this file are subject to the Mozilla Public License\r
- * Version 1.1 (the "License"); you may not use this file except in\r
- * compliance with the License. You may obtain a copy of the License at\r
- * http://www.mozilla.org/MPL/\r
- *\r
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY\r
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for\r
- * the specific language governing rights and limitations.\r
- *\r
- */\r
-\r
-#ifndef _2GEOM_D2 //If this is change, change the guard in rect.h as well.\r
-#define _2GEOM_D2\r
-\r
-#include "point.h"\r
-#include "interval.h"\r
-#include "matrix.h"\r
-\r
-#include <boost/concept_check.hpp>\r
-#include "concepts.h"\r
-\r
-namespace Geom{\r
-\r
-template <class T>\r
-class D2{\r
- //BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);\r
- private:\r
- T f[2];\r
-\r
- public:\r
- D2() {f[X] = f[Y] = T();}\r
- explicit D2(Point const &a) {\r
- f[X] = T(a[X]); f[Y] = T(a[Y]);\r
- }\r
-\r
- D2(T const &a, T const &b) {\r
- f[X] = a;\r
- f[Y] = b;\r
- }\r
-\r
- //TODO: ask mental about operator= as seen in Point\r
-\r
- T& operator[](unsigned i) { return f[i]; }\r
- T const & operator[](unsigned i) const { return f[i]; }\r
-\r
- //IMPL: FragmentConcept\r
- typedef Point output_type;\r
- bool isZero() const {\r
- boost::function_requires<FragmentConcept<T> >();\r
- return f[X].isZero() && f[Y].isZero();\r
- }\r
- bool isFinite() const {\r
- boost::function_requires<FragmentConcept<T> >();\r
- return f[X].isFinite() && f[Y].isFinite();\r
- }\r
- Point at0() const { \r
- boost::function_requires<FragmentConcept<T> >();\r
- return Point(f[X].at0(), f[Y].at0());\r
- }\r
- Point at1() const {\r
- boost::function_requires<FragmentConcept<T> >();\r
- return Point(f[X].at1(), f[Y].at1());\r
- }\r
- Point valueAt(double t) const {\r
- boost::function_requires<FragmentConcept<T> >();\r
- return (*this)(t);\r
+/**
+ * \file
+ * \brief Lifts one dimensional objects into 2d
+ *
+ * Copyright 2007 Michael Sloan <mgsloan@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, output 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_D2 //If this is change, change the guard in rect.h as well.
+#define _2GEOM_D2
+
+#include <2geom/point.h>
+#include <2geom/interval.h>
+#include <2geom/matrix.h>
+
+#include <boost/concept_check.hpp>
+#include <2geom/concepts.h>
+
+namespace Geom{
+/**
+ * The D2 class takes two instances of a scalar data type and treats them
+ * like a point. All operations which make sense on a point are deļ¬ned for D2.
+ * A D2<double> is a Point. A D2<Interval> is a standard axis aligned rectangle.
+ * D2<SBasis> provides a 2d parametric function which maps t to a point
+ * x(t), y(t)
+ */
+template <class T>
+class D2{
+ //BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
+ private:
+ T f[2];
+
+ public:
+ D2() {f[X] = f[Y] = T();}
+ explicit D2(Point const &a) {
+ f[X] = T(a[X]); f[Y] = T(a[Y]);
}
- std::vector<Point > valueAndDerivatives(double t, unsigned count) const {
- std::vector<Coord> x = f[X].valueAndDerivatives(t, count),
- y = f[Y].valueAndDerivatives(t, count);
- std::vector<Point> res;
- for(unsigned i = 0; i < count; i++) {
- res.push_back(Point(x[i], y[i]));
+
+ D2(T const &a, T const &b) {
+ f[X] = a;
+ f[Y] = b;
+ }
+
+ //TODO: ask mental about operator= as seen in Point
+
+ T& operator[](unsigned i) { return f[i]; }
+ T const & operator[](unsigned i) const { return f[i]; }
+
+ //IMPL: FragmentConcept
+ typedef Point output_type;
+ bool isZero() const {
+ boost::function_requires<FragmentConcept<T> >();
+ return f[X].isZero() && f[Y].isZero();
+ }
+ bool isConstant() const {
+ boost::function_requires<FragmentConcept<T> >();
+ return f[X].isConstant() && f[Y].isConstant();
+ }
+ bool isFinite() const {
+ boost::function_requires<FragmentConcept<T> >();
+ return f[X].isFinite() && f[Y].isFinite();
+ }
+ Point at0() const {
+ boost::function_requires<FragmentConcept<T> >();
+ return Point(f[X].at0(), f[Y].at0());
+ }
+ Point at1() const {
+ boost::function_requires<FragmentConcept<T> >();
+ return Point(f[X].at1(), f[Y].at1());
+ }
+ Point valueAt(double t) const {
+ boost::function_requires<FragmentConcept<T> >();
+ return (*this)(t);
+ }
+ std::vector<Point > valueAndDerivatives(double t, unsigned n) const {
+ std::vector<Coord> x = f[X].valueAndDerivatives(t, n),
+ y = f[Y].valueAndDerivatives(t, n); // always returns a vector of size n+1
+ std::vector<Point> res(n+1);
+ for(unsigned i = 0; i <= n; i++) {
+ res[i] = Point(x[i], y[i]);
}
return res;
- }\r
- D2<SBasis> toSBasis() const {\r
- boost::function_requires<FragmentConcept<T> >();\r
- return D2<SBasis>(f[X].toSBasis(), f[Y].toSBasis());\r
- }\r
-\r
- Point operator()(double t) const;\r
- Point operator()(double x, double y) const;\r
-};\r\r
-template <typename T>\r
-inline D2<T> reverse(const D2<T> &a) {\r
- boost::function_requires<FragmentConcept<T> >();\r
- return D2<T>(reverse(a[X]), reverse(a[Y]));\r
-}\r
+ }
+ D2<SBasis> toSBasis() const {
+ boost::function_requires<FragmentConcept<T> >();
+ return D2<SBasis>(f[X].toSBasis(), f[Y].toSBasis());
+ }
+
+ Point operator()(double t) const;
+ Point operator()(double x, double y) const;
+};
+template <typename T>
+inline D2<T> reverse(const D2<T> &a) {
+ boost::function_requires<FragmentConcept<T> >();
+ return D2<T>(reverse(a[X]), reverse(a[Y]));
+}
template <typename T>
inline D2<T> portion(const D2<T> &a, Coord f, Coord t) {
boost::function_requires<FragmentConcept<T> >();
return D2<T>(portion(a[X], f, t), portion(a[Y], f, t));
}
-\r
-//IMPL: boost::EqualityComparableConcept\r
-template <typename T>\r
-inline bool\r
-operator==(D2<T> const &a, D2<T> const &b) {\r
- boost::function_requires<boost::EqualityComparableConcept<T> >();\r
- return a[0]==b[0] && a[1]==b[1];\r
-}\r
-template <typename T>\r
-inline bool\r
-operator!=(D2<T> const &a, D2<T> const &b) {\r
- boost::function_requires<boost::EqualityComparableConcept<T> >();\r
- return a[0]!=b[0] || a[1]!=b[1];\r
-}\r
-\r
-//IMPL: NearConcept\r
-template <typename T>\r
-inline bool\r
-near(D2<T> const &a, D2<T> const &b, double tol) {\r
- boost::function_requires<NearConcept<T> >();\r
- return near(a[0], b[0]) && near(a[1], b[1]);\r
-}\r
-\r
-//IMPL: AddableConcept\r
-template <typename T>\r
-inline D2<T>\r
-operator+(D2<T> const &a, D2<T> const &b) {\r
- boost::function_requires<AddableConcept<T> >();\r
-\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = a[i] + b[i];\r
- return r;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator-(D2<T> const &a, D2<T> const &b) {\r
- boost::function_requires<AddableConcept<T> >();\r
-\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = a[i] - b[i];\r
- return r;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator+=(D2<T> &a, D2<T> const &b) {\r
- boost::function_requires<AddableConcept<T> >();\r
-\r
- for(unsigned i = 0; i < 2; i++)\r
- a[i] += b[i];\r
- return a;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator-=(D2<T> &a, D2<T> const & b) {\r
- boost::function_requires<AddableConcept<T> >();\r
-\r
- for(unsigned i = 0; i < 2; i++)\r
- a[i] -= b[i];\r
- return a;\r
-}\r
-\r
-//IMPL: ScalableConcept\r
-template <typename T>\r
-inline D2<T>\r
-operator-(D2<T> const & a) {\r
- boost::function_requires<ScalableConcept<T> >();\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = -a[i];\r
- return r;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator*(D2<T> const & a, Point const & b) {\r
- boost::function_requires<ScalableConcept<T> >();\r
-\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = a[i] * b[i];\r
- return r;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator/(D2<T> const & a, Point const & b) {\r
- boost::function_requires<ScalableConcept<T> >();\r
- //TODO: b==0?\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = a[i] / b[i];\r
- return r;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator*=(D2<T> &a, Point const & b) {\r
- boost::function_requires<ScalableConcept<T> >();\r
-\r
- for(unsigned i = 0; i < 2; i++)\r
- a[i] *= b[i];\r
- return a;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator/=(D2<T> &a, Point const & b) {\r
- boost::function_requires<ScalableConcept<T> >();\r
- //TODO: b==0?\r
- for(unsigned i = 0; i < 2; i++)\r
- a[i] /= b[i];\r
- return a;\r
-}\r
-\r
-template <typename T>\r
-inline D2<T> operator*(D2<T> const & a, double b) { return D2<T>(a[0]*b, a[1]*b); }\r
-template <typename T> \r
-inline D2<T> operator*=(D2<T> & a, double b) { a[0] *= b; a[1] *= b; return a; }\r
-template <typename T>\r
-inline D2<T> operator/(D2<T> const & a, double b) { return D2<T>(a[0]/b, a[1]/b); }\r
-template <typename T> \r
-inline D2<T> operator/=(D2<T> & a, double b) { a[0] /= b; a[1] /= b; return a; }\r
-\r
-template<typename T>\r
-D2<T> operator*(D2<T> const &v, Matrix const &m) {\r
- boost::function_requires<AddableConcept<T> >();\r
- boost::function_requires<ScalableConcept<T> >();\r
- D2<T> ret;\r
- for(unsigned i = 0; i < 2; i++)\r
- ret[i] = v[X] * m[i] + v[Y] * m[i + 2] + m[i + 4];\r
- return ret;\r
-}\r
-\r
-//IMPL: OffsetableConcept\r
-template <typename T>\r
-inline D2<T>\r
-operator+(D2<T> const & a, Point b) {\r
- boost::function_requires<OffsetableConcept<T> >();\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = a[i] + b[i];\r
- return r;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator-(D2<T> const & a, Point b) {\r
- boost::function_requires<OffsetableConcept<T> >();\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = a[i] - b[i];\r
- return r;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator+=(D2<T> & a, Point b) {\r
- boost::function_requires<OffsetableConcept<T> >();\r
- for(unsigned i = 0; i < 2; i++)\r
- a[i] += b[i];\r
- return a;\r
-}\r
-template <typename T>\r
-inline D2<T>\r
-operator-=(D2<T> & a, Point b) {\r
- boost::function_requires<OffsetableConcept<T> >();\r
- for(unsigned i = 0; i < 2; i++)\r
- a[i] -= b[i];\r
- return a;\r
-}\r
-\r
-template <typename T>\r
-inline T\r
-dot(D2<T> const & a, D2<T> const & b) {\r
- boost::function_requires<AddableConcept<T> >();\r
- boost::function_requires<MultiplicableConcept<T> >();\r
-\r
- T r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r += a[i] * b[i];\r
- return r;\r
-}\r
-\r
-template <typename T>\r
-inline T\r
-cross(D2<T> const & a, D2<T> const & b) {\r
- boost::function_requires<ScalableConcept<T> >();\r
- boost::function_requires<MultiplicableConcept<T> >();\r
-\r
- return a[1] * b[0] - a[0] * b[1];\r
-}\r
-\r
-\r
-//equivalent to cw/ccw, for use in situations where rotation direction doesn't matter.\r
-template <typename T>\r
-inline D2<T>\r
-rot90(D2<T> const & a) {\r
- boost::function_requires<ScalableConcept<T> >();\r
- return D2<T>(-a[Y], a[X]);\r
-}\r
-\r
-//TODO: concepterize the following functions\r
-template <typename T>\r
-inline D2<T>\r
-compose(D2<T> const & a, T const & b) {\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = compose(a[i],b);\r
- return r;\r
-}\r
-\r
-template <typename T>\r
-inline D2<T>\r
-compose_each(D2<T> const & a, D2<T> const & b) {\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = compose(a[i],b[i]);\r
- return r;\r
-}\r
-\r
-template <typename T>\r
-inline D2<T>\r
-compose_each(T const & a, D2<T> const & b) {\r
- D2<T> r;\r
- for(unsigned i = 0; i < 2; i++)\r
- r[i] = compose(a,b[i]);\r
- return r;\r
-}\r
-\r
-\r
-template<typename T>\r
-inline Point\r
-D2<T>::operator()(double t) const {\r
- Point p;\r
- for(unsigned i = 0; i < 2; i++)\r
- p[i] = (*this)[i](t);\r
- return p;\r
-}\r
-\r
-//TODO: we might want to have this take a Point as the parameter.\r
-template<typename T>\r
-inline Point\r
-D2<T>::operator()(double x, double y) const {\r
- Point p;\r
- for(unsigned i = 0; i < 2; i++)\r
- p[i] = (*this)[i](x, y);\r
- return p;\r
-}\r
-\r
-\r
-template<typename T>\r
-D2<T> derivative(D2<T> const & a) {\r
- return D2<T>(derivative(a[X]), derivative(a[Y]));\r
-}\r\r
-template<typename T>\r
-D2<T> integral(D2<T> const & a) {\r
- return D2<T>(integral(a[X]), integral(a[Y]));\r
-}
-\r
-} //end namespace Geom\r
-\r
-#include "rect.h"\r
-#include "d2-sbasis.h"\r
-\r
-namespace Geom{\r
-\r
-//Some D2 Fragment implementation which requires rect:\r
-template <typename T>\r
-Rect bounds_fast(const D2<T> &a) {\r
- boost::function_requires<FragmentConcept<T> >(); \r
- return Rect(bounds_fast(a[X]), bounds_fast(a[Y]));\r
-}\r
-template <typename T>\r
-Rect bounds_exact(const D2<T> &a) {\r
- boost::function_requires<FragmentConcept<T> >(); \r
- return Rect(bounds_exact(a[X]), bounds_exact(a[Y]));\r
-}\r
-template <typename T>\r
-Rect bounds_local(const D2<T> &a, const Interval &t) {\r
- boost::function_requires<FragmentConcept<T> >(); \r
- return Rect(bounds_local(a[X], t), bounds_local(a[Y], t));\r
-}\r\r
-};\r
-\r
-/*\r
- Local Variables:\r
- mode:c++\r
- c-file-style:"stroustrup"\r
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
- indent-tabs-mode:nil\r
- fill-column:99\r
- End:\r
-*/\r
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r
-#endif\r
+
+template <typename T>
+inline D2<T> portion(const D2<T> &a, Interval i) {
+ boost::function_requires<FragmentConcept<T> >();
+ return D2<T>(portion(a[X], i), portion(a[Y], i));
+}
+
+//IMPL: boost::EqualityComparableConcept
+template <typename T>
+inline bool
+operator==(D2<T> const &a, D2<T> const &b) {
+ boost::function_requires<boost::EqualityComparableConcept<T> >();
+ return a[0]==b[0] && a[1]==b[1];
+}
+template <typename T>
+inline bool
+operator!=(D2<T> const &a, D2<T> const &b) {
+ boost::function_requires<boost::EqualityComparableConcept<T> >();
+ return a[0]!=b[0] || a[1]!=b[1];
+}
+
+//IMPL: NearConcept
+template <typename T>
+inline bool
+are_near(D2<T> const &a, D2<T> const &b, double tol) {
+ boost::function_requires<NearConcept<T> >();
+ return are_near(a[0], b[0]) && are_near(a[1], b[1]);
+}
+
+//IMPL: AddableConcept
+template <typename T>
+inline D2<T>
+operator+(D2<T> const &a, D2<T> const &b) {
+ boost::function_requires<AddableConcept<T> >();
+
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] + b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator-(D2<T> const &a, D2<T> const &b) {
+ boost::function_requires<AddableConcept<T> >();
+
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] - b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator+=(D2<T> &a, D2<T> const &b) {
+ boost::function_requires<AddableConcept<T> >();
+
+ for(unsigned i = 0; i < 2; i++)
+ a[i] += b[i];
+ return a;
+}
+template <typename T>
+inline D2<T>
+operator-=(D2<T> &a, D2<T> const & b) {
+ boost::function_requires<AddableConcept<T> >();
+
+ for(unsigned i = 0; i < 2; i++)
+ a[i] -= b[i];
+ return a;
+}
+
+//IMPL: ScalableConcept
+template <typename T>
+inline D2<T>
+operator-(D2<T> const & a) {
+ boost::function_requires<ScalableConcept<T> >();
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = -a[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator*(D2<T> const & a, Point const & b) {
+ boost::function_requires<ScalableConcept<T> >();
+
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] * b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator/(D2<T> const & a, Point const & b) {
+ boost::function_requires<ScalableConcept<T> >();
+ //TODO: b==0?
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] / b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator*=(D2<T> &a, Point const & b) {
+ boost::function_requires<ScalableConcept<T> >();
+
+ for(unsigned i = 0; i < 2; i++)
+ a[i] *= b[i];
+ return a;
+}
+template <typename T>
+inline D2<T>
+operator/=(D2<T> &a, Point const & b) {
+ boost::function_requires<ScalableConcept<T> >();
+ //TODO: b==0?
+ for(unsigned i = 0; i < 2; i++)
+ a[i] /= b[i];
+ return a;
+}
+
+template <typename T>
+inline D2<T> operator*(D2<T> const & a, double b) { return D2<T>(a[0]*b, a[1]*b); }
+template <typename T>
+inline D2<T> operator*=(D2<T> & a, double b) { a[0] *= b; a[1] *= b; return a; }
+template <typename T>
+inline D2<T> operator/(D2<T> const & a, double b) { return D2<T>(a[0]/b, a[1]/b); }
+template <typename T>
+inline D2<T> operator/=(D2<T> & a, double b) { a[0] /= b; a[1] /= b; return a; }
+
+template<typename T>
+D2<T> operator*(D2<T> const &v, Matrix const &m) {
+ boost::function_requires<AddableConcept<T> >();
+ boost::function_requires<ScalableConcept<T> >();
+ D2<T> ret;
+ for(unsigned i = 0; i < 2; i++)
+ ret[i] = v[X] * m[i] + v[Y] * m[i + 2] + m[i + 4];
+ return ret;
+}
+
+//IMPL: MultiplicableConcept
+template <typename T>
+inline D2<T>
+operator*(D2<T> const & a, T const & b) {
+ boost::function_requires<MultiplicableConcept<T> >();
+ D2<T> ret;
+ for(unsigned i = 0; i < 2; i++)
+ ret[i] = a[i] * b;
+ return ret;
+}
+
+//IMPL:
+
+//IMPL: OffsetableConcept
+template <typename T>
+inline D2<T>
+operator+(D2<T> const & a, Point b) {
+ boost::function_requires<OffsetableConcept<T> >();
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] + b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator-(D2<T> const & a, Point b) {
+ boost::function_requires<OffsetableConcept<T> >();
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = a[i] - b[i];
+ return r;
+}
+template <typename T>
+inline D2<T>
+operator+=(D2<T> & a, Point b) {
+ boost::function_requires<OffsetableConcept<T> >();
+ for(unsigned i = 0; i < 2; i++)
+ a[i] += b[i];
+ return a;
+}
+template <typename T>
+inline D2<T>
+operator-=(D2<T> & a, Point b) {
+ boost::function_requires<OffsetableConcept<T> >();
+ for(unsigned i = 0; i < 2; i++)
+ a[i] -= b[i];
+ return a;
+}
+
+template <typename T>
+inline T
+dot(D2<T> const & a, D2<T> const & b) {
+ boost::function_requires<AddableConcept<T> >();
+ boost::function_requires<MultiplicableConcept<T> >();
+
+ T r;
+ for(unsigned i = 0; i < 2; i++)
+ r += a[i] * b[i];
+ return r;
+}
+
+/** @brief Calculates the 'dot product' or 'inner product' of \c a and \c b
+ * @return \f$a \bullet b = a_X b_X + a_Y b_Y\f$.
+ * @relates D2 */
+template <typename T>
+inline T
+dot(D2<T> const & a, Point const & b) {
+ boost::function_requires<AddableConcept<T> >();
+ boost::function_requires<ScalableConcept<T> >();
+
+ T r;
+ for(unsigned i = 0; i < 2; i++) {
+ r += a[i] * b[i];
+ }
+ return r;
+}
+
+/** @brief Calculates the 'cross product' or 'outer product' of \c a and \c b
+ * @return \f$a \times b = a_Y b_X - a_X b_Y\f$.
+ * @relates D2 */
+template <typename T>
+inline T
+cross(D2<T> const & a, D2<T> const & b) {
+ boost::function_requires<ScalableConcept<T> >();
+ boost::function_requires<MultiplicableConcept<T> >();
+
+ return a[1] * b[0] - a[0] * b[1];
+}
+
+
+//equivalent to cw/ccw, for use in situations where rotation direction doesn't matter.
+template <typename T>
+inline D2<T>
+rot90(D2<T> const & a) {
+ boost::function_requires<ScalableConcept<T> >();
+ return D2<T>(-a[Y], a[X]);
+}
+
+//TODO: concepterize the following functions
+template <typename T>
+inline D2<T>
+compose(D2<T> const & a, T const & b) {
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = compose(a[i],b);
+ return r;
+}
+
+template <typename T>
+inline D2<T>
+compose_each(D2<T> const & a, D2<T> const & b) {
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = compose(a[i],b[i]);
+ return r;
+}
+
+template <typename T>
+inline D2<T>
+compose_each(T const & a, D2<T> const & b) {
+ D2<T> r;
+ for(unsigned i = 0; i < 2; i++)
+ r[i] = compose(a,b[i]);
+ return r;
+}
+
+
+template<typename T>
+inline Point
+D2<T>::operator()(double t) const {
+ Point p;
+ for(unsigned i = 0; i < 2; i++)
+ p[i] = (*this)[i](t);
+ return p;
+}
+
+//TODO: we might want to have this take a Point as the parameter.
+template<typename T>
+inline Point
+D2<T>::operator()(double x, double y) const {
+ Point p;
+ for(unsigned i = 0; i < 2; i++)
+ p[i] = (*this)[i](x, y);
+ return p;
+}
+
+
+template<typename T>
+D2<T> derivative(D2<T> const & a) {
+ return D2<T>(derivative(a[X]), derivative(a[Y]));
+}
+template<typename T>
+D2<T> integral(D2<T> const & a) {
+ return D2<T>(integral(a[X]), integral(a[Y]));
+}
+
+/** A function to print out the Point. It just prints out the coords
+ on the given output stream */
+template <typename T>
+inline std::ostream &operator<< (std::ostream &out_file, const Geom::D2<T> &in_d2) {
+ out_file << "X: " << in_d2[X] << " Y: " << in_d2[Y];
+ return out_file;
+}
+
+} //end namespace Geom
+
+#include <2geom/rect.h>
+#include <2geom/d2-sbasis.h>
+
+namespace Geom{
+
+//Some D2 Fragment implementation which requires rect:
+template <typename T>
+OptRect bounds_fast(const D2<T> &a) {
+ boost::function_requires<FragmentConcept<T> >();
+ return OptRect(bounds_fast(a[X]), bounds_fast(a[Y]));
+}
+template <typename T>
+OptRect bounds_exact(const D2<T> &a) {
+ boost::function_requires<FragmentConcept<T> >();
+ return OptRect(bounds_exact(a[X]), bounds_exact(a[Y]));
+}
+template <typename T>
+OptRect bounds_local(const D2<T> &a, const OptInterval &t) {
+ boost::function_requires<FragmentConcept<T> >();
+ return OptRect(bounds_local(a[X], t), bounds_local(a[Y], t));
+}
+};
+
+/*
+ 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 :
+#endif