78e91baba524b8645472becf07647d9032466b22
[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         //! 180 degree rotation operator
122         /*! Returns the angle directly opposite of
123                 the given angle, and will yield a result
124                 between 0 and 2PI */
125         angle
126         operator~()const
127         {
128                 angle ret;
129                 ret.v = v+PI;
130                 return ret.mod();
131         }
132
133         /*! Returns true if the shortest
134                 angle from the left-hand to the
135                 right-hand side is counter-clockwise */
136         bool
137         operator<(const angle &rhs)const
138         { return dist(rhs).v<(value_type)0.0; }
139
140         /*! Returns true if the shortest
141                 angle from the left-hand to the
142                 right-hand side is clockwise */
143         bool
144         operator>(const angle &rhs)const
145         { return dist(rhs).v>(value_type)0.0; }
146
147         /*! Returns true if the shortest
148                 angle from the left-hand to the
149                 right-hand side is counter-clockwise,
150                 or if the angles are refer to the same
151                 point on the unit circle. */
152         bool
153         operator<=(const angle &rhs)const
154         { return dist(rhs).v<=(value_type)0.0; }
155
156         /*! Returns true if the shortest
157                 angle from the left-hand to the
158                 right-hand side is clockwise,
159                 or if the angles are refer to the same
160                 point on the unit circle. */
161         bool
162         operator>=(const angle &rhs)const
163         { return dist(rhs).v>=(value_type)0.0; }
164
165         /*! Returns true if the angles
166                 are refer to the same point
167                 on the unit circle. */
168         bool
169         operator==(const angle &rhs)const
170         { return std::abs(dist(rhs).v)<ANGLE_EPSILON; }
171
172         /*! Returns false if the angles
173                 are refer to the same point
174                 on the unit circle. */
175         bool
176         operator!=(const angle &rhs)const
177         { return std::abs(dist(rhs).v)>ANGLE_EPSILON; }
178
179         //! Absolute Angle Function
180         /*! This function will return the
181                 absolute value of the angle. */
182         angle
183         abs()const
184         {
185                 angle ret;
186                 ret.v=std::abs(v);
187                 return ret;
188         }
189
190         //! Angle Difference Function
191         /*! This function will return the
192                 shortest physical distance between
193                 two angles, from -PI/2 to PI/2
194                 \sa angle operator-(const angle &) */
195         angle
196         dist(const angle &rhs)const
197         {
198                 angle ret;
199                 ret.v=v-rhs.v;
200                 ret.v-=rot_floor(ret.v+PI);
201                 return ret;
202         }
203
204         //! Rotation Modulus
205         /*! This function will return the
206                 value of the angle between 0 and 2PI */
207         angle
208         mod()const
209         {
210                 angle ret(*this);
211                 ret.v-=rot_floor(ret.v);
212                 return ret;
213         }
214
215         //! Zero Rotation (0 degrees)
216         static angle
217         zero()
218         {
219                 angle ret;
220                 ret.v=0;
221                 return ret;
222         }
223
224         //! One Complete Rotation (360 degrees)
225         static angle
226         one()
227         {
228                 angle ret;
229                 ret.v=PI*2;
230                 return ret;
231         }
232
233         //! One Half Rotation (180 degrees)
234         static angle
235         half()
236         {
237                 angle ret;
238                 ret.v=PI;
239                 return ret;
240         }
241
242         bool operator!()const { return std::abs(mod().v) < ANGLE_EPSILON; }
243
244 private:
245
246         static value_type rot_floor(value_type x)
247         { return static_cast<value_type>(std::floor(x/(PI*2))*PI*2); }
248
249 public:
250         /*
251         ** Conversion Classes
252         */
253
254         class rad;
255         class deg;
256         class rot;
257
258         /*
259         ** Trigonometric Classes
260         */
261
262         class sin;
263         class cos;
264         class tan;
265
266         /*
267         ** Friend classes
268         */
269
270         friend class rad;
271         friend class deg;
272         friend class rot;
273         friend class sin;
274         friend class cos;
275         friend class tan;
276
277         /*
278         ** Deprecated
279         */
280
281 #ifndef ETL_NO_DEPRECATED
282         typedef rad             radians;
283         typedef deg             degrees;
284         typedef rot             rotations;
285 #endif
286 }; // END of class angle
287
288 // ========================================================================
289 /*!     \class  angle::rad      _angle.h        ETL/angle
290 **      \brief  Angle representation in radians
291 **      \see angle
292 **      \writeme
293 */
294 class angle::rad : public angle
295 {
296 public:
297         explicit rad(const value_type &x) { v=x; }
298         rad(const angle &a):angle(a) { }
299         rad     mod()const { return angle::mod(); }
300         rad dist(const angle &rhs)const { return angle::dist(rhs); }
301         value_type get()const { return v; }
302 #ifndef ETL_NO_DEPRECATED
303         // operator value_type()const ETL_DEPRECATED_FUNCTION;
304 #endif
305 }; // END of class angle::radians
306 // inline angle::rad::operator angle::value_type()const { return get(); }
307
308 // ========================================================================
309 /*!     \class  angle::deg      _angle.h        ETL/angle
310 **      \brief  Angle representation in degrees
311 **      \see angle
312 **      \writeme
313 */
314 class angle::deg : public angle
315 {
316 public:
317         explicit deg(const value_type &x) { v=x*((PI*2)/360); }
318         deg(const angle &a):angle(a) { }
319         deg     mod()const { return angle::mod(); }
320         deg dist(const angle &rhs)const { return angle::dist(rhs); }
321         value_type get()const { return v*360/(PI*2); }
322 #ifndef ETL_NO_DEPRECATED
323         // operator value_type()const ETL_DEPRECATED_FUNCTION;
324 #endif
325 }; // END of class angle::degrees
326 // inline angle::deg::operator angle::value_type()const { return get(); }
327
328 // ========================================================================
329 /*!     \class  angle::rot      _angle.h        ETL/angle
330 **      \brief  Angle representation in rotations
331 **      \see angle
332 **      \writeme
333 */
334 class angle::rot : public angle
335 {
336 public:
337         explicit rot(const value_type &x) { v=x*(PI*2); }
338         rot(const angle &a):angle(a) { }
339         rot mod()const { return angle::mod(); }
340         rot dist(const angle &rhs)const { return angle::dist(rhs); }
341         value_type get()const { return v/(PI*2); }
342 #ifndef ETL_NO_DEPRECATED
343         // operator value_type()const ETL_DEPRECATED_FUNCTION;
344 #endif
345 }; // END of class angle::rotations
346 // inline angle::rot::operator angle::value_type()const { return get(); }
347
348 // ========================================================================
349 /*!     \class  angle::sin      _angle.h        ETL/angle
350 **      \brief  Angle representation as a sine function
351 **      \see angle
352 **      \writeme
353 */
354 class angle::sin : public angle
355 {
356 public:
357         explicit sin(const value_type &x) { v=static_cast<value_type>(std::asin(x)); }
358         sin(const angle &a):angle(a) { }
359         sin     mod()const { return angle::mod(); }
360         sin dist(const angle &rhs)const { return angle::dist(rhs); }
361         value_type get()const { return static_cast<value_type>(std::sin(v)); }
362 #ifndef ETL_NO_DEPRECATED
363         // operator value_type()const ETL_DEPRECATED_FUNCTION;
364 #endif
365 }; // END of class angle::sin
366 // inline angle::sin::operator angle::value_type()const { return get(); }
367
368 // ========================================================================
369 /*!     \class  angle::cos      _angle.h        ETL/angle
370 **      \brief  Angle representation as a cosine function
371 **      \see angle
372 **      \writeme
373 */
374 class angle::cos : public angle
375 {
376 public:
377         explicit cos(const value_type &x)       { v=(value_type)(std::acos(x)); }
378         cos(const angle &a):angle(a) { }
379         cos     mod()const { return angle::mod(); }
380         cos dist(const angle &rhs)const { return angle::dist(rhs); }
381         value_type get()const { return (value_type)std::cos(v); }
382 #ifndef ETL_NO_DEPRECATED
383         // operator value_type()const ETL_DEPRECATED_FUNCTION;
384 #endif
385 }; // END of class angle::cos
386 // inline angle::cos::operator angle::value_type()const { return get(); }
387
388 // ========================================================================
389 /*!     \class  angle::tan      _angle.h        ETL/angle
390 **      \brief  Angle representation as a tangent function
391 **      \see angle
392 **      \writeme
393 */
394 class angle::tan : public angle
395 {
396 public:
397         explicit tan(const value_type &x)       { v=(value_type)(std::atan(x)); }
398         tan(const value_type &y,const value_type &x) { v=(value_type)(std::atan2(y,x)); }
399         tan(const angle &a):angle(a) { }
400         tan     mod()const { return angle::mod(); }
401         tan dist(const angle &rhs)const { return angle::dist(rhs); }
402         value_type get()const { return (value_type)std::tan(v); }
403 #ifndef ETL_NO_DEPRECATED
404         // operator value_type()const ETL_DEPRECATED_FUNCTION;
405 #endif
406 }; // END of class angle::tan
407 // inline angle::tan::operator angle::value_type()const { return get(); }
408
409 _ETL_END_NAMESPACE
410
411 //#include <iostream>
412
413 template <typename T>
414 struct affine_combo<etl::angle, T>
415 {
416         typedef T time_type;
417
418         //affine_combo() { std::cerr<<"affine_combo<etl::angle,float>: I was created!"<<std::endl; }
419         //~affine_combo() { std::cerr<<"affine_combo<etl::angle,float>: I was DELETED!"<<std::endl; }
420
421         etl::angle operator()(const etl::angle &a,const etl::angle &b,const time_type &t)const
422         {
423                 return b.dist(a)*(float)t+a;
424         }
425
426         etl::angle reverse(const etl::angle &x, const etl::angle &b, const time_type &t)const
427         {
428                 return x.dist(b*(float)t)*(float)(time_type(1)/(time_type(1)-t));
429         }
430 };
431
432 template <>
433 struct distance_func<etl::angle> : public std::binary_function<etl::angle, etl::angle, etl::angle>
434 {
435         etl::angle operator()(const etl::angle &a,const etl::angle &b)const
436         {
437                 etl::angle delta=b.dist(a);
438                 //if(delta<etl::angle::zero())
439                 //      return delta+etl::angle::one();
440                 return delta;
441         }
442
443         etl::angle cook(const etl::angle &x)const { return x; }
444         etl::angle uncook(const etl::angle &x)const { return x; }
445 };
446
447 /* === E N D =============================================================== */
448
449 #endif