Steeriously  0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Pages
Vector2.hpp
1 #ifndef VECTOR2_HPP
2 #define VECTOR2_HPP
3 
4 #include <math.h>
5 #include <iosfwd>
6 #include <limits>
7 
8 #include <steeriously/Utilities.hpp>
9 
10 namespace steer
11 {
12 
13 
18 struct Vector2
19 {
20  double x;
21  double y;
22 
27  Vector2():x(0.0),y(0.0){}
28  Vector2(double a, double b):x(a),y(b){}
29 
30  //sets x and y to zero
35  void Zero(){x=0.0; y=0.0;}
36 
37  //returns true if both x and y are zero
42  bool isZero() const {return (x*x + y*y) < MinDouble;}
43 
44  //returns the length of the vector
49  inline double Length()const;
50 
51  //returns the squared length of the vector (thereby avoiding the sqrt)
56  inline double LengthSq() const;
57 
62  inline void Normalize();
63 
68  inline double Dot(const Vector2& v2) const;
69 
70  //returns positive if v2 is clockwise of this vector,
71  //negative if anticlockwise (assuming the Y axis is pointing down,
72  //X axis to right like a Window app)
77  inline int Sign(const Vector2& v2) const;
78 
79  //returns the vector that is perpendicular to this one.
84  inline Vector2 Perp() const;
85 
86  //adjusts x and y so that the length of the vector does not exceed max
87  inline void Truncate(double max);
88 
89  //returns the distance between this vector and th one passed as a parameter
90  inline double Distance(const Vector2 &v2)const;
91 
92  //squared version of above.
93  inline double DistanceSq(const Vector2 &v2)const;
94 
95  inline void Reflect(const Vector2& norm);
96 
97  //returns the vector that is the reverse of this vector
98  inline Vector2 GetReverse()const;
99 
100 
101  //we need some overloaded operators
102  const Vector2& operator+=(const Vector2 &rhs)
103  {
104  x += rhs.x;
105  y += rhs.y;
106 
107  return *this;
108  }
109 
110  const Vector2& operator-=(const Vector2 &rhs)
111  {
112  x -= rhs.x;
113  y -= rhs.y;
114 
115  return *this;
116  }
117 
118  const Vector2& operator*=(const double& rhs)
119  {
120  x *= rhs;
121  y *= rhs;
122 
123  return *this;
124  }
125 
126  const Vector2& operator/=(const double& rhs)
127  {
128  x /= rhs;
129  y /= rhs;
130 
131  return *this;
132  }
133 
134  bool operator==(const Vector2& rhs)const
135  {
136  return (isEqual(x, rhs.x) && isEqual(y,rhs.y) );
137  }
138 
139  bool operator!=(const Vector2& rhs)const
140  {
141  return (x != rhs.x) || (y != rhs.y);
142  }
143 
144 };
145 
146 //-----------------------------------------------------------------------some more operator overloads
147 inline Vector2 operator*(const Vector2 &lhs, double rhs);
148 inline Vector2 operator*(double lhs, const Vector2 &rhs);
149 inline Vector2 operator-(const Vector2 &lhs, const Vector2 &rhs);
150 inline Vector2 operator+(const Vector2 &lhs, const Vector2 &rhs);
151 inline Vector2 operator/(const Vector2 &lhs, double val);
152 
153 //------------------------------------------------------------------------member functions
154 
155 //------------------------- Length ---------------------------------------
156 //
157 // returns the length of a 2D vector
158 //------------------------------------------------------------------------
159 inline double Vector2::Length()const
160 {
161  return sqrt(x * x + y * y);
162 }
163 
164 
165 //------------------------- LengthSq -------------------------------------
166 //
167 // returns the squared length of a 2D vector
168 //------------------------------------------------------------------------
169 inline double Vector2::LengthSq()const
170 {
171  return (x * x + y * y);
172 }
173 
174 
175 //------------------------- Vec2DDot -------------------------------------
176 //
177 // calculates the dot product
178 //------------------------------------------------------------------------
179 inline double Vector2::Dot(const Vector2 &v2)const
180 {
181  return x*v2.x + y*v2.y;
182 }
183 
184 //------------------------ Sign ------------------------------------------
185 //
186 // returns positive if v2 is clockwise of this vector,
187 // minus if anticlockwise (Y axis pointing down, X axis to right)
188 //------------------------------------------------------------------------
189 enum {clockwise = 1, anticlockwise = -1};
190 
191 inline int Vector2::Sign(const Vector2& v2)const
192 {
193  if (y*v2.x > x*v2.y)
194  {
195  return anticlockwise;
196  }
197  else
198  {
199  return clockwise;
200  }
201 }
202 
203 //------------------------------ Perp ------------------------------------
204 //
205 // Returns a vector perpendicular to this vector
206 //------------------------------------------------------------------------
207 inline Vector2 Vector2::Perp()const
208 {
209  return Vector2(-y, x);
210 }
211 
212 //------------------------------ Distance --------------------------------
213 //
214 // calculates the euclidean distance between two vectors
215 //------------------------------------------------------------------------
216 inline double Vector2::Distance(const Vector2 &v2)const
217 {
218  double ySeparation = v2.y - y;
219  double xSeparation = v2.x - x;
220 
221  return sqrt(ySeparation*ySeparation + xSeparation*xSeparation);
222 }
223 
224 
225 //------------------------------ DistanceSq ------------------------------
226 //
227 // calculates the euclidean distance squared between two vectors
228 //------------------------------------------------------------------------
229 inline double Vector2::DistanceSq(const Vector2 &v2)const
230 {
231  double ySeparation = v2.y - y;
232  double xSeparation = v2.x - x;
233 
234  return ySeparation*ySeparation + xSeparation*xSeparation;
235 }
236 
237 //----------------------------- Truncate ---------------------------------
238 //
239 // truncates a vector so that its length does not exceed max
240 //------------------------------------------------------------------------
241 inline void Vector2::Truncate(double max)
242 {
243  if (this->Length() > max)
244  {
245  this->Normalize();
246 
247  *this *= max;
248  }
249 }
250 
251 //--------------------------- Reflect ------------------------------------
252 //
253 // given a normalized vector this method reflects the vector it
254 // is operating upon. (like the path of a ball bouncing off a wall)
255 //------------------------------------------------------------------------
256 inline void Vector2::Reflect(const Vector2& norm)
257 {
258  *this += 2.0 * this->Dot(norm) * norm.GetReverse();
259 }
260 
261 //----------------------- GetReverse ----------------------------------------
262 //
263 // returns the vector that is the reverse of this vector
264 //------------------------------------------------------------------------
265 inline Vector2 Vector2::GetReverse()const
266 {
267  return Vector2(-this->x, -this->y);
268 }
269 
270 
271 //------------------------- Normalize ------------------------------------
272 //
273 // normalizes a 2D Vector
274 //------------------------------------------------------------------------
275 inline void Vector2::Normalize()
276 {
277  double vector_length = this->Length();
278 
279  if (vector_length > std::numeric_limits<double>::epsilon())
280  {
281  this->x /= vector_length;
282  this->y /= vector_length;
283  }
284 }
285 
286 
287 //------------------------------------------------------------------------non member functions
288 
289 inline Vector2 Vec2DNormalize(const Vector2 &v)
290 {
291  Vector2 vec = v;
292 
293  double vector_length = vec.Length();
294 
295  if (vector_length > std::numeric_limits<double>::epsilon())
296  {
297  vec.x /= vector_length;
298  vec.y /= vector_length;
299  }
300 
301  return vec;
302 }
303 
304 
305 inline double Vec2DDistance(const Vector2 &v1, const Vector2 &v2)
306 {
307 
308  double ySeparation = v2.y - v1.y;
309  double xSeparation = v2.x - v1.x;
310 
311  return sqrt(ySeparation*ySeparation + xSeparation*xSeparation);
312 }
313 
314 inline double Vec2DDistanceSq(const Vector2 &v1, const Vector2 &v2)
315 {
316 
317  double ySeparation = v2.y - v1.y;
318  double xSeparation = v2.x - v1.x;
319 
320  return ySeparation*ySeparation + xSeparation*xSeparation;
321 }
322 
323 inline double Vec2DLength(const Vector2& v)
324 {
325  return sqrt(v.x*v.x + v.y*v.y);
326 }
327 
328 inline double Vec2DLengthSq(const Vector2& v)
329 {
330  return (v.x*v.x + v.y*v.y);
331 }
332 
333 
334 //------------------------------------------------------------------------operator overloads
335 inline Vector2 operator*(const Vector2 &lhs, double rhs)
336 {
337  Vector2 result(lhs);
338  result *= rhs;
339  return result;
340 }
341 
342 inline Vector2 operator*(double lhs, const Vector2 &rhs)
343 {
344  Vector2 result(rhs);
345  result *= lhs;
346  return result;
347 }
348 
349 //overload the - operator
350 inline Vector2 operator-(const Vector2 &lhs, const Vector2 &rhs)
351 {
352  Vector2 result(lhs);
353  result.x -= rhs.x;
354  result.y -= rhs.y;
355 
356  return result;
357 }
358 
359 //overload the + operator
360 inline Vector2 operator+(const Vector2 &lhs, const Vector2 &rhs)
361 {
362  Vector2 result(lhs);
363  result.x += rhs.x;
364  result.y += rhs.y;
365 
366  return result;
367 }
368 
369 //overload the / operator
370 inline Vector2 operator/(const Vector2 &lhs, double val)
371 {
372  Vector2 result(lhs);
373  result.x /= val;
374  result.y /= val;
375 
376  return result;
377 }
378 
380 
381 
382 //treats a window as a toroid
383 inline void WrapAround(Vector2 &pos, int MaxX, int MaxY)
384 {
385  if (pos.x > MaxX) {pos.x = 0.0;}
386 
387  if (pos.x < 0) {pos.x = (double)MaxX;}
388 
389  if (pos.y < 0) {pos.y = (double)MaxY;}
390 
391  if (pos.y > MaxY) {pos.y = 0.0;}
392 }
393 
394 //returns true if the point p is not inside the region defined by top_left
395 //and bot_rgt
396 inline bool NotInsideRegion(Vector2 p,
397  Vector2 top_left,
398  Vector2 bot_rgt)
399 {
400  return (p.x < top_left.x) || (p.x > bot_rgt.x) ||
401  (p.y < top_left.y) || (p.y > bot_rgt.y);
402 }
403 
404 inline bool InsideRegion(Vector2 p,
405  Vector2 top_left,
406  Vector2 bot_rgt)
407 {
408  return !((p.x < top_left.x) || (p.x > bot_rgt.x) ||
409  (p.y < top_left.y) || (p.y > bot_rgt.y));
410 }
411 
412 inline bool InsideRegion(Vector2 p, int left, int top, int right, int bottom)
413 {
414  return !( (p.x < left) || (p.x > right) || (p.y < top) || (p.y > bottom) );
415 }
416 
417 //------------------ isSecondInFOVOfFirst -------------------------------------
418 //
419 // returns true if the target position is in the field of view of the entity
420 // positioned at posFirst facing in facingFirst
421 //-----------------------------------------------------------------------------
422 inline bool isSecondInFOVOfFirst(Vector2 posFirst,
423  Vector2 facingFirst,
424  Vector2 posSecond,
425  double fov)
426 {
427  Vector2 toTarget = Vec2DNormalize(posSecond - posFirst);
428 
429  return facingFirst.Dot(toTarget) >= cos(fov/2.0);
430 }
431 
432 }
433 
434 #endif //VECTOR2_HPP