Code

Merge from fe-moved
[inkscape.git] / src / 2geom / d2.h
1 /**
2  * \file
3  * \brief   Lifts one dimensional objects into 2d 
4  *
5  * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, output to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  *
30  */
32 #ifndef _2GEOM_D2  //If this is change, change the guard in rect.h as well.
33 #define _2GEOM_D2
35 #include <2geom/point.h>
36 #include <2geom/interval.h>
37 #include <2geom/matrix.h>
39 #include <boost/concept_check.hpp>
40 #include <2geom/concepts.h>
42 namespace Geom{
43 /**
44  * The D2 class takes two instances of a scalar data type and treats them
45  * like a point. All operations which make sense on a point are deļ¬ned for D2.
46  * A D2<double> is a Point. A D2<Interval> is a standard axis aligned rectangle.
47  * D2<SBasis> provides a 2d parametric function which maps t to a point
48  * x(t), y(t)
49  */
50 template <class T>
51 class D2{
52     //BOOST_CLASS_REQUIRE(T, boost, AssignableConcept);
53   private:
54     T f[2];
56   public:
57     D2() {f[X] = f[Y] = T();}
58     explicit D2(Point const &a) {
59         f[X] = T(a[X]); f[Y] = T(a[Y]);
60     }
62     D2(T const &a, T const &b) {
63         f[X] = a;
64         f[Y] = b;
65     }
67     //TODO: ask mental about operator= as seen in Point
69     T& operator[](unsigned i)              { return f[i]; }
70     T const & operator[](unsigned i) const { return f[i]; }
72     //IMPL: FragmentConcept
73     typedef Point output_type;
74     bool isZero() const {
75         boost::function_requires<FragmentConcept<T> >();
76         return f[X].isZero() && f[Y].isZero();
77     }
78     bool isConstant() const {
79         boost::function_requires<FragmentConcept<T> >();
80         return f[X].isConstant() && f[Y].isConstant();
81     }
82     bool isFinite() const {
83         boost::function_requires<FragmentConcept<T> >();
84         return f[X].isFinite() && f[Y].isFinite();
85     }
86     Point at0() const { 
87         boost::function_requires<FragmentConcept<T> >();
88         return Point(f[X].at0(), f[Y].at0());
89     }
90     Point at1() const {
91         boost::function_requires<FragmentConcept<T> >();
92         return Point(f[X].at1(), f[Y].at1());
93     }
94     Point valueAt(double t) const {
95         boost::function_requires<FragmentConcept<T> >();
96         return (*this)(t);
97     }
98     std::vector<Point > valueAndDerivatives(double t, unsigned n) const {
99         std::vector<Coord> x = f[X].valueAndDerivatives(t, n),
100                            y = f[Y].valueAndDerivatives(t, n);
101         std::vector<Point> res;
102         for(unsigned i = 0; i <= n; i++) {
103             res.push_back(Point(x[i], y[i]));
104         }
105         return res;
106     }
107     D2<SBasis> toSBasis() const {
108         boost::function_requires<FragmentConcept<T> >();
109         return D2<SBasis>(f[X].toSBasis(), f[Y].toSBasis());
110     }
112     Point operator()(double t) const;
113     Point operator()(double x, double y) const;
114 };
115 template <typename T>
116 inline D2<T> reverse(const D2<T> &a) {
117     boost::function_requires<FragmentConcept<T> >();
118     return D2<T>(reverse(a[X]), reverse(a[Y]));
121 template <typename T>
122 inline D2<T> portion(const D2<T> &a, Coord f, Coord t) {
123     boost::function_requires<FragmentConcept<T> >();
124     return D2<T>(portion(a[X], f, t), portion(a[Y], f, t));
127 //IMPL: boost::EqualityComparableConcept
128 template <typename T>
129 inline bool
130 operator==(D2<T> const &a, D2<T> const &b) {
131     boost::function_requires<boost::EqualityComparableConcept<T> >();
132     return a[0]==b[0] && a[1]==b[1];
134 template <typename T>
135 inline bool
136 operator!=(D2<T> const &a, D2<T> const &b) {
137     boost::function_requires<boost::EqualityComparableConcept<T> >();
138     return a[0]!=b[0] || a[1]!=b[1];
141 //IMPL: NearConcept
142 template <typename T>
143 inline bool
144 are_near(D2<T> const &a, D2<T> const &b, double tol) {
145     boost::function_requires<NearConcept<T> >();
146     return are_near(a[0], b[0]) && are_near(a[1], b[1]);
149 //IMPL: AddableConcept
150 template <typename T>
151 inline D2<T>
152 operator+(D2<T> const &a, D2<T> const &b) {
153     boost::function_requires<AddableConcept<T> >();
155     D2<T> r;
156     for(unsigned i = 0; i < 2; i++)
157         r[i] = a[i] + b[i];
158     return r;
160 template <typename T>
161 inline D2<T>
162 operator-(D2<T> const &a, D2<T> const &b) {
163     boost::function_requires<AddableConcept<T> >();
165     D2<T> r;
166     for(unsigned i = 0; i < 2; i++)
167         r[i] = a[i] - b[i];
168     return r;
170 template <typename T>
171 inline D2<T>
172 operator+=(D2<T> &a, D2<T> const &b) {
173     boost::function_requires<AddableConcept<T> >();
175     for(unsigned i = 0; i < 2; i++)
176         a[i] += b[i];
177     return a;
179 template <typename T>
180 inline D2<T>
181 operator-=(D2<T> &a, D2<T> const & b) {
182     boost::function_requires<AddableConcept<T> >();
184     for(unsigned i = 0; i < 2; i++)
185         a[i] -= b[i];
186     return a;
189 //IMPL: ScalableConcept
190 template <typename T>
191 inline D2<T>
192 operator-(D2<T> const & a) {
193     boost::function_requires<ScalableConcept<T> >();
194     D2<T> r;
195     for(unsigned i = 0; i < 2; i++)
196         r[i] = -a[i];
197     return r;
199 template <typename T>
200 inline D2<T>
201 operator*(D2<T> const & a, Point const & b) {
202     boost::function_requires<ScalableConcept<T> >();
204     D2<T> r;
205     for(unsigned i = 0; i < 2; i++)
206         r[i] = a[i] * b[i];
207     return r;
209 template <typename T>
210 inline D2<T>
211 operator/(D2<T> const & a, Point const & b) {
212     boost::function_requires<ScalableConcept<T> >();
213     //TODO: b==0?
214     D2<T> r;
215     for(unsigned i = 0; i < 2; i++)
216         r[i] = a[i] / b[i];
217     return r;
219 template <typename T>
220 inline D2<T>
221 operator*=(D2<T> &a, Point const & b) {
222     boost::function_requires<ScalableConcept<T> >();
224     for(unsigned i = 0; i < 2; i++)
225         a[i] *= b[i];
226     return a;
228 template <typename T>
229 inline D2<T>
230 operator/=(D2<T> &a, Point const & b) {
231     boost::function_requires<ScalableConcept<T> >();
232     //TODO: b==0?
233     for(unsigned i = 0; i < 2; i++)
234         a[i] /= b[i];
235     return a;
238 template <typename T>
239 inline D2<T> operator*(D2<T> const & a, double b) { return D2<T>(a[0]*b, a[1]*b); }
240 template <typename T> 
241 inline D2<T> operator*=(D2<T> & a, double b) { a[0] *= b; a[1] *= b; return a; }
242 template <typename T>
243 inline D2<T> operator/(D2<T> const & a, double b) { return D2<T>(a[0]/b, a[1]/b); }
244 template <typename T> 
245 inline D2<T> operator/=(D2<T> & a, double b) { a[0] /= b; a[1] /= b; return a; }
247 template<typename T>
248 D2<T> operator*(D2<T> const &v, Matrix const &m) {
249     boost::function_requires<AddableConcept<T> >();
250     boost::function_requires<ScalableConcept<T> >();
251     D2<T> ret;
252     for(unsigned i = 0; i < 2; i++)
253         ret[i] = v[X] * m[i] + v[Y] * m[i + 2] + m[i + 4];
254     return ret;
257 //IMPL: MultiplicableConcept
258 template <typename T>
259 inline D2<T>
260 operator*(D2<T> const & a, T const & b) {
261     boost::function_requires<MultiplicableConcept<T> >();
262     D2<T> ret;
263     for(unsigned i = 0; i < 2; i++)
264         ret[i] = a[i] * b;
265     return ret;
268 //IMPL: 
270 //IMPL: OffsetableConcept
271 template <typename T>
272 inline D2<T>
273 operator+(D2<T> const & a, Point b) {
274     boost::function_requires<OffsetableConcept<T> >();
275     D2<T> r;
276     for(unsigned i = 0; i < 2; i++)
277         r[i] = a[i] + b[i];
278     return r;
280 template <typename T>
281 inline D2<T>
282 operator-(D2<T> const & a, Point b) {
283     boost::function_requires<OffsetableConcept<T> >();
284     D2<T> r;
285     for(unsigned i = 0; i < 2; i++)
286         r[i] = a[i] - b[i];
287     return r;
289 template <typename T>
290 inline D2<T>
291 operator+=(D2<T> & a, Point b) {
292     boost::function_requires<OffsetableConcept<T> >();
293     for(unsigned i = 0; i < 2; i++)
294         a[i] += b[i];
295     return a;
297 template <typename T>
298 inline D2<T>
299 operator-=(D2<T> & a, Point b) {
300     boost::function_requires<OffsetableConcept<T> >();
301     for(unsigned i = 0; i < 2; i++)
302         a[i] -= b[i];
303     return a;
306 template <typename T>
307 inline T
308 dot(D2<T> const & a, D2<T> const & b) {
309     boost::function_requires<AddableConcept<T> >();
310     boost::function_requires<MultiplicableConcept<T> >();
312     T r;
313     for(unsigned i = 0; i < 2; i++)
314         r += a[i] * b[i];
315     return r;
318 template <typename T>
319 inline T
320 cross(D2<T> const & a, D2<T> const & b) {
321     boost::function_requires<ScalableConcept<T> >();
322     boost::function_requires<MultiplicableConcept<T> >();
324     return a[1] * b[0] - a[0] * b[1];
328 //equivalent to cw/ccw, for use in situations where rotation direction doesn't matter.
329 template <typename T>
330 inline D2<T>
331 rot90(D2<T> const & a) {
332     boost::function_requires<ScalableConcept<T> >();
333     return D2<T>(-a[Y], a[X]);
336 //TODO: concepterize the following functions
337 template <typename T>
338 inline D2<T>
339 compose(D2<T> const & a, T const & b) {
340     D2<T> r;
341     for(unsigned i = 0; i < 2; i++)
342         r[i] = compose(a[i],b);
343     return r;
346 template <typename T>
347 inline D2<T>
348 compose_each(D2<T> const & a, D2<T> const & b) {
349     D2<T> r;
350     for(unsigned i = 0; i < 2; i++)
351         r[i] = compose(a[i],b[i]);
352     return r;
355 template <typename T>
356 inline D2<T>
357 compose_each(T const & a, D2<T> const & b) {
358     D2<T> r;
359     for(unsigned i = 0; i < 2; i++)
360         r[i] = compose(a,b[i]);
361     return r;
365 template<typename T>
366 inline Point
367 D2<T>::operator()(double t) const {
368     Point p;
369     for(unsigned i = 0; i < 2; i++)
370        p[i] = (*this)[i](t);
371     return p;
374 //TODO: we might want to have this take a Point as the parameter.
375 template<typename T>
376 inline Point
377 D2<T>::operator()(double x, double y) const {
378     Point p;
379     for(unsigned i = 0; i < 2; i++)
380        p[i] = (*this)[i](x, y);
381     return p;
385 template<typename T>
386 D2<T> derivative(D2<T> const & a) {
387     return D2<T>(derivative(a[X]), derivative(a[Y]));
389 template<typename T>
390 D2<T> integral(D2<T> const & a) {
391     return D2<T>(integral(a[X]), integral(a[Y]));
394 } //end namespace Geom
396 #include <2geom/rect.h>
397 #include <2geom/d2-sbasis.h>
399 namespace Geom{
401 //Some D2 Fragment implementation which requires rect:
402 template <typename T>
403 OptRect bounds_fast(const D2<T> &a) {
404     boost::function_requires<FragmentConcept<T> >();
405     return OptRect(bounds_fast(a[X]), bounds_fast(a[Y]));
407 template <typename T>
408 OptRect bounds_exact(const D2<T> &a) {
409     boost::function_requires<FragmentConcept<T> >();
410     return OptRect(bounds_exact(a[X]), bounds_exact(a[Y]));
412 template <typename T>
413 OptRect bounds_local(const D2<T> &a, const OptInterval &t) {
414     boost::function_requires<FragmentConcept<T> >();
415     return OptRect(bounds_local(a[X], t), bounds_local(a[Y], t));
417 };
419 /*
420   Local Variables:
421   mode:c++
422   c-file-style:"stroustrup"
423   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
424   indent-tabs-mode:nil
425   fill-column:99
426   End:
427 */
428 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
429 #endif