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