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