Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / synfig_0_61_06 / src / synfig / vector.h
1 /* === S Y N F I G ========================================================= */
2 /*!     \file vector.h
3 **      \brief Various discreet type definitions
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
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 **      \endlegal
20 */
21 /* ========================================================================= */
22
23 /* === S T A R T =========================================================== */
24
25 #ifndef __SYNFIG_VECTOR_H
26 #define __SYNFIG_VECTOR_H
27
28 /* === H E A D E R S ======================================================= */
29
30 #include "real.h"
31 #include <math.h>
32
33 /* === M A C R O S ========================================================= */
34
35
36 #ifdef WIN32
37 #include <float.h>
38 #ifndef isnan
39 extern "C" { int _isnan(double x); }
40 #define isnan _isnan
41 #endif
42 #endif
43
44 // For some reason isnan() isn't working on macosx any more.
45 // This is a quick fix.
46 #if defined(__APPLE__) && !defined(SYNFIG_ISNAN_FIX)
47 #ifdef isnan
48 #undef isnan
49 #endif
50 inline bool isnan(double x) { return x != x; }
51 inline bool isnan(float x) { return x != x; }
52 #define SYNFIG_ISNAN_FIX 1
53 #endif
54
55
56 /* === T Y P E D E F S ===================================================== */
57
58 /* === C L A S S E S & S T R U C T S ======================================= */
59
60 namespace synfig {
61
62 /*!     \class Vector
63 **      \todo writeme
64 */
65 class Vector
66 {
67 public:
68         typedef Real value_type;
69
70 private:
71         value_type _x, _y;
72
73 public:
74         Vector(): _x(0.0), _y(0.0) { };
75         Vector(const value_type &x, const value_type &y):_x(x),_y(y) { };
76
77         bool is_valid()const { return !(isnan(_x) || isnan(_y)); }
78
79         value_type &
80         operator[](const int& i)
81         { return (&_x)[i] ; }
82
83         const value_type &
84         operator[](const int& i) const
85         { return (&_x)[i] ; }
86
87         const Vector &
88         operator+=(const Vector &rhs)
89         {
90                 _x+=rhs._x;
91                 _y+=rhs._y;
92                 return *this;
93         }
94
95         const Vector &
96         operator-=(const Vector &rhs)
97         {
98                 _x-=rhs._x;
99                 _y-=rhs._y;
100                 return *this;
101         }
102
103         const Vector &
104         operator*=(const value_type &rhs)
105         {
106                 _x*=rhs;
107                 _y*=rhs;
108                 return *this;
109         }
110
111         const Vector &
112         operator/=(const value_type &rhs)
113         {
114                 value_type tmp=1.0/rhs;
115                 _x*=tmp;
116                 _y*=tmp;
117                 return *this;
118         }
119
120         Vector
121         operator+(const Vector &rhs)const
122                 { return Vector(*this)+=rhs; }
123
124         Vector
125         operator-(const Vector &rhs)const
126                 { return Vector(*this)-=rhs; }
127
128         Vector
129         operator*(const value_type &rhs)const
130                 { return Vector(*this)*=rhs; }
131
132         Vector
133         operator/(const value_type &rhs)const
134                 { return Vector(*this)/=rhs; }
135
136         Vector
137         operator-()const
138                 { return Vector(-_x,-_y); }
139
140         value_type
141         operator*(const Vector &rhs)const
142                 { return _x*rhs._x+_y*rhs._y; }
143
144         bool
145         operator==(const Vector &rhs)const
146                 { return _x==rhs._x && _y==rhs._y; }
147
148         bool
149         operator!=(const Vector &rhs)const
150                 { return _y!=rhs._y || _x!=rhs._x; }
151
152         //! Returns the squared magnitude of the vector
153         value_type mag_squared()const
154                 { return _x*_x+_y*_y; }
155
156         //! Returns the magnitude of the vector
157         value_type mag()const
158                 { return sqrt(mag_squared()); }
159
160         //! Returns the reciprocal of the magnitude of the vector
161         value_type inv_mag()const
162                 { return 1.0/sqrt(mag_squared()); }
163
164         //! Returns a normalized version of the vector
165         Vector norm()const
166                 { return (*this)*inv_mag(); }
167
168         //! Returns a perpendicular version of the vector
169         Vector perp()const
170                 { return Vector(_y,-_x); }
171
172         bool is_equal_to(const Vector& rhs)const
173         {
174                 static const value_type epsilon(0.0000000000001);
175 //              return (_x>rhs._x)?_x-rhs._x<=epsilon:rhs._x-_x<=epsilon && (_y>rhs._y)?_y-rhs._y<=epsilon:rhs._y-_y<=epsilon;
176                 return (*this-rhs).mag_squared()<=epsilon;
177         }
178
179         static const Vector zero() { return Vector(0,0); }
180 };
181
182 /*!     \typedef Point
183 **      \todo writeme
184 */
185 typedef Vector Point;
186
187
188
189 }; // END of namespace synfig
190
191 namespace std {
192
193 inline synfig::Vector::value_type
194 abs(const synfig::Vector &rhs)
195         { return rhs.mag(); }
196
197 }; // END of namespace std
198
199 #include <ETL/bezier>
200
201 _ETL_BEGIN_NAMESPACE
202
203 template <>
204 class bezier_base<synfig::Vector,float> : public std::unary_function<float,synfig::Vector>
205 {
206 public:
207         typedef synfig::Vector value_type;
208         typedef float time_type;
209 private:
210
211         bezier_base<synfig::Vector::value_type,time_type> bezier_x,bezier_y;
212
213         value_type a,b,c,d;
214
215 protected:
216         affine_combo<value_type,time_type> affine_func;
217
218 public:
219         bezier_base() { }
220         bezier_base(
221                 const value_type &a, const value_type &b, const value_type &c, const value_type &d,
222                 const time_type &r=0.0, const time_type &s=1.0):
223                 a(a),b(b),c(c),d(d) { set_rs(r,s); sync(); }
224
225         void sync()
226         {
227                 bezier_x[0]=a[0],bezier_y[0]=a[1];
228                 bezier_x[1]=b[0],bezier_y[1]=b[1];
229                 bezier_x[2]=c[0],bezier_y[2]=c[1];
230                 bezier_x[3]=d[0],bezier_y[3]=d[1];
231                 bezier_x.sync();
232                 bezier_y.sync();
233         }
234
235         value_type
236         operator()(time_type t)const
237         {
238                 return synfig::Vector(bezier_x(t),bezier_y(t));
239         }
240
241         void evaluate(time_type t, value_type &f, value_type &df) const
242         {
243                 t=(t-get_r())/get_dt();
244
245                 const value_type p1 = affine_func(
246                                                         affine_func(a,b,t),
247                                                         affine_func(b,c,t)
248                                                         ,t);
249                 const value_type p2 = affine_func(
250                                                         affine_func(b,c,t),
251                                                         affine_func(c,d,t)
252                                                 ,t);
253
254                 f = affine_func(p1,p2,t);
255                 df = (p2-p1)*3;
256         }
257
258         void set_rs(time_type new_r, time_type new_s) { bezier_x.set_rs(new_r,new_s); bezier_y.set_rs(new_r,new_s); }
259         void set_r(time_type new_r) { bezier_x.set_r(new_r); bezier_y.set_r(new_r); }
260         void set_s(time_type new_s) { bezier_x.set_s(new_s); bezier_y.set_s(new_s); }
261         const time_type &get_r()const { return bezier_x.get_r(); }
262         const time_type &get_s()const { return bezier_x.get_s(); }
263         time_type get_dt()const { return bezier_x.get_dt(); }
264
265         value_type &
266         operator[](int i)
267         { return (&a)[i]; }
268
269         const value_type &
270         operator[](int i) const
271         { return (&a)[i]; }
272
273         //! Bezier curve intersection function
274         time_type intersect(const bezier_base<value_type,time_type> &x, time_type near=0.0)const
275         {
276                 return 0;
277         }
278 };
279
280 _ETL_END_NAMESPACE
281
282
283 /* === E N D =============================================================== */
284
285 #endif