00001
00002
00003
00004
00005 #ifndef __IRR_POINT_2D_H_INCLUDED__
00006 #define __IRR_POINT_2D_H_INCLUDED__
00007
00008 #include "irrMath.h"
00009 #include "dimension2d.h"
00010
00011 namespace irr
00012 {
00013 namespace core
00014 {
00015
00016
00018
00020 template <class T>
00021 class vector2d
00022 {
00023 public:
00025 vector2d() : X(0), Y(0) {}
00027 vector2d(T nx, T ny) : X(nx), Y(ny) {}
00029 explicit vector2d(T n) : X(n), Y(n) {}
00031 vector2d(const vector2d<T>& other) : X(other.X), Y(other.Y) {}
00032
00033 vector2d(const dimension2d<T>& other) : X(other.Width), Y(other.Height) {}
00034
00035
00036
00037 vector2d<T> operator-() const { return vector2d<T>(-X, -Y); }
00038
00039 vector2d<T>& operator=(const vector2d<T>& other) { X = other.X; Y = other.Y; return *this; }
00040
00041 vector2d<T>& operator=(const dimension2d<T>& other) { X = other.Width; Y = other.Height; return *this; }
00042
00043 vector2d<T> operator+(const vector2d<T>& other) const { return vector2d<T>(X + other.X, Y + other.Y); }
00044 vector2d<T> operator+(const dimension2d<T>& other) const { return vector2d<T>(X + other.Width, Y + other.Height); }
00045 vector2d<T>& operator+=(const vector2d<T>& other) { X+=other.X; Y+=other.Y; return *this; }
00046 vector2d<T> operator+(const T v) const { return vector2d<T>(X + v, Y + v); }
00047 vector2d<T>& operator+=(const T v) { X+=v; Y+=v; return *this; }
00048 vector2d<T>& operator+=(const dimension2d<T>& other) { X += other.Width; Y += other.Height; return *this; }
00049
00050 vector2d<T> operator-(const vector2d<T>& other) const { return vector2d<T>(X - other.X, Y - other.Y); }
00051 vector2d<T> operator-(const dimension2d<T>& other) const { return vector2d<T>(X - other.Width, Y - other.Height); }
00052 vector2d<T>& operator-=(const vector2d<T>& other) { X-=other.X; Y-=other.Y; return *this; }
00053 vector2d<T> operator-(const T v) const { return vector2d<T>(X - v, Y - v); }
00054 vector2d<T>& operator-=(const T v) { X-=v; Y-=v; return *this; }
00055 vector2d<T>& operator-=(const dimension2d<T>& other) { X -= other.Width; Y -= other.Height; return *this; }
00056
00057 vector2d<T> operator*(const vector2d<T>& other) const { return vector2d<T>(X * other.X, Y * other.Y); }
00058 vector2d<T>& operator*=(const vector2d<T>& other) { X*=other.X; Y*=other.Y; return *this; }
00059 vector2d<T> operator*(const T v) const { return vector2d<T>(X * v, Y * v); }
00060 vector2d<T>& operator*=(const T v) { X*=v; Y*=v; return *this; }
00061
00062 vector2d<T> operator/(const vector2d<T>& other) const { return vector2d<T>(X / other.X, Y / other.Y); }
00063 vector2d<T>& operator/=(const vector2d<T>& other) { X/=other.X; Y/=other.Y; return *this; }
00064 vector2d<T> operator/(const T v) const { return vector2d<T>(X / v, Y / v); }
00065 vector2d<T>& operator/=(const T v) { X/=v; Y/=v; return *this; }
00066
00067 bool operator<=(const vector2d<T>&other) const { return X<=other.X && Y<=other.Y; }
00068 bool operator>=(const vector2d<T>&other) const { return X>=other.X && Y>=other.Y; }
00069
00070 bool operator<(const vector2d<T>&other) const { return X<other.X && Y<other.Y; }
00071 bool operator>(const vector2d<T>&other) const { return X>other.X && Y>other.Y; }
00072
00073 bool operator==(const vector2d<T>& other) const { return equals(other); }
00074 bool operator!=(const vector2d<T>& other) const { return !equals(other); }
00075
00076
00077
00079
00082 bool equals(const vector2d<T>& other) const
00083 {
00084 return core::equals(X, other.X) && core::equals(Y, other.Y);
00085 }
00086
00087 vector2d<T>& set(T nx, T ny) {X=nx; Y=ny; return *this; }
00088 vector2d<T>& set(const vector2d<T>& p) { X=p.X; Y=p.Y; return *this; }
00089
00091
00092 T getLength() const { return core::squareroot( X*X + Y*Y ); }
00093
00095
00097 T getLengthSQ() const { return X*X + Y*Y; }
00098
00100
00102 T dotProduct(const vector2d<T>& other) const
00103 {
00104 return X*other.X + Y*other.Y;
00105 }
00106
00108
00111 T getDistanceFrom(const vector2d<T>& other) const
00112 {
00113 return vector2d<T>(X - other.X, Y - other.Y).getLength();
00114 }
00115
00117
00120 T getDistanceFromSQ(const vector2d<T>& other) const
00121 {
00122 return vector2d<T>(X - other.X, Y - other.Y).getLengthSQ();
00123 }
00124
00126
00129 vector2d<T>& rotateBy(f64 degrees, const vector2d<T>& center=vector2d<T>())
00130 {
00131 degrees *= DEGTORAD64;
00132 const f64 cs = cos(degrees);
00133 const f64 sn = sin(degrees);
00134
00135 X -= center.X;
00136 Y -= center.Y;
00137
00138 set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs));
00139
00140 X += center.X;
00141 Y += center.Y;
00142 return *this;
00143 }
00144
00146
00148 vector2d<T>& normalize()
00149 {
00150 f32 length = (f32)(X*X + Y*Y);
00151 if (core::equals(length, 0.f))
00152 return *this;
00153 length = core::reciprocal_squareroot ( length );
00154 X = (T)(X * length);
00155 Y = (T)(Y * length);
00156 return *this;
00157 }
00158
00160
00163 f64 getAngleTrig() const
00164 {
00165 if (Y == 0)
00166 return X < 0 ? 180 : 0;
00167 else
00168 if (X == 0)
00169 return Y < 0 ? 270 : 90;
00170
00171 if ( Y > 0)
00172 if (X > 0)
00173 return atan(Y/X) * RADTODEG64;
00174 else
00175 return 180.0-atan(Y/-X) * RADTODEG64;
00176 else
00177 if (X > 0)
00178 return 360.0-atan(-Y/X) * RADTODEG64;
00179 else
00180 return 180.0+atan(-Y/-X) * RADTODEG64;
00181 }
00182
00184
00186 inline f64 getAngle() const
00187 {
00188 if (Y == 0)
00189 return X < 0 ? 180 : 0;
00190 else if (X == 0)
00191 return Y < 0 ? 90 : 270;
00192
00193
00194 f64 tmp = Y / sqrt((f64)(X*X + Y*Y));
00195 tmp = atan( core::squareroot(1 - tmp*tmp) / tmp) * RADTODEG64;
00196
00197 if (X>0 && Y>0)
00198 return tmp + 270;
00199 else
00200 if (X>0 && Y<0)
00201 return tmp + 90;
00202 else
00203 if (X<0 && Y<0)
00204 return 90 - tmp;
00205 else
00206 if (X<0 && Y>0)
00207 return 270 - tmp;
00208
00209 return tmp;
00210 }
00211
00213
00215 inline f64 getAngleWith(const vector2d<T>& b) const
00216 {
00217 f64 tmp = X*b.X + Y*b.Y;
00218
00219 if (tmp == 0.0)
00220 return 90.0;
00221
00222 tmp = tmp / core::squareroot((f64)((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y)));
00223 if (tmp < 0.0)
00224 tmp = -tmp;
00225
00226 return atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64;
00227 }
00228
00230
00234 bool isBetweenPoints(const vector2d<T>& begin, const vector2d<T>& end) const
00235 {
00236 if (begin.X != end.X)
00237 {
00238 return ((begin.X <= X && X <= end.X) ||
00239 (begin.X >= X && X >= end.X));
00240 }
00241 else
00242 {
00243 return ((begin.Y <= Y && Y <= end.Y) ||
00244 (begin.Y >= Y && Y >= end.Y));
00245 }
00246 }
00247
00249
00253 vector2d<T> getInterpolated(const vector2d<T>& other, f64 d) const
00254 {
00255 f64 inv = 1.0f - d;
00256 return vector2d<T>((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d));
00257 }
00258
00260
00265 vector2d<T> getInterpolated_quadratic(const vector2d<T>& v2, const vector2d<T>& v3, f64 d) const
00266 {
00267
00268 const f64 inv = 1.0f - d;
00269 const f64 mul0 = inv * inv;
00270 const f64 mul1 = 2.0f * d * inv;
00271 const f64 mul2 = d * d;
00272
00273 return vector2d<T> ( (T)(X * mul0 + v2.X * mul1 + v3.X * mul2),
00274 (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2));
00275 }
00276
00278
00283 vector2d<T>& interpolate(const vector2d<T>& a, const vector2d<T>& b, f64 d)
00284 {
00285 X = (T)((f64)b.X + ( ( a.X - b.X ) * d ));
00286 Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d ));
00287 return *this;
00288 }
00289
00291 T X;
00292
00294 T Y;
00295 };
00296
00298 typedef vector2d<f32> vector2df;
00299
00301 typedef vector2d<s32> vector2di;
00302
00303 template<class S, class T>
00304 vector2d<T> operator*(const S scalar, const vector2d<T>& vector) { return vector*scalar; }
00305
00306
00307 template<class T>
00308 dimension2d<T>::dimension2d(const vector2d<T>& other) : Width(other.X), Height(other.Y) { }
00309
00310 template<class T>
00311 bool dimension2d<T>::operator==(const vector2d<T>& other) const { return Width == other.X && Height == other.Y; }
00312
00313 }
00314 }
00315
00316 #endif
00317