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