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
00068 bool operator<=(const vector2d<T>&other) const
00069 {
00070 return (X<other.X || core::equals(X, other.X)) ||
00071 (core::equals(X, other.X) && (Y<other.Y || core::equals(Y, other.Y)));
00072 }
00073
00075 bool operator>=(const vector2d<T>&other) const
00076 {
00077 return (X>other.X || core::equals(X, other.X)) ||
00078 (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y)));
00079 }
00080
00082 bool operator<(const vector2d<T>&other) const
00083 {
00084 return (X<other.X && !core::equals(X, other.X)) ||
00085 (core::equals(X, other.X) && Y<other.Y && !core::equals(Y, other.Y));
00086 }
00087
00089 bool operator>(const vector2d<T>&other) const
00090 {
00091 return (X>other.X && !core::equals(X, other.X)) ||
00092 (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y));
00093 }
00094
00095 bool operator==(const vector2d<T>& other) const { return equals(other); }
00096 bool operator!=(const vector2d<T>& other) const { return !equals(other); }
00097
00098
00099
00101
00104 bool equals(const vector2d<T>& other) const
00105 {
00106 return core::equals(X, other.X) && core::equals(Y, other.Y);
00107 }
00108
00109 vector2d<T>& set(T nx, T ny) {X=nx; Y=ny; return *this; }
00110 vector2d<T>& set(const vector2d<T>& p) { X=p.X; Y=p.Y; return *this; }
00111
00113
00114 T getLength() const { return core::squareroot( X*X + Y*Y ); }
00115
00117
00119 T getLengthSQ() const { return X*X + Y*Y; }
00120
00122
00124 T dotProduct(const vector2d<T>& other) const
00125 {
00126 return X*other.X + Y*other.Y;
00127 }
00128
00130
00133 T getDistanceFrom(const vector2d<T>& other) const
00134 {
00135 return vector2d<T>(X - other.X, Y - other.Y).getLength();
00136 }
00137
00139
00142 T getDistanceFromSQ(const vector2d<T>& other) const
00143 {
00144 return vector2d<T>(X - other.X, Y - other.Y).getLengthSQ();
00145 }
00146
00148
00151 vector2d<T>& rotateBy(f64 degrees, const vector2d<T>& center=vector2d<T>())
00152 {
00153 degrees *= DEGTORAD64;
00154 const f64 cs = cos(degrees);
00155 const f64 sn = sin(degrees);
00156
00157 X -= center.X;
00158 Y -= center.Y;
00159
00160 set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs));
00161
00162 X += center.X;
00163 Y += center.Y;
00164 return *this;
00165 }
00166
00168
00170 vector2d<T>& normalize()
00171 {
00172 f32 length = (f32)(X*X + Y*Y);
00173 if ( length == 0 )
00174 return *this;
00175 length = core::reciprocal_squareroot ( length );
00176 X = (T)(X * length);
00177 Y = (T)(Y * length);
00178 return *this;
00179 }
00180
00182
00185 f64 getAngleTrig() const
00186 {
00187 if (Y == 0)
00188 return X < 0 ? 180 : 0;
00189 else
00190 if (X == 0)
00191 return Y < 0 ? 270 : 90;
00192
00193 if ( Y > 0)
00194 if (X > 0)
00195 return atan((irr::f64)Y/(irr::f64)X) * RADTODEG64;
00196 else
00197 return 180.0-atan((irr::f64)Y/-(irr::f64)X) * RADTODEG64;
00198 else
00199 if (X > 0)
00200 return 360.0-atan(-(irr::f64)Y/(irr::f64)X) * RADTODEG64;
00201 else
00202 return 180.0+atan(-(irr::f64)Y/-(irr::f64)X) * RADTODEG64;
00203 }
00204
00206
00208 inline f64 getAngle() const
00209 {
00210 if (Y == 0)
00211 return X < 0 ? 180 : 0;
00212 else if (X == 0)
00213 return Y < 0 ? 90 : 270;
00214
00215
00216
00217 const f64 tmp = core::clamp(Y / sqrt((f64)(X*X + Y*Y)), -1.0, 1.0);
00218 const f64 angle = atan( core::squareroot(1 - tmp*tmp) / tmp) * RADTODEG64;
00219
00220 if (X>0 && Y>0)
00221 return angle + 270;
00222 else
00223 if (X>0 && Y<0)
00224 return angle + 90;
00225 else
00226 if (X<0 && Y<0)
00227 return 90 - angle;
00228 else
00229 if (X<0 && Y>0)
00230 return 270 - angle;
00231
00232 return angle;
00233 }
00234
00236
00238 inline f64 getAngleWith(const vector2d<T>& b) const
00239 {
00240 f64 tmp = (f64)(X*b.X + Y*b.Y);
00241
00242 if (tmp == 0.0)
00243 return 90.0;
00244
00245 tmp = tmp / core::squareroot((f64)((X*X + Y*Y) * (b.X*b.X + b.Y*b.Y)));
00246 if (tmp < 0.0)
00247 tmp = -tmp;
00248 if ( tmp > 1.0 )
00249 tmp = 1.0;
00250
00251 return atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64;
00252 }
00253
00255
00259 bool isBetweenPoints(const vector2d<T>& begin, const vector2d<T>& end) const
00260 {
00261 if (begin.X != end.X)
00262 {
00263 return ((begin.X <= X && X <= end.X) ||
00264 (begin.X >= X && X >= end.X));
00265 }
00266 else
00267 {
00268 return ((begin.Y <= Y && Y <= end.Y) ||
00269 (begin.Y >= Y && Y >= end.Y));
00270 }
00271 }
00272
00274
00278 vector2d<T> getInterpolated(const vector2d<T>& other, f64 d) const
00279 {
00280 f64 inv = 1.0f - d;
00281 return vector2d<T>((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d));
00282 }
00283
00285
00290 vector2d<T> getInterpolated_quadratic(const vector2d<T>& v2, const vector2d<T>& v3, f64 d) const
00291 {
00292
00293 const f64 inv = 1.0f - d;
00294 const f64 mul0 = inv * inv;
00295 const f64 mul1 = 2.0f * d * inv;
00296 const f64 mul2 = d * d;
00297
00298 return vector2d<T> ( (T)(X * mul0 + v2.X * mul1 + v3.X * mul2),
00299 (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2));
00300 }
00301
00303
00308 vector2d<T>& interpolate(const vector2d<T>& a, const vector2d<T>& b, f64 d)
00309 {
00310 X = (T)((f64)b.X + ( ( a.X - b.X ) * d ));
00311 Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d ));
00312 return *this;
00313 }
00314
00316 T X;
00317
00319 T Y;
00320 };
00321
00323 typedef vector2d<f32> vector2df;
00324
00326 typedef vector2d<s32> vector2di;
00327
00328 template<class S, class T>
00329 vector2d<T> operator*(const S scalar, const vector2d<T>& vector) { return vector*scalar; }
00330
00331
00332 template<class T>
00333 dimension2d<T>::dimension2d(const vector2d<T>& other) : Width(other.X), Height(other.Y) { }
00334
00335 template<class T>
00336 bool dimension2d<T>::operator==(const vector2d<T>& other) const { return Width == other.X && Height == other.Y; }
00337
00338 }
00339 }
00340
00341 #endif
00342