Release of synfigstudio 0.61.09 version. *****
[synfig.git] / ETL / tags / stable / ETL / _angle.h
1 #include <stdio.h>
2 /* ========================================================================
3 ** Extended Template and Library
4 ** Angle Abstraction Class Implementation
5 ** $Id$
6 **
7 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
8 ** Copyright (c) 2007 Chris Moore
9 **
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
14 **
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ** General Public License for more details.
19 **
20 ** === N O T E S ===========================================================
21 **
22 ** This is an internal header file, included by other ETL headers.
23 ** You should not attempt to use it directly.
24 **
25 ** ========================================================================= */
26
27 /* === S T A R T =========================================================== */
28
29 #ifndef __ETL_ANGLE_H
30 #define __ETL_ANGLE_H
31
32 /* === H E A D E R S ======================================================= */
33
34 #include <cmath>
35 #include <functional>
36
37 /* === M A C R O S ========================================================= */
38
39 #ifndef PI
40 # define PI (3.1415926535897932384626433832795029L)
41 # define HALF_PI (PI/2)
42 #endif
43
44 #define ANGLE_EPSILON (1.0e-6)
45
46 /* === T Y P E D E F S ===================================================== */
47
48 /* === C L A S S E S & S T R U C T S ======================================= */
49
50 _ETL_BEGIN_NAMESPACE
51
52 // ========================================================================
53 /*!     \class  angle   _angle.h        ETL/angle
54 **      \brief  Abstraction of the concept of an angle
55 **  \see angle::deg, angle::rad, angle::rot, angle::sin, angle::cos, angle::tan, fastangle
56 **      \writeme
57 */
58 class angle
59 {
60 public:
61         typedef float value_type;
62
63 protected:
64         typedef value_type unit;
65
66         unit v; //! Stored in radians; positive values indicate counter-clockwise.
67
68 public:
69
70         /*
71         ** Arithmetic Operators
72         */
73
74         const angle     &
75         operator+=(const angle &rhs)
76         { v+=rhs.v; return *this; }
77
78         const angle     &
79         operator-=(const angle &rhs)
80         { v-=rhs.v; return *this; }
81
82         const angle     &
83         operator*=(const unit &rhs)
84         { v*=rhs; return *this; }
85
86         const angle     &
87         operator/=(const unit &rhs)
88         { v/=rhs; return *this; }
89
90         //! Angle Addition Operator
91         angle
92         operator+(const angle &rhs)const
93         { return angle(*this)+=rhs; }
94
95         //! Angle Subtraction Operator
96         /*! \sa angle dist(const angle &) */
97         angle
98         operator-(const angle &rhs)const
99         { return angle(*this)-=rhs; }
100
101         //! Angle Scalar Multiplication Operator
102         /*! This operator will multiply the given
103                 angle by the given scalar value. */
104         angle
105         operator*(const unit &rhs)const
106         { return angle(*this)*=rhs; }
107
108         angle
109         operator/(const unit &rhs)const
110         { return angle(*this)/=rhs; }
111
112         //! Angle Negation
113         angle
114         operator-()const
115         {
116                 angle ret;
117                 ret.v=-v;
118                 return ret;
119         }
120
121 #ifdef ETL_NOT_USED
122         //! 180 degree rotation operator
123         /*! Returns the angle directly opposite of
124                 the given angle, and will yield a result
125                 between 0 and 2PI */
126         angle
127         operator~()const
128         {
129                 angle ret;
130                 ret.v = v+PI;
131                 return ret.mod();
132         }
133 #endif // ETL_NOT_USED
134
135 #ifdef ETL_WRAP_ANGLES
136         /*! Returns true if the shortest
137                 angle from the left-hand to the
138                 right-hand side is counter-clockwise */
139         bool
140         operator<(const angle &rhs)const
141         { return dist(rhs).v<(value_type)0.0; }
142
143         /*! Returns true if the shortest
144                 angle from the left-hand to the
145                 right-hand side is clockwise */
146         bool
147         operator>(const angle &rhs)const
148         { return dist(rhs).v>(value_type)0.0; }
149
150         /*! Returns true if the shortest
151                 angle from the left-hand to the
152                 right-hand side is counter-clockwise,
153                 or if the angles are refer to the same
154                 point on the unit circle. */
155         bool
156         operator<=(const angle &rhs)const
157         { return dist(rhs).v<=(value_type)0.0; }
158
159         /*! Returns true if the shortest
160                 angle from the left-hand to the
161                 right-hand side is clockwise,
162                 or if the angles are refer to the same
163                 point on the unit circle. */
164         bool
165         operator>=(const angle &rhs)const
166         { return dist(rhs).v>=(value_type)0.0; }
167
168         /*! Returns true if the angles
169                 are refer to the same point
170                 on the unit circle. */
171         bool
172         operator==(const angle &rhs)const
173         { return std::abs(dist(rhs).v)<ANGLE_EPSILON; }
174
175         /*! Returns false if the angles
176                 are refer to the same point
177                 on the unit circle. */
178         bool
179         operator!=(const angle &rhs)const
180         { return std::abs(dist(rhs).v)>ANGLE_EPSILON; }
181 #else // ETL_WRAP_ANGLES
182         /*! Returns true if the left-hand
183                 side is less than the
184                 right-hand side */
185         bool
186         operator<(const angle &rhs)const
187         { return v < rhs.v; }
188
189         /*! Returns true if the left-hand
190                 side is greater than the
191                 right-hand side */
192         bool
193         operator>(const angle &rhs)const
194         { return v > rhs.v; }
195
196         /*! Returns true if the left-hand
197                 side is less or equal to the
198                 right-hand side */
199         bool
200         operator<=(const angle &rhs)const
201         { return v <= rhs.v; }
202
203         /*! Returns true if the left-hand
204                 side is greater than or equal
205                 to the right-hand side */
206         bool
207         operator>=(const angle &rhs)const
208         { return v >= rhs.v; }
209
210         /*! Returns true if the angles
211                 are the same, or close */
212         bool
213         operator==(const angle &rhs)const
214         { return std::abs(v - rhs.v)<ANGLE_EPSILON; }
215
216         /*! Returns false if the angles
217                 are different */
218         bool
219         operator!=(const angle &rhs)const
220                 { return std::abs(v - rhs.v)>ANGLE_EPSILON; }
221 #endif // ETL_WRAP_ANGLES
222
223         //! Absolute Angle Function
224         /*! This function will return the
225                 absolute value of the angle. */
226         angle
227         abs()const
228         {
229                 angle ret;
230                 ret.v=std::abs(v);
231                 return ret;
232         }
233
234 #ifdef ETL_WRAP_ANGLES
235         //! Angle Difference Function
236         /*! This function will return the
237                 shortest physical distance between
238                 two angles, from -PI/2 to PI/2
239                 \sa angle operator-(const angle &) */
240         angle
241         dist(const angle &rhs)const
242         {
243                 angle ret;
244                 ret.v=v-rhs.v;
245                 ret.v-=rot_floor(ret.v+PI);
246                 return ret;
247         }
248
249         //! Rotation Modulus
250         /*! This function will return the
251                 value of the angle between 0 and 2PI */
252         angle
253         mod()const
254         {
255                 angle ret(*this);
256                 ret.v-=rot_floor(ret.v);
257                 return ret;
258         }
259 #else // ETL_WRAP_ANGLES
260         //! Angle Difference Function
261         /*! This function will return the
262                 difference between
263                 two angles, just like
264                 \sa angle operator-(const angle &) */
265         angle
266         dist(const angle &rhs)const
267         { return angle(*this)-=rhs; }
268
269         //! Rotation Modulus
270         /*! This function will return the
271                 value of the angle */
272         angle
273         mod()const
274         {
275                 angle ret(*this);
276                 return ret;
277         }
278 #endif // ETL_WRAP_ANGLES
279
280         //! Zero Rotation (0 degrees)
281         static angle
282         zero()
283         {
284                 angle ret;
285                 ret.v=0;
286                 return ret;
287         }
288
289         //! One Complete Rotation (360 degrees)
290         static angle
291         one()
292         {
293                 angle ret;
294                 ret.v=PI*2;
295                 return ret;
296         }
297
298         //! One Half Rotation (180 degrees)
299         static angle
300         half()
301         {
302                 angle ret;
303                 ret.v=PI;
304                 return ret;
305         }
306
307         bool operator!()const { return std::abs(mod().v) < ANGLE_EPSILON; }
308
309 private:
310
311 #ifdef ETL_WRAP_ANGLES
312         static value_type rot_floor(value_type x)
313         { return static_cast<value_type>(std::floor(x/(PI*2))*PI*2); }
314 #endif // ETL_WRAP_ANGLES
315
316 public:
317         /*
318         ** Conversion Classes
319         */
320
321         class rad;
322         class deg;
323         class rot;
324
325         /*
326         ** Trigonometric Classes
327         */
328
329         class sin;
330         class cos;
331         class tan;
332
333         /*
334         ** Friend classes
335         */
336
337         friend class rad;
338         friend class deg;
339         friend class rot;
340         friend class sin;
341         friend class cos;
342         friend class tan;
343
344         /*
345         ** Deprecated
346         */
347
348 #ifndef ETL_NO_DEPRECATED
349         typedef rad             radians;
350         typedef deg             degrees;
351         typedef rot             rotations;
352 #endif
353 }; // END of class angle
354
355 // ========================================================================
356 /*!     \class  angle::rad      _angle.h        ETL/angle
357 **      \brief  Angle representation in radians
358 **      \see angle
359 **      \writeme
360 */
361 class angle::rad : public angle
362 {
363 public:
364         explicit rad(const value_type &x) { v=x; }
365         rad(const angle &a):angle(a) { }
366         rad     mod()const { return angle::mod(); }
367         rad dist(const angle &rhs)const { return angle::dist(rhs); }
368         value_type get()const { return v; }
369 #ifndef ETL_NO_DEPRECATED
370         // operator value_type()const ETL_DEPRECATED_FUNCTION;
371 #endif
372 }; // END of class angle::radians
373 // inline angle::rad::operator angle::value_type()const { return get(); }
374
375 // ========================================================================
376 /*!     \class  angle::deg      _angle.h        ETL/angle
377 **      \brief  Angle representation in degrees
378 **      \see angle
379 **      \writeme
380 */
381 class angle::deg : public angle
382 {
383 public:
384         explicit deg(const value_type &x) { v=x*((PI*2)/360); }
385         deg(const angle &a):angle(a) { }
386         deg     mod()const { return angle::mod(); }
387         deg dist(const angle &rhs)const { return angle::dist(rhs); }
388         value_type get()const { return v*360/(PI*2); }
389 #ifndef ETL_NO_DEPRECATED
390         // operator value_type()const ETL_DEPRECATED_FUNCTION;
391 #endif
392 }; // END of class angle::degrees
393 // inline angle::deg::operator angle::value_type()const { return get(); }
394
395 // ========================================================================
396 /*!     \class  angle::rot      _angle.h        ETL/angle
397 **      \brief  Angle representation in rotations
398 **      \see angle
399 **      \writeme
400 */
401 class angle::rot : public angle
402 {
403 public:
404         explicit rot(const value_type &x) { v=x*(PI*2); }
405         rot(const angle &a):angle(a) { }
406         rot mod()const { return angle::mod(); }
407         rot dist(const angle &rhs)const { return angle::dist(rhs); }
408         value_type get()const { return v/(PI*2); }
409 #ifndef ETL_NO_DEPRECATED
410         // operator value_type()const ETL_DEPRECATED_FUNCTION;
411 #endif
412 }; // END of class angle::rotations
413 // inline angle::rot::operator angle::value_type()const { return get(); }
414
415 // ========================================================================
416 /*!     \class  angle::sin      _angle.h        ETL/angle
417 **      \brief  Angle representation as a sine function
418 **      \see angle
419 **      \writeme
420 */
421 class angle::sin : public angle
422 {
423 public:
424         explicit sin(const value_type &x) { v=static_cast<value_type>(std::asin(x)); }
425         sin(const angle &a):angle(a) { }
426         sin     mod()const { return angle::mod(); }
427         sin dist(const angle &rhs)const { return angle::dist(rhs); }
428         value_type get()const { return static_cast<value_type>(std::sin(v)); }
429 #ifndef ETL_NO_DEPRECATED
430         // operator value_type()const ETL_DEPRECATED_FUNCTION;
431 #endif
432 }; // END of class angle::sin
433 // inline angle::sin::operator angle::value_type()const { return get(); }
434
435 // ========================================================================
436 /*!     \class  angle::cos      _angle.h        ETL/angle
437 **      \brief  Angle representation as a cosine function
438 **      \see angle
439 **      \writeme
440 */
441 class angle::cos : public angle
442 {
443 public:
444         explicit cos(const value_type &x)       { v=(value_type)(std::acos(x)); }
445         cos(const angle &a):angle(a) { }
446         cos     mod()const { return angle::mod(); }
447         cos dist(const angle &rhs)const { return angle::dist(rhs); }
448         value_type get()const { return (value_type)std::cos(v); }
449 #ifndef ETL_NO_DEPRECATED
450         // operator value_type()const ETL_DEPRECATED_FUNCTION;
451 #endif
452 }; // END of class angle::cos
453 // inline angle::cos::operator angle::value_type()const { return get(); }
454
455 // ========================================================================
456 /*!     \class  angle::tan      _angle.h        ETL/angle
457 **      \brief  Angle representation as a tangent function
458 **      \see angle
459 **      \writeme
460 */
461 class angle::tan : public angle
462 {
463 public:
464         explicit tan(const value_type &x)       { v=(value_type)(std::atan(x)); }
465         tan(const value_type &y,const value_type &x) { v=(value_type)(std::atan2(y,x)); }
466         tan(const angle &a):angle(a) { }
467         tan     mod()const { return angle::mod(); }
468         tan dist(const angle &rhs)const { return angle::dist(rhs); }
469         value_type get()const { return (value_type)std::tan(v); }
470 #ifndef ETL_NO_DEPRECATED
471         // operator value_type()const ETL_DEPRECATED_FUNCTION;
472 #endif
473 }; // END of class angle::tan
474 // inline angle::tan::operator angle::value_type()const { return get(); }
475
476 _ETL_END_NAMESPACE
477
478 //#include <iostream>
479
480 template <typename T>
481 struct affine_combo<etl::angle, T>
482 {
483         typedef T time_type;
484
485         //affine_combo() { std::cerr<<"affine_combo<etl::angle,float>: I was created!"<<std::endl; }
486         //~affine_combo() { std::cerr<<"affine_combo<etl::angle,float>: I was DELETED!"<<std::endl; }
487
488         etl::angle operator()(const etl::angle &a,const etl::angle &b,const time_type &t)const
489         {
490                 return b.dist(a)*(float)t+a;
491         }
492
493         etl::angle reverse(const etl::angle &x, const etl::angle &b, const time_type &t)const
494         {
495                 return x.dist(b*(float)t)*(float)(time_type(1)/(time_type(1)-t));
496         }
497 };
498
499 template <>
500 struct distance_func<etl::angle> : public std::binary_function<etl::angle, etl::angle, etl::angle>
501 {
502         etl::angle operator()(const etl::angle &a,const etl::angle &b)const
503         {
504                 etl::angle delta=b.dist(a);
505                 //if(delta<etl::angle::zero())
506                 //      return delta+etl::angle::one();
507                 return delta;
508         }
509
510         etl::angle cook(const etl::angle &x)const { return x; }
511         etl::angle uncook(const etl::angle &x)const { return x; }
512 };
513
514 /* === E N D =============================================================== */
515
516 #endif