Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[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 /** @brief Calculates the 'dot product' or 'inner product' of \c a and \c b
325  * @return \f$a \bullet b = a_X b_X + a_Y b_Y\f$.
326  * @relates D2 */
327 template <typename T>
328 inline T
329 dot(D2<T> const & a, Point const & b) {
330     boost::function_requires<AddableConcept<T> >();
331     boost::function_requires<ScalableConcept<T> >();
333     T r;
334     for(unsigned i = 0; i < 2; i++) {
335         r += a[i] * b[i];
336     }
337     return r;
340 /** @brief Calculates the 'cross product' or 'outer product' of \c a and \c b
341  * @return \f$a \times b = a_Y b_X - a_X b_Y\f$.
342  * @relates D2 */
343 template <typename T>
344 inline T
345 cross(D2<T> const & a, D2<T> const & b) {
346     boost::function_requires<ScalableConcept<T> >();
347     boost::function_requires<MultiplicableConcept<T> >();
349     return a[1] * b[0] - a[0] * b[1];
353 //equivalent to cw/ccw, for use in situations where rotation direction doesn't matter.
354 template <typename T>
355 inline D2<T>
356 rot90(D2<T> const & a) {
357     boost::function_requires<ScalableConcept<T> >();
358     return D2<T>(-a[Y], a[X]);
361 //TODO: concepterize the following functions
362 template <typename T>
363 inline D2<T>
364 compose(D2<T> const & a, T const & b) {
365     D2<T> r;
366     for(unsigned i = 0; i < 2; i++)
367         r[i] = compose(a[i],b);
368     return r;
371 template <typename T>
372 inline D2<T>
373 compose_each(D2<T> const & a, D2<T> const & b) {
374     D2<T> r;
375     for(unsigned i = 0; i < 2; i++)
376         r[i] = compose(a[i],b[i]);
377     return r;
380 template <typename T>
381 inline D2<T>
382 compose_each(T const & a, D2<T> const & b) {
383     D2<T> r;
384     for(unsigned i = 0; i < 2; i++)
385         r[i] = compose(a,b[i]);
386     return r;
390 template<typename T>
391 inline Point
392 D2<T>::operator()(double t) const {
393     Point p;
394     for(unsigned i = 0; i < 2; i++)
395        p[i] = (*this)[i](t);
396     return p;
399 //TODO: we might want to have this take a Point as the parameter.
400 template<typename T>
401 inline Point
402 D2<T>::operator()(double x, double y) const {
403     Point p;
404     for(unsigned i = 0; i < 2; i++)
405        p[i] = (*this)[i](x, y);
406     return p;
410 template<typename T>
411 D2<T> derivative(D2<T> const & a) {
412     return D2<T>(derivative(a[X]), derivative(a[Y]));
414 template<typename T>
415 D2<T> integral(D2<T> const & a) {
416     return D2<T>(integral(a[X]), integral(a[Y]));
419 /** A function to print out the Point.  It just prints out the coords
420     on the given output stream */
421 template <typename T>
422 inline std::ostream &operator<< (std::ostream &out_file, const Geom::D2<T> &in_d2) {
423     out_file << "X: " << in_d2[X] << "  Y: " << in_d2[Y];
424     return out_file;
427 } //end namespace Geom
429 #include <2geom/rect.h>
430 #include <2geom/d2-sbasis.h>
432 namespace Geom{
434 //Some D2 Fragment implementation which requires rect:
435 template <typename T>
436 OptRect bounds_fast(const D2<T> &a) {
437     boost::function_requires<FragmentConcept<T> >();
438     return OptRect(bounds_fast(a[X]), bounds_fast(a[Y]));
440 template <typename T>
441 OptRect bounds_exact(const D2<T> &a) {
442     boost::function_requires<FragmentConcept<T> >();
443     return OptRect(bounds_exact(a[X]), bounds_exact(a[Y]));
445 template <typename T>
446 OptRect bounds_local(const D2<T> &a, const OptInterval &t) {
447     boost::function_requires<FragmentConcept<T> >();
448     return OptRect(bounds_local(a[X], t), bounds_local(a[Y], t));
450 };
452 /*
453   Local Variables:
454   mode:c++
455   c-file-style:"stroustrup"
456   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
457   indent-tabs-mode:nil
458   fill-column:99
459   End:
460 */
461 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
462 #endif