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