Imported more code from the old engine.
[peakengine.git] / engine / include / support / vector2d.h
blob5ab78d303cdfd9bfd4d61845da7491438414602c
1 // Copyright (C) 2002-2007 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
5 #ifndef __IRR_POINT_2D_H_INCLUDED__
6 #define __IRR_POINT_2D_H_INCLUDED__
8 #include "irrMath.h"
10 namespace irr
12 namespace core
16 //! 2d vector template class with lots of operators and methods.
17 template <class T>
18 class vector2d
20 public:
22 vector2d() : X(0), Y(0) {}
23 vector2d(T nx, T ny) : X(nx), Y(ny) {}
24 vector2d(const vector2d<T>& other) : X(other.X), Y(other.Y) {}
26 // operators
28 vector2d<T> operator-() const { return vector2d<T>(-X, -Y); }
30 vector2d<T>& operator=(const vector2d<T>& other) { X = other.X; Y = other.Y; return *this; }
32 vector2d<T> operator+(const vector2d<T>& other) const { return vector2d<T>(X + other.X, Y + other.Y); }
33 vector2d<T>& operator+=(const vector2d<T>& other) { X+=other.X; Y+=other.Y; return *this; }
34 vector2d<T> operator+(const T v) const { return vector2d<T>(X + v, Y + v); }
35 vector2d<T>& operator+=(const T v) { X+=v; Y+=v; return *this; }
37 vector2d<T> operator-(const vector2d<T>& other) const { return vector2d<T>(X - other.X, Y - other.Y); }
38 vector2d<T>& operator-=(const vector2d<T>& other) { X-=other.X; Y-=other.Y; return *this; }
39 vector2d<T> operator-(const T v) const { return vector2d<T>(X - v, Y - v); }
40 vector2d<T>& operator-=(const T v) { X-=v; Y-=v; return *this; }
42 vector2d<T> operator*(const vector2d<T>& other) const { return vector2d<T>(X * other.X, Y * other.Y); }
43 vector2d<T>& operator*=(const vector2d<T>& other) { X*=other.X; Y*=other.Y; return *this; }
44 vector2d<T> operator*(const T v) const { return vector2d<T>(X * v, Y * v); }
45 vector2d<T>& operator*=(const T v) { X*=v; Y*=v; return *this; }
47 vector2d<T> operator/(const vector2d<T>& other) const { return vector2d<T>(X / other.X, Y / other.Y); }
48 vector2d<T>& operator/=(const vector2d<T>& other) { X/=other.X; Y/=other.Y; return *this; }
49 vector2d<T> operator/(const T v) const { return vector2d<T>(X / v, Y / v); }
50 vector2d<T>& operator/=(const T v) { X/=v; Y/=v; return *this; }
52 bool operator<=(const vector2d<T>&other) const { return X<=other.X && Y<=other.Y; }
53 bool operator>=(const vector2d<T>&other) const { return X>=other.X && Y>=other.Y; }
55 bool operator<(const vector2d<T>&other) const { return X<other.X && Y<other.Y; }
56 bool operator>(const vector2d<T>&other) const { return X>other.X && Y>other.Y; }
58 bool operator==(const vector2d<T>& other) const { return other.X==X && other.Y==Y; }
59 bool operator!=(const vector2d<T>& other) const { return other.X!=X || other.Y!=Y; }
61 // functions
63 //! returns if this vector equals the other one, taking floating point rounding errors into account
64 bool equals(const vector2d<T>& other) const
66 return core::equals(X, other.X) && core::equals(Y, other.Y);
69 void set(T nx, T ny) {X=nx; Y=ny; }
70 void set(const vector2d<T>& p) { X=p.X; Y=p.Y;}
72 //! Returns the length of the vector
73 //! \return Returns the length of the vector.
74 T getLength() const { return (T)sqrt((f64)(X*X + Y*Y)); }
76 //! Returns the squared length of this vector
77 /** This is useful because it is much faster than getLength(). */
78 T getLengthSQ() const { return X*X + Y*Y; }
80 //! Returns the dot product of this vector with another.
81 T dotProduct(const vector2d<T>& other) const
83 return X*other.X + Y*other.Y;
86 //! Returns distance from another point. Here, the vector is interpreted
87 //! as a point in 2 dimensional space.
88 T getDistanceFrom(const vector2d<T>& other) const
90 return vector2d<T>(X - other.X, Y - other.Y).getLength();
93 //! Returns squared distance from another point. Here, the vector is
94 //! interpreted as a point in 2 dimensional space.
95 T getDistanceFromSQ(const vector2d<T>& other) const
97 return vector2d<T>(X - other.X, Y - other.Y).getLengthSQ();
100 //! rotates the point around a center by an amount of degrees.
101 void rotateBy(f64 degrees, const vector2d<T>& center)
103 degrees *= DEGTORAD64;
104 T cs = (T)cos(degrees);
105 T sn = (T)sin(degrees);
107 X -= center.X;
108 Y -= center.Y;
110 set(X*cs - Y*sn, X*sn + Y*cs);
112 X += center.X;
113 Y += center.Y;
116 //! normalizes the vector.
117 vector2d<T>& normalize()
119 T l = X*X + Y*Y;
120 if (l == 0)
121 return *this;
122 l = core::reciprocal_squareroot ( (f32)l );
123 X *= l;
124 Y *= l;
125 return *this;
128 //! Calculates the angle of this vector in grad in the trigonometric sense.
129 //! This method has been suggested by Pr3t3nd3r.
130 //! \return Returns a value between 0 and 360.
131 f64 getAngleTrig() const
133 if (X == 0)
134 return Y < 0 ? 270 : 90;
135 else
136 if (Y == 0)
137 return X < 0 ? 180 : 0;
139 if ( Y > 0)
140 if (X > 0)
141 return atan(Y/X) * RADTODEG64;
142 else
143 return 180.0-atan(Y/-X) * RADTODEG64;
144 else
145 if (X > 0)
146 return 360.0-atan(-Y/X) * RADTODEG64;
147 else
148 return 180.0+atan(-Y/-X) * RADTODEG64;
151 //! Calculates the angle of this vector in grad in the counter trigonometric sense.
152 //! \return Returns a value between 0 and 360.
153 inline f64 getAngle() const
155 if (Y == 0) // corrected thanks to a suggestion by Jox
156 return X < 0 ? 180 : 0;
157 else if (X == 0)
158 return Y < 0 ? 90 : 270;
160 f64 tmp = Y / getLength();
161 tmp = atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64;
163 if (X>0 && Y>0)
164 return tmp + 270;
165 else
166 if (X>0 && Y<0)
167 return tmp + 90;
168 else
169 if (X<0 && Y<0)
170 return 90 - tmp;
171 else
172 if (X<0 && Y>0)
173 return 270 - tmp;
175 return tmp;
178 //! Calculates the angle between this vector and another one in grad.
179 //! \return Returns a value between 0 and 90.
180 inline f64 getAngleWith(const vector2d<T>& b) const
182 f64 tmp = X*b.X + Y*b.Y;
184 if (tmp == 0.0)
185 return 90.0;
187 tmp = tmp / sqrt((f64)((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y)));
188 if (tmp < 0.0)
189 tmp = -tmp;
191 return atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64;
194 //! Returns if this vector interpreted as a point is on a line between two other points.
195 /** It is assumed that the point is on the line. */
196 //! \param begin: Beginning vector to compare between.
197 //! \param end: Ending vector to compare between.
198 //! \return True if this vector is between begin and end. False if not.
199 bool isBetweenPoints(const vector2d<T>& begin, const vector2d<T>& end) const
201 T f = (end - begin).getLengthSQ();
202 return getDistanceFromSQ(begin) < f &&
203 getDistanceFromSQ(end) < f;
206 //! returns interpolated vector
207 //! \param other: other vector to interpolate between
208 //! \param d: value between 0.0f and 1.0f.
209 vector2d<T> getInterpolated(const vector2d<T>& other, f32 d) const
211 T inv = (T) 1.0 - d;
212 return vector2d<T>(other.X*inv + X*d, other.Y*inv + Y*d);
215 //! Returns (quadratically) interpolated vector between this and the two given ones.
216 /** \param v2: second vector to interpolate with
217 \param v3: third vector to interpolate with
218 \param d: value between 0.0f and 1.0f. */
219 vector2d<T> getInterpolated_quadratic(const vector2d<T>& v2, const vector2d<T>& v3, const T d) const
221 // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d;
222 const T inv = (T) 1.0 - d;
223 const T mul0 = inv * inv;
224 const T mul1 = (T) 2.0 * d * inv;
225 const T mul2 = d * d;
227 return vector2d<T> ( X * mul0 + v2.X * mul1 + v3.X * mul2,
228 Y * mul0 + v2.Y * mul1 + v3.Y * mul2);
231 //! sets this vector to the linearly interpolated vector between a and b.
232 /** \param a: first vector to interpolate with
233 \param b: second vector to interpolate with
234 \param t: value between 0.0f and 1.0f. */
235 void interpolate(const vector2d<T>& a, const vector2d<T>& b, const f32 t)
237 X = b.X + ( ( a.X - b.X ) * t );
238 Y = b.Y + ( ( a.Y - b.Y ) * t );
241 // member variables
242 T X, Y;
245 //! Typedef for f32 2d vector.
246 typedef vector2d<f32> vector2df;
247 //! Typedef for integer 2d vector.
248 typedef vector2d<s32> vector2di;
250 template<class S, class T> vector2d<T> operator*(const S scalar, const vector2d<T>& vector) { return vector*scalar; }
252 } // end namespace core
253 } // end namespace irr
255 #endif