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]));
119 }
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));
125 }
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];
133 }
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];
139 }
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]);
147 }
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;
159 }
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;
169 }
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;
178 }
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;
187 }
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;
198 }
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;
208 }
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;
218 }
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;
227 }
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;
236 }
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;
255 }
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;
266 }
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;
279 }
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;
288 }
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;
296 }
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;
304 }
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;
316 }
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];
325 }
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]);
334 }
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;
344 }
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;
353 }
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;
362 }
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;
372 }
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;
382 }
385 template<typename T>
386 D2<T> derivative(D2<T> const & a) {
387 return D2<T>(derivative(a[X]), derivative(a[Y]));
388 }
389 template<typename T>
390 D2<T> integral(D2<T> const & a) {
391 return D2<T>(integral(a[X]), integral(a[Y]));
392 }
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]));
406 }
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]));
411 }
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));
416 }
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