diff options
Diffstat (limited to 'libraries/irrlicht-1.8.1/include/vector2d.h')
-rw-r--r-- | libraries/irrlicht-1.8.1/include/vector2d.h | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/include/vector2d.h b/libraries/irrlicht-1.8.1/include/vector2d.h new file mode 100644 index 0000000..360da8f --- /dev/null +++ b/libraries/irrlicht-1.8.1/include/vector2d.h | |||
@@ -0,0 +1,342 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #ifndef __IRR_POINT_2D_H_INCLUDED__ | ||
6 | #define __IRR_POINT_2D_H_INCLUDED__ | ||
7 | |||
8 | #include "irrMath.h" | ||
9 | #include "dimension2d.h" | ||
10 | |||
11 | namespace irr | ||
12 | { | ||
13 | namespace core | ||
14 | { | ||
15 | |||
16 | |||
17 | //! 2d vector template class with lots of operators and methods. | ||
18 | /** As of Irrlicht 1.6, this class supercedes position2d, which should | ||
19 | be considered deprecated. */ | ||
20 | template <class T> | ||
21 | class vector2d | ||
22 | { | ||
23 | public: | ||
24 | //! Default constructor (null vector) | ||
25 | vector2d() : X(0), Y(0) {} | ||
26 | //! Constructor with two different values | ||
27 | vector2d(T nx, T ny) : X(nx), Y(ny) {} | ||
28 | //! Constructor with the same value for both members | ||
29 | explicit vector2d(T n) : X(n), Y(n) {} | ||
30 | //! Copy constructor | ||
31 | vector2d(const vector2d<T>& other) : X(other.X), Y(other.Y) {} | ||
32 | |||
33 | vector2d(const dimension2d<T>& other) : X(other.Width), Y(other.Height) {} | ||
34 | |||
35 | // operators | ||
36 | |||
37 | vector2d<T> operator-() const { return vector2d<T>(-X, -Y); } | ||
38 | |||
39 | vector2d<T>& operator=(const vector2d<T>& other) { X = other.X; Y = other.Y; return *this; } | ||
40 | |||
41 | vector2d<T>& operator=(const dimension2d<T>& other) { X = other.Width; Y = other.Height; return *this; } | ||
42 | |||
43 | vector2d<T> operator+(const vector2d<T>& other) const { return vector2d<T>(X + other.X, Y + other.Y); } | ||
44 | vector2d<T> operator+(const dimension2d<T>& other) const { return vector2d<T>(X + other.Width, Y + other.Height); } | ||
45 | vector2d<T>& operator+=(const vector2d<T>& other) { X+=other.X; Y+=other.Y; return *this; } | ||
46 | vector2d<T> operator+(const T v) const { return vector2d<T>(X + v, Y + v); } | ||
47 | vector2d<T>& operator+=(const T v) { X+=v; Y+=v; return *this; } | ||
48 | vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Height; return *this; } | ||
49 | |||
50 | vector2d<T> operator-(const vector2d<T>& other) const { return vector2d<T>(X - other.X, Y - other.Y); } | ||
51 | vector2d<T> operator-(const dimension2d<T>& other) const { return vector2d<T>(X - other.Width, Y - other.Height); } | ||
52 | vector2d<T>& operator-=(const vector2d<T>& other) { X-=other.X; Y-=other.Y; return *this; } | ||
53 | vector2d<T> operator-(const T v) const { return vector2d<T>(X - v, Y - v); } | ||
54 | vector2d<T>& operator-=(const T v) { X-=v; Y-=v; return *this; } | ||
55 | vector2d<T>& operator-=(const dimension2d<T>& other) { X -= other.Width; Y -= other.Height; return *this; } | ||
56 | |||
57 | vector2d<T> operator*(const vector2d<T>& other) const { return vector2d<T>(X * other.X, Y * other.Y); } | ||
58 | vector2d<T>& operator*=(const vector2d<T>& other) { X*=other.X; Y*=other.Y; return *this; } | ||
59 | vector2d<T> operator*(const T v) const { return vector2d<T>(X * v, Y * v); } | ||
60 | vector2d<T>& operator*=(const T v) { X*=v; Y*=v; return *this; } | ||
61 | |||
62 | vector2d<T> operator/(const vector2d<T>& other) const { return vector2d<T>(X / other.X, Y / other.Y); } | ||
63 | vector2d<T>& operator/=(const vector2d<T>& other) { X/=other.X; Y/=other.Y; return *this; } | ||
64 | vector2d<T> operator/(const T v) const { return vector2d<T>(X / v, Y / v); } | ||
65 | vector2d<T>& operator/=(const T v) { X/=v; Y/=v; return *this; } | ||
66 | |||
67 | //! sort in order X, Y. Equality with rounding tolerance. | ||
68 | bool operator<=(const vector2d<T>&other) const | ||
69 | { | ||
70 | return (X<other.X || core::equals(X, other.X)) || | ||
71 | (core::equals(X, other.X) && (Y<other.Y || core::equals(Y, other.Y))); | ||
72 | } | ||
73 | |||
74 | //! sort in order X, Y. Equality with rounding tolerance. | ||
75 | bool operator>=(const vector2d<T>&other) const | ||
76 | { | ||
77 | return (X>other.X || core::equals(X, other.X)) || | ||
78 | (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))); | ||
79 | } | ||
80 | |||
81 | //! sort in order X, Y. Difference must be above rounding tolerance. | ||
82 | bool operator<(const vector2d<T>&other) const | ||
83 | { | ||
84 | return (X<other.X && !core::equals(X, other.X)) || | ||
85 | (core::equals(X, other.X) && Y<other.Y && !core::equals(Y, other.Y)); | ||
86 | } | ||
87 | |||
88 | //! sort in order X, Y. Difference must be above rounding tolerance. | ||
89 | bool operator>(const vector2d<T>&other) const | ||
90 | { | ||
91 | return (X>other.X && !core::equals(X, other.X)) || | ||
92 | (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)); | ||
93 | } | ||
94 | |||
95 | bool operator==(const vector2d<T>& other) const { return equals(other); } | ||
96 | bool operator!=(const vector2d<T>& other) const { return !equals(other); } | ||
97 | |||
98 | // functions | ||
99 | |||
100 | //! Checks if this vector equals the other one. | ||
101 | /** Takes floating point rounding errors into account. | ||
102 | \param other Vector to compare with. | ||
103 | \return True if the two vector are (almost) equal, else false. */ | ||
104 | bool equals(const vector2d<T>& other) const | ||
105 | { | ||
106 | return core::equals(X, other.X) && core::equals(Y, other.Y); | ||
107 | } | ||
108 | |||
109 | vector2d<T>& set(T nx, T ny) {X=nx; Y=ny; return *this; } | ||
110 | vector2d<T>& set(const vector2d<T>& p) { X=p.X; Y=p.Y; return *this; } | ||
111 | |||
112 | //! Gets the length of the vector. | ||
113 | /** \return The length of the vector. */ | ||
114 | T getLength() const { return core::squareroot( X*X + Y*Y ); } | ||
115 | |||
116 | //! Get the squared length of this vector | ||
117 | /** This is useful because it is much faster than getLength(). | ||
118 | \return The squared length of the vector. */ | ||
119 | T getLengthSQ() const { return X*X + Y*Y; } | ||
120 | |||
121 | //! Get the dot product of this vector with another. | ||
122 | /** \param other Other vector to take dot product with. | ||
123 | \return The dot product of the two vectors. */ | ||
124 | T dotProduct(const vector2d<T>& other) const | ||
125 | { | ||
126 | return X*other.X + Y*other.Y; | ||
127 | } | ||
128 | |||
129 | //! Gets distance from another point. | ||
130 | /** Here, the vector is interpreted as a point in 2-dimensional space. | ||
131 | \param other Other vector to measure from. | ||
132 | \return Distance from other point. */ | ||
133 | T getDistanceFrom(const vector2d<T>& other) const | ||
134 | { | ||
135 | return vector2d<T>(X - other.X, Y - other.Y).getLength(); | ||
136 | } | ||
137 | |||
138 | //! Returns squared distance from another point. | ||
139 | /** Here, the vector is interpreted as a point in 2-dimensional space. | ||
140 | \param other Other vector to measure from. | ||
141 | \return Squared distance from other point. */ | ||
142 | T getDistanceFromSQ(const vector2d<T>& other) const | ||
143 | { | ||
144 | return vector2d<T>(X - other.X, Y - other.Y).getLengthSQ(); | ||
145 | } | ||
146 | |||
147 | //! rotates the point anticlockwise around a center by an amount of degrees. | ||
148 | /** \param degrees Amount of degrees to rotate by, anticlockwise. | ||
149 | \param center Rotation center. | ||
150 | \return This vector after transformation. */ | ||
151 | vector2d<T>& rotateBy(f64 degrees, const vector2d<T>& center=vector2d<T>()) | ||
152 | { | ||
153 | degrees *= DEGTORAD64; | ||
154 | const f64 cs = cos(degrees); | ||
155 | const f64 sn = sin(degrees); | ||
156 | |||
157 | X -= center.X; | ||
158 | Y -= center.Y; | ||
159 | |||
160 | set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs)); | ||
161 | |||
162 | X += center.X; | ||
163 | Y += center.Y; | ||
164 | return *this; | ||
165 | } | ||
166 | |||
167 | //! Normalize the vector. | ||
168 | /** The null vector is left untouched. | ||
169 | \return Reference to this vector, after normalization. */ | ||
170 | vector2d<T>& normalize() | ||
171 | { | ||
172 | f32 length = (f32)(X*X + Y*Y); | ||
173 | if ( length == 0 ) | ||
174 | return *this; | ||
175 | length = core::reciprocal_squareroot ( length ); | ||
176 | X = (T)(X * length); | ||
177 | Y = (T)(Y * length); | ||
178 | return *this; | ||
179 | } | ||
180 | |||
181 | //! Calculates the angle of this vector in degrees in the trigonometric sense. | ||
182 | /** 0 is to the right (3 o'clock), values increase counter-clockwise. | ||
183 | This method has been suggested by Pr3t3nd3r. | ||
184 | \return Returns a value between 0 and 360. */ | ||
185 | f64 getAngleTrig() const | ||
186 | { | ||
187 | if (Y == 0) | ||
188 | return X < 0 ? 180 : 0; | ||
189 | else | ||
190 | if (X == 0) | ||
191 | return Y < 0 ? 270 : 90; | ||
192 | |||
193 | if ( Y > 0) | ||
194 | if (X > 0) | ||
195 | return atan((irr::f64)Y/(irr::f64)X) * RADTODEG64; | ||
196 | else | ||
197 | return 180.0-atan((irr::f64)Y/-(irr::f64)X) * RADTODEG64; | ||
198 | else | ||
199 | if (X > 0) | ||
200 | return 360.0-atan(-(irr::f64)Y/(irr::f64)X) * RADTODEG64; | ||
201 | else | ||
202 | return 180.0+atan(-(irr::f64)Y/-(irr::f64)X) * RADTODEG64; | ||
203 | } | ||
204 | |||
205 | //! Calculates the angle of this vector in degrees in the counter trigonometric sense. | ||
206 | /** 0 is to the right (3 o'clock), values increase clockwise. | ||
207 | \return Returns a value between 0 and 360. */ | ||
208 | inline f64 getAngle() const | ||
209 | { | ||
210 | if (Y == 0) // corrected thanks to a suggestion by Jox | ||
211 | return X < 0 ? 180 : 0; | ||
212 | else if (X == 0) | ||
213 | return Y < 0 ? 90 : 270; | ||
214 | |||
215 | // don't use getLength here to avoid precision loss with s32 vectors | ||
216 | // avoid floating-point trouble as sqrt(y*y) is occasionally larger than y, so clamp | ||
217 | const f64 tmp = core::clamp(Y / sqrt((f64)(X*X + Y*Y)), -1.0, 1.0); | ||
218 | const f64 angle = atan( core::squareroot(1 - tmp*tmp) / tmp) * RADTODEG64; | ||
219 | |||
220 | if (X>0 && Y>0) | ||
221 | return angle + 270; | ||
222 | else | ||
223 | if (X>0 && Y<0) | ||
224 | return angle + 90; | ||
225 | else | ||
226 | if (X<0 && Y<0) | ||
227 | return 90 - angle; | ||
228 | else | ||
229 | if (X<0 && Y>0) | ||
230 | return 270 - angle; | ||
231 | |||
232 | return angle; | ||
233 | } | ||
234 | |||
235 | //! Calculates the angle between this vector and another one in degree. | ||
236 | /** \param b Other vector to test with. | ||
237 | \return Returns a value between 0 and 90. */ | ||
238 | inline f64 getAngleWith(const vector2d<T>& b) const | ||
239 | { | ||
240 | f64 tmp = (f64)(X*b.X + Y*b.Y); | ||
241 | |||
242 | if (tmp == 0.0) | ||
243 | return 90.0; | ||
244 | |||
245 | tmp = tmp / core::squareroot((f64)((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y))); | ||
246 | if (tmp < 0.0) | ||
247 | tmp = -tmp; | ||
248 | if ( tmp > 1.0 ) // avoid floating-point trouble | ||
249 | tmp = 1.0; | ||
250 | |||
251 | return atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64; | ||
252 | } | ||
253 | |||
254 | //! Returns if this vector interpreted as a point is on a line between two other points. | ||
255 | /** It is assumed that the point is on the line. | ||
256 | \param begin Beginning vector to compare between. | ||
257 | \param end Ending vector to compare between. | ||
258 | \return True if this vector is between begin and end, false if not. */ | ||
259 | bool isBetweenPoints(const vector2d<T>& begin, const vector2d<T>& end) const | ||
260 | { | ||
261 | if (begin.X != end.X) | ||
262 | { | ||
263 | return ((begin.X <= X && X <= end.X) || | ||
264 | (begin.X >= X && X >= end.X)); | ||
265 | } | ||
266 | else | ||
267 | { | ||
268 | return ((begin.Y <= Y && Y <= end.Y) || | ||
269 | (begin.Y >= Y && Y >= end.Y)); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | //! Creates an interpolated vector between this vector and another vector. | ||
274 | /** \param other The other vector to interpolate with. | ||
275 | \param d Interpolation value between 0.0f (all the other vector) and 1.0f (all this vector). | ||
276 | Note that this is the opposite direction of interpolation to getInterpolated_quadratic() | ||
277 | \return An interpolated vector. This vector is not modified. */ | ||
278 | vector2d<T> getInterpolated(const vector2d<T>& other, f64 d) const | ||
279 | { | ||
280 | f64 inv = 1.0f - d; | ||
281 | return vector2d<T>((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d)); | ||
282 | } | ||
283 | |||
284 | //! Creates a quadratically interpolated vector between this and two other vectors. | ||
285 | /** \param v2 Second vector to interpolate with. | ||
286 | \param v3 Third vector to interpolate with (maximum at 1.0f) | ||
287 | \param d Interpolation value between 0.0f (all this vector) and 1.0f (all the 3rd vector). | ||
288 | Note that this is the opposite direction of interpolation to getInterpolated() and interpolate() | ||
289 | \return An interpolated vector. This vector is not modified. */ | ||
290 | vector2d<T> getInterpolated_quadratic(const vector2d<T>& v2, const vector2d<T>& v3, f64 d) const | ||
291 | { | ||
292 | // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d; | ||
293 | const f64 inv = 1.0f - d; | ||
294 | const f64 mul0 = inv * inv; | ||
295 | const f64 mul1 = 2.0f * d * inv; | ||
296 | const f64 mul2 = d * d; | ||
297 | |||
298 | return vector2d<T> ( (T)(X * mul0 + v2.X * mul1 + v3.X * mul2), | ||
299 | (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2)); | ||
300 | } | ||
301 | |||
302 | //! Sets this vector to the linearly interpolated vector between a and b. | ||
303 | /** \param a first vector to interpolate with, maximum at 1.0f | ||
304 | \param b second vector to interpolate with, maximum at 0.0f | ||
305 | \param d Interpolation value between 0.0f (all vector b) and 1.0f (all vector a) | ||
306 | Note that this is the opposite direction of interpolation to getInterpolated_quadratic() | ||
307 | */ | ||
308 | vector2d<T>& interpolate(const vector2d<T>& a, const vector2d<T>& b, f64 d) | ||
309 | { | ||
310 | X = (T)((f64)b.X + ( ( a.X - b.X ) * d )); | ||
311 | Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d )); | ||
312 | return *this; | ||
313 | } | ||
314 | |||
315 | //! X coordinate of vector. | ||
316 | T X; | ||
317 | |||
318 | //! Y coordinate of vector. | ||
319 | T Y; | ||
320 | }; | ||
321 | |||
322 | //! Typedef for f32 2d vector. | ||
323 | typedef vector2d<f32> vector2df; | ||
324 | |||
325 | //! Typedef for integer 2d vector. | ||
326 | typedef vector2d<s32> vector2di; | ||
327 | |||
328 | template<class S, class T> | ||
329 | vector2d<T> operator*(const S scalar, const vector2d<T>& vector) { return vector*scalar; } | ||
330 | |||
331 | // These methods are declared in dimension2d, but need definitions of vector2d | ||
332 | template<class T> | ||
333 | dimension2d<T>::dimension2d(const vector2d<T>& other) : Width(other.X), Height(other.Y) { } | ||
334 | |||
335 | template<class T> | ||
336 | bool dimension2d<T>::operator==(const vector2d<T>& other) const { return Width == other.X && Height == other.Y; } | ||
337 | |||
338 | } // end namespace core | ||
339 | } // end namespace irr | ||
340 | |||
341 | #endif | ||
342 | |||