Code

Applying second patch for bug #425557.
[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); // always returns a vector of size n+1
101         std::vector<Point> res(n+1);
102         for (unsigned i = 0; i <= n; i++) {
103             res[i] = 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 template <typename T>
128 inline D2<T> portion(const D2<T> &a, Interval i) {
129     boost::function_requires<FragmentConcept<T> >();
130     return D2<T>(portion(a[X], i), portion(a[Y], i));
133 //IMPL: boost::EqualityComparableConcept
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];
140 template <typename T>
141 inline bool
142 operator!=(D2<T> const &a, D2<T> const &b) {
143     boost::function_requires<boost::EqualityComparableConcept<T> >();
144     return a[0]!=b[0] || a[1]!=b[1];
147 //IMPL: NearConcept
148 template <typename T>
149 inline bool
150 are_near(D2<T> const &a, D2<T> const &b, double tol) {
151     boost::function_requires<NearConcept<T> >();
152     return are_near(a[0], b[0]) && are_near(a[1], b[1]);
155 //IMPL: AddableConcept
156 template <typename T>
157 inline D2<T>
158 operator+(D2<T> const &a, D2<T> const &b) {
159     boost::function_requires<AddableConcept<T> >();
161     D2<T> r;
162     for(unsigned i = 0; i < 2; i++)
163         r[i] = a[i] + b[i];
164     return r;
166 template <typename T>
167 inline D2<T>
168 operator-(D2<T> const &a, D2<T> const &b) {
169     boost::function_requires<AddableConcept<T> >();
171     D2<T> r;
172     for(unsigned i = 0; i < 2; i++)
173         r[i] = a[i] - b[i];
174     return r;
176 template <typename T>
177 inline D2<T>
178 operator+=(D2<T> &a, D2<T> const &b) {
179     boost::function_requires<AddableConcept<T> >();
181     for(unsigned i = 0; i < 2; i++)
182         a[i] += b[i];
183     return a;
185 template <typename T>
186 inline D2<T>
187 operator-=(D2<T> &a, D2<T> const & b) {
188     boost::function_requires<AddableConcept<T> >();
190     for(unsigned i = 0; i < 2; i++)
191         a[i] -= b[i];
192     return a;
195 //IMPL: ScalableConcept
196 template <typename T>
197 inline D2<T>
198 operator-(D2<T> const & a) {
199     boost::function_requires<ScalableConcept<T> >();
200     D2<T> r;
201     for(unsigned i = 0; i < 2; i++)
202         r[i] = -a[i];
203     return r;
205 template <typename T>
206 inline D2<T>
207 operator*(D2<T> const & a, Point const & b) {
208     boost::function_requires<ScalableConcept<T> >();
210     D2<T> r;
211     for(unsigned i = 0; i < 2; i++)
212         r[i] = a[i] * b[i];
213     return r;
215 template <typename T>
216 inline D2<T>
217 operator/(D2<T> const & a, Point const & b) {
218     boost::function_requires<ScalableConcept<T> >();
219     //TODO: b==0?
220     D2<T> r;
221     for(unsigned i = 0; i < 2; i++)
222         r[i] = a[i] / b[i];
223     return r;
225 template <typename T>
226 inline D2<T>
227 operator*=(D2<T> &a, Point const & b) {
228     boost::function_requires<ScalableConcept<T> >();
230     for(unsigned i = 0; i < 2; i++)
231         a[i] *= b[i];
232     return a;
234 template <typename T>
235 inline D2<T>
236 operator/=(D2<T> &a, Point const & b) {
237     boost::function_requires<ScalableConcept<T> >();
238     //TODO: b==0?
239     for(unsigned i = 0; i < 2; i++)
240         a[i] /= b[i];
241     return a;
244 template <typename T>
245 inline D2<T> operator*(D2<T> const & a, double b) { return D2<T>(a[0]*b, a[1]*b); }
246 template <typename T> 
247 inline D2<T> operator*=(D2<T> & a, double b) { a[0] *= b; a[1] *= b; return a; }
248 template <typename T>
249 inline D2<T> operator/(D2<T> const & a, double b) { return D2<T>(a[0]/b, a[1]/b); }
250 template <typename T> 
251 inline D2<T> operator/=(D2<T> & a, double b) { a[0] /= b; a[1] /= b; return a; }
253 template<typename T>
254 D2<T> operator*(D2<T> const &v, Matrix const &m) {
255     boost::function_requires<AddableConcept<T> >();
256     boost::function_requires<ScalableConcept<T> >();
257     D2<T> ret;
258     for(unsigned i = 0; i < 2; i++)
259         ret[i] = v[X] * m[i] + v[Y] * m[i + 2] + m[i + 4];
260     return ret;
263 //IMPL: MultiplicableConcept
264 template <typename T>
265 inline D2<T>
266 operator*(D2<T> const & a, T const & b) {
267     boost::function_requires<MultiplicableConcept<T> >();
268     D2<T> ret;
269     for(unsigned i = 0; i < 2; i++)
270         ret[i] = a[i] * b;
271     return ret;
274 //IMPL: 
276 //IMPL: OffsetableConcept
277 template <typename T>
278 inline D2<T>
279 operator+(D2<T> const & a, Point b) {
280     boost::function_requires<OffsetableConcept<T> >();
281     D2<T> r;
282     for(unsigned i = 0; i < 2; i++)
283         r[i] = a[i] + b[i];
284     return r;
286 template <typename T>
287 inline D2<T>
288 operator-(D2<T> const & a, Point b) {
289     boost::function_requires<OffsetableConcept<T> >();
290     D2<T> r;
291     for(unsigned i = 0; i < 2; i++)
292         r[i] = a[i] - b[i];
293     return r;
295 template <typename T>
296 inline D2<T>
297 operator+=(D2<T> & a, Point b) {
298     boost::function_requires<OffsetableConcept<T> >();
299     for(unsigned i = 0; i < 2; i++)
300         a[i] += b[i];
301     return a;
303 template <typename T>
304 inline D2<T>
305 operator-=(D2<T> & a, Point b) {
306     boost::function_requires<OffsetableConcept<T> >();
307     for(unsigned i = 0; i < 2; i++)
308         a[i] -= b[i];
309     return a;
312 template <typename T>
313 inline T
314 dot(D2<T> const & a, D2<T> const & b) {
315     boost::function_requires<AddableConcept<T> >();
316     boost::function_requires<MultiplicableConcept<T> >();
318     T r;
319     for(unsigned i = 0; i < 2; i++)
320         r += a[i] * b[i];
321     return r;
324 template <typename T>
325 inline T
326 cross(D2<T> const & a, D2<T> const & b) {
327     boost::function_requires<ScalableConcept<T> >();
328     boost::function_requires<MultiplicableConcept<T> >();
330     return a[1] * b[0] - a[0] * b[1];
334 //equivalent to cw/ccw, for use in situations where rotation direction doesn't matter.
335 template <typename T>
336 inline D2<T>
337 rot90(D2<T> const & a) {
338     boost::function_requires<ScalableConcept<T> >();
339     return D2<T>(-a[Y], a[X]);
342 //TODO: concepterize the following functions
343 template <typename T>
344 inline D2<T>
345 compose(D2<T> const & a, T const & b) {
346     D2<T> r;
347     for(unsigned i = 0; i < 2; i++)
348         r[i] = compose(a[i],b);
349     return r;
352 template <typename T>
353 inline D2<T>
354 compose_each(D2<T> const & a, D2<T> const & b) {
355     D2<T> r;
356     for(unsigned i = 0; i < 2; i++)
357         r[i] = compose(a[i],b[i]);
358     return r;
361 template <typename T>
362 inline D2<T>
363 compose_each(T const & a, D2<T> const & b) {
364     D2<T> r;
365     for(unsigned i = 0; i < 2; i++)
366         r[i] = compose(a,b[i]);
367     return r;
371 template<typename T>
372 inline Point
373 D2<T>::operator()(double t) const {
374     Point p;
375     for(unsigned i = 0; i < 2; i++)
376        p[i] = (*this)[i](t);
377     return p;
380 //TODO: we might want to have this take a Point as the parameter.
381 template<typename T>
382 inline Point
383 D2<T>::operator()(double x, double y) const {
384     Point p;
385     for(unsigned i = 0; i < 2; i++)
386        p[i] = (*this)[i](x, y);
387     return p;
391 template<typename T>
392 D2<T> derivative(D2<T> const & a) {
393     return D2<T>(derivative(a[X]), derivative(a[Y]));
395 template<typename T>
396 D2<T> integral(D2<T> const & a) {
397     return D2<T>(integral(a[X]), integral(a[Y]));
400 /** A function to print out the Point.  It just prints out the coords
401     on the given output stream */
402 template <typename T>
403 inline std::ostream &operator<< (std::ostream &out_file, const Geom::D2<T> &in_d2) {
404     out_file << "X: " << in_d2[X] << "  Y: " << in_d2[Y];
405     return out_file;
408 } //end namespace Geom
410 #include <2geom/rect.h>
411 #include <2geom/d2-sbasis.h>
413 namespace Geom{
415 //Some D2 Fragment implementation which requires rect:
416 template <typename T>
417 OptRect bounds_fast(const D2<T> &a) {
418     boost::function_requires<FragmentConcept<T> >();
419     return OptRect(bounds_fast(a[X]), bounds_fast(a[Y]));
421 template <typename T>
422 OptRect bounds_exact(const D2<T> &a) {
423     boost::function_requires<FragmentConcept<T> >();
424     return OptRect(bounds_exact(a[X]), bounds_exact(a[Y]));
426 template <typename T>
427 OptRect bounds_local(const D2<T> &a, const OptInterval &t) {
428     boost::function_requires<FragmentConcept<T> >();
429     return OptRect(bounds_local(a[X], t), bounds_local(a[Y], t));
431 };
433 /*
434   Local Variables:
435   mode:c++
436   c-file-style:"stroustrup"
437   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
438   indent-tabs-mode:nil
439   fill-column:99
440   End:
441 */
442 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
443 #endif