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