Enki  1.9
Geometry.h
Go to the documentation of this file.
1 /*
2  Enki - a fast 2D robot simulator
3  Copyright (C) 1999-2016 Stephane Magnenat <stephane at magnenat dot net>
4  Copyright (C) 2004-2005 Markus Waibel <markus dot waibel at epfl dot ch>
5  Copyright (c) 2004-2005 Antoine Beyeler <abeyeler at ab-ware dot com>
6  Copyright (C) 2005-2006 Laboratory of Intelligent Systems, EPFL, Lausanne
7  Copyright (C) 2006-2008 Laboratory of Robotics Systems, EPFL, Lausanne
8  See AUTHORS for details
9 
10  This program is free software; the authors of any publication
11  arising from research using this software are asked to add the
12  following reference:
13  Enki - a fast 2D robot simulator
14  http://home.gna.org/enki
15  Stephane Magnenat <stephane at magnenat dot net>,
16  Markus Waibel <markus dot waibel at epfl dot ch>
17  Laboratory of Intelligent Systems, EPFL, Lausanne.
18 
19  You can redistribute this program and/or modify
20  it under the terms of the GNU General Public License as published by
21  the Free Software Foundation; either version 2 of the License, or
22  (at your option) any later version.
23 
24  This program is distributed in the hope that it will be useful,
25  but WITHOUT ANY WARRANTY; without even the implied warranty of
26  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  GNU General Public License for more details.
28 
29  You should have received a copy of the GNU General Public License
30  along with this program; if not, write to the Free Software
31  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 */
33 
34 #ifndef __ENKI_GEOMETRY_H
35 #define __ENKI_GEOMETRY_H
36 
37 #ifdef WIN32
38 #define _USE_MATH_DEFINES
39 #include <math.h>
40 #ifndef NOMINMAX
41 #define NOMINMAX
42 #endif
43 #endif
44 #include <cmath>
45 #include <vector>
46 #include <limits>
47 #include <ostream>
48 #include <algorithm>
49 
50 #ifdef _MSC_VER
51 #define round(x) floor((x) + 0.5)
52 #endif
53 
58 namespace Enki
59 {
61 
68  struct Vector
69  {
71  double x;
73  double y;
74 
76  Vector() { x = y = 0; }
78  Vector(double v) { this->x = v; this->y = v; }
80  Vector(double x, double y) { this->x = x; this->y = y; }
82  Vector(double array[2]) { x = array[0]; y = array[1]; }
83 
85  void operator +=(const Vector &v) { x += v.x; y += v.y; }
87  void operator -=(const Vector &v) { x -= v.x; y -= v.y; }
89  void operator *=(double f) { x *= f; y *= f; }
91  void operator /=(double f) { x /= f; y /= f; }
93  Vector operator +(const Vector &v) const { Vector n; n.x = x + v.x; n.y = y + v.y; return n; }
95  Vector operator -(const Vector &v) const { Vector n; n.x = x - v.x; n.y = y - v.y; return n; }
97  Vector operator /(double f) const { Vector n; n.x = x/f; n.y = y/f; return n; }
99  Vector operator *(double f) const { Vector n; n.x = x*f; n.y = y*f; return n; }
101  Vector operator -() const { return Vector(-x, -y); }
102 
104  double operator *(const Vector &v) const { return x*v.x + y*v.y; }
106  double norm(void) const { return sqrt(x*x + y*y); }
108  double norm2(void) const { return x*x+y*y; }
110  double cross(const Vector &v) const { return x * v.y - y * v.x; }
112  Vector unitary(void) const { if (norm() < std::numeric_limits<double>::epsilon()) return Vector(); return *this / norm(); }
114  double angle(void) const { return atan2(y, x); }
116  Vector perp(void) const { return Vector(-y, x); }
117 
119  Vector crossWithZVector(double l) const { return Vector(y * l, -x * l); }
121  Vector crossFromZVector(double l) const { return Vector(-y * l, x * l); }
122 
124  bool operator <(const Vector& that) const { if (this->x == that.x) return (this->y < that.y); else return (this->x < that.x); }
125  };
126 
128  std::ostream & operator << (std::ostream & outs, const Vector &vector);
129 
131 
132  typedef Vector Point;
133 
135 
142  struct Matrix22
143  {
144  // line-column component
146  double _11;
148  double _21;
150  double _12;
152  double _22;
153 
155  Matrix22() { _11 = _21 = _12 = _22 = 0; }
157  Matrix22(double _11, double _21, double _12, double _22) { this->_11 = _11; this->_21 = _21; this->_12 = _12; this->_22 = _22; }
159  Matrix22(double alpha) { _11 = cos(alpha); _21 = sin(alpha); _12 = -_21; _22 = _11; }
161  Matrix22(double array[4]) { _11=array[0]; _21=array[1]; _12=array[2]; _22=array[3]; }
162 
164  void zeros() { _11 = _21 = _12 = _22 = 0; }
165 
167  void operator +=(const Matrix22 &v) { _11 += v._11; _21 += v._21; _12 += v._12; _22 += v._22; }
169  void operator -=(const Matrix22 &v) { _11 -= v._11; _21 -= v._21; _12 -= v._12; _22 -= v._22; }
171  void operator *=(double f) { _11 *= f; _21 *= f; _12 *= f; _22 *= f; }
173  void operator /=(double f) { _11 /= f; _21 /= f; _12 /= f; _22 /= f; }
175  Matrix22 operator +(const Matrix22 &v) const { Matrix22 n; n._11 = _11 + v._11; n._21 = _21 + v._21; n._12 = _12 + v._12; n._22 = _22 + v._22; return n; }
177  Matrix22 operator -(const Matrix22 &v) const { Matrix22 n; n._11 = _11 - v._11; n._21 = _21 - v._21; n._12 = _12 - v._12; n._22 = _22 - v._22; return n; }
179  Matrix22 operator *(double f) const { Matrix22 n; n._11 = _11 * f; n._21 = _21 * f; n._12 = _12 * f; n._22 = _22 * f; return n; }
181  Matrix22 operator /(double f) const { Matrix22 n; n._11 = _11 / f; n._21 = _21 / f; n._12 = _12 / f; n._22 = _22 / f; return n; }
183  Matrix22 transpose() const { Matrix22 n; n._11 = _11; n._21 = _12; n._12 = _21; n._22 = _22; return n; }
184 
186  Point operator*(const Point &v) const { Point n; n.x = v.x*_11 + v.y*_12; n.y = v.x*_21 + v.y*_22; return n; }
187 
189  static Matrix22 fromDiag(double _1, double _2 ) { return Matrix22(_1, 0, 0, _2); }
191  static Matrix22 identity() { return fromDiag(1,1); }
192  };
193 
195 
196  struct Segment
197  {
199  Segment(double ax, double ay, double bx, double by) { this->a.x = ax; this->a.y = ay; this->b.x = bx; this->b.y = by; }
201  Segment(double array[4]) { a.x = array[0]; a.y = array[1]; b.x = array[2]; b.y = array[3]; }
203  Segment(const Point &p1, const Point &p2) { a = p1; b = p2; }
204 
206  Point a;
208  Point b;
209 
211  double dist(const Point &p) const
212  {
213  const Vector n(a.y-b.y, b.x-a.x);
214  const Vector u = n.unitary();
215  const Vector ap = p-a;
216  return ap * u;
217  }
218 
220  bool doesIntersect(const Segment &o) const
221  {
222  const double s2da = dist (o.a);
223  const double s2db = dist (o.b);
224  const double s1da = o.dist (a);
225  const double s1db = o.dist (b);
226  return (s2da*s2db<0) && (s1da*s1db<0);
227  }
228 
230  Point getMiddlePoint() const
231  {
232  return (a + b) / 2;
233  }
234  };
235 
237 
238  struct Polygone: public std::vector<Point>
239  {
241  Segment getSegment(size_t i) const
242  {
243  return Segment((*this)[i], (*this)[(i + 1) % size()]);
244  }
245 
247  bool isPointInside(const Point& p) const
248  {
249  for (size_t i = 0; i < size(); i++)
250  {
251  if (getSegment(i).dist(p) < 0)
252  return false;
253  }
254  return true;
255  }
256 
258  bool getAxisAlignedBoundingBox(Point& bottomLeft, Point& topRight) const
259  {
260  if (empty())
261  return false;
262 
263  bottomLeft = (*this)[0];
264  topRight = (*this)[0];
265 
266  extendAxisAlignedBoundingBox(bottomLeft, topRight);
267 
268  return true;
269  }
270 
272  void extendAxisAlignedBoundingBox(Point& bottomLeft, Point& topRight) const
273  {
274  for (const_iterator it = begin(); it != end(); ++it)
275  {
276  const Point& p = *it;
277 
278  if (p.x < bottomLeft.x)
279  bottomLeft.x = p.x;
280  else if (p.x > topRight.x)
281  topRight.x = p.x;
282 
283  if (p.y < bottomLeft.y)
284  bottomLeft.y = p.y;
285  else if (p.y > topRight.y)
286  topRight.y = p.y;
287  }
288  }
289 
291  double getBoundingRadius() const
292  {
293  double radius = 0;
294  for (size_t i = 0; i < size(); i++)
295  radius = std::max<double>(radius, (*this)[i].norm());
296  return radius;
297  }
298 
300  void translate(const Vector& delta)
301  {
302  for (iterator it = begin(); it != end(); ++it)
303  *it += delta;
304  }
305 
307  void translate(const double x, const double y)
308  {
309  translate(Vector(x,y));
310  }
311 
313  void rotate(const double angle)
314  {
315  Matrix22 rot(angle);
316  for (iterator it = begin(); it != end(); ++it)
317  *it = rot * (*it);
318  }
319 
321  void flipX()
322  {
323  for (size_t i = 0; i < size(); i++)
324  (*this)[i].x = -(*this)[i].x;
325  for (size_t i = 0; i < size() / 2; i++)
326  {
327  Point p = (*this)[i];
328  (*this)[i] = (*this)[size() - i - 1];
329  (*this)[size() - i - 1] = p;
330  }
331  }
332 
334  void flipY()
335  {
336  for (size_t i = 0; i < size(); i++)
337  (*this)[i].y = -(*this)[i].y;
338  for (size_t i = 0; i < size() / 2; i++)
339  {
340  Point p = (*this)[i];
341  (*this)[i] = (*this)[size() - i - 1];
342  (*this)[size() - i - 1] = p;
343  }
344  }
345 
347  Polygone& operator << (const Point& p) { push_back(p); return *this; }
348  };
349 
351 
352  std::ostream & operator << (std::ostream & outs, const Polygone &polygone);
353 
355 
356  inline double normalizeAngle(double angle)
357  {
358  while (angle > M_PI)
359  angle -= 2*M_PI;
360  while (angle < -M_PI)
361  angle += 2*M_PI;
362  return angle;
363  }
364 
365  #if 0
366  // NOTE: unused for now
368  inline double getTriangleArea(const Point &a, const Point &b, const Point &c)
369  {
370  return (a.x-c.x) * (b.y-c.y) - (a.y-c.y) * (b.x-c.x);
371  }
372  #endif
373 
377 
378  inline Point getIntersection(const Segment &s1, const Segment &s2)
379  {
380  // compute first segment's equation
381  const double c1 = s1.a.y + (-s1.a.x / (s1.b.x - s1.a.x)) * (s1.b.y - s1.a.y);
382  const double m1 = (s1.b.y - s1.a.y) / (s1.b.x - s1.a.x);
383 
384  // compute second segment's equation
385  const double c2 = s2.a.y + (-s2.a.x / (s2.b.x - s2.a.x)) * (s2.b.y - s2.a.y);
386  const double m2 = (s2.b.y - s2.a.y) / (s2.b.x - s2.a.x);
387 
388  // are the lines parallel ?
389  if (m1 == m2)
390  return Point(HUGE_VAL, HUGE_VAL);
391 
392  double x1 = s1.a.x;
393  double x2 = s1.b.x;
394  double x3 = s2.a.x;
395  double x4 = s2.b.x;
396  double y1 = s1.a.y;
397  double y2 = s1.b.y;
398  double y3 = s2.a.y;
399  double y4 = s2.b.y;
400 
401  // make sure x1 < x2
402  if (x1 > x2)
403  {
404  double temp = x1;
405  x1 = x2;
406  x2 = temp;
407  }
408 
409  // make sure x3 < x4
410  if (x3 > x4)
411  {
412  double temp = x3;
413  x3 = x4;
414  x4 = temp;
415  }
416 
417  // make sure y1 < y2
418  if (y1 > y2)
419  {
420  double temp = y1;
421  y1 = y2;
422  y2 = temp;
423  }
424 
425  // make sure y3 < y4
426  if (y3 > y4)
427  {
428  double temp = y3;
429  y3 = y4;
430  y4 = temp;
431  }
432 
433  // intersection point in case of infinite slopes
434  double x;
435  double y;
436 
437  // infinite slope m1
438  if (x1 == x2)
439  {
440  x = x1;
441  y = m2 * x1 + c2;
442  if (x > x3 && x < x4 && y > y1 && y <y2)
443  return Point(x, y);
444  else
445  return Point(HUGE_VAL, HUGE_VAL);
446  }
447 
448  // infinite slope m2
449  if (x3 == x4)
450  {
451  x = x3;
452  y = m1 * x3 + c1;
453  if (x > x1 && x < x2 && y > y3 && y < y4)
454  return Point(x, y);
455  else
456  return Point(HUGE_VAL, HUGE_VAL);
457  }
458 
459  // compute lines intersection point
460  x = (c2 - c1) / (m1 - m2);
461 
462  // see whether x in in both ranges [x1, x2] and [x3, x4]
463  if (x > x1 && x < x2 && x > x3 && x < x4)
464  return Point(x, m1 * x + c1);
465 
466  return Point(HUGE_VAL, HUGE_VAL);
467  }
468 
470 
475  inline double getTriangleAreaTwice(const Point &a, const Point &b, const Point &c)
476  {
477  return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x);
478  }
479 
481 
485  inline double getTriangleHeight(const Point &a, const Point &b, const Point &c)
486  {
487  const double ba_norm = (b-a).norm();
488  if (ba_norm < std::numeric_limits<double>::epsilon())
489  return 0;
490 
491  // area of the parallelogram divided by the length of the base
492  return getTriangleAreaTwice(a, b, c) / ba_norm;
493  }
494 }
495 
496 #endif
A vector in a 2D space.
Definition: Geometry.h:68
Point getMiddlePoint() const
Return the middle point.
Definition: Geometry.h:230
A 2x2 matrix.
Definition: Geometry.h:142
Matrix22(double array[4])
Constructor, create matrix with array[0] array[1] array[2] array[3].
Definition: Geometry.h:161
Vector Point
A point in a 2D space, another name for a vector.
Definition: Geometry.h:132
double _11
11 components
Definition: Geometry.h:146
static Matrix22 identity()
Create an identity matrix.
Definition: Geometry.h:191
double angle(void) const
Return the angle with the horizontal (arc tangant (y/x))
Definition: Geometry.h:114
Matrix22 transpose() const
Return the transpose of the matrix.
Definition: Geometry.h:183
std::ostream & operator<<(std::ostream &outs, const Vector &vector)
Print a vector to a stream.
Definition: Geometry.cpp:38
bool operator<(const Vector &that) const
Comparison operator.
Definition: Geometry.h:124
double y
y component
Definition: Geometry.h:73
static Matrix22 fromDiag(double _1, double _2)
Creates a diagonal matrix.
Definition: Geometry.h:189
void operator-=(const Vector &v)
Substract vector v component by component.
Definition: Geometry.h:87
Vector(double v)
Constructor, create vector with coordinates (v, v)
Definition: Geometry.h:78
Vector crossFromZVector(double l) const
Return the cross from (other x this) a (virtual, as we are in 2D) perpendicular vector (on axis z) of...
Definition: Geometry.h:121
void rotate(const double angle)
Rotate by a specific angle.
Definition: Geometry.h:313
Vector operator*(double f) const
Divive each component by scalar f and return the resulting vector.
Definition: Geometry.h:99
void operator*=(double f)
Multiply each component by scalar f.
Definition: Geometry.h:89
void translate(const Vector &delta)
Translate of a specific distance.
Definition: Geometry.h:300
Enki is the namespace of the Enki simulator. All Enki functions and classes excepted the math one are...
Definition: BluetoothBase.cpp:44
double getTriangleAreaTwice(const Point &a, const Point &b, const Point &c)
Returns 2 times the signed triangle area.
Definition: Geometry.h:475
bool isPointInside(const Point &p) const
Return true if p is inside this polygone.
Definition: Geometry.h:247
Matrix22()
Constructor, create matrix with 0.
Definition: Geometry.h:155
Vector crossWithZVector(double l) const
Return the cross with (this x other) a (virtual, as we are in 2D) perpendicular vector (on axis z) of...
Definition: Geometry.h:119
double cross(const Vector &v) const
Return the cross product with vector v.
Definition: Geometry.h:110
Segment(double array[4])
Constructor, create segment from point (array[0], array[1]) to point (array[2], array[3]) ...
Definition: Geometry.h:201
double norm2(void) const
Return the square norm of this vector (and thus avoid a square root)
Definition: Geometry.h:108
bool doesIntersect(const Segment &o) const
Return true if o intersect this segment.
Definition: Geometry.h:220
void extendAxisAlignedBoundingBox(Point &bottomLeft, Point &topRight) const
Extend an axis aligned bounding box with this object.
Definition: Geometry.h:272
Segment getSegment(size_t i) const
Return the i-th segment.
Definition: Geometry.h:241
Vector()
Constructor, create vector with coordinates (0, 0)
Definition: Geometry.h:76
void operator+=(const Vector &v)
Add vector v component by component.
Definition: Geometry.h:85
Point getIntersection(const Segment &s1, const Segment &s2)
get the intersection point between two line segments returns Point(HUGE_VAL, HUGE_VAL) if there&#39;s no ...
Definition: Geometry.h:378
void operator/=(double f)
Divive each component by scalar f.
Definition: Geometry.h:91
double getBoundingRadius() const
Return the bounding radius of this polygon.
Definition: Geometry.h:291
Vector operator+(const Vector &v) const
Add vector v component by component and return the resulting vector.
Definition: Geometry.h:93
double norm(void) const
Return the norm of this vector.
Definition: Geometry.h:106
Matrix22(double _11, double _21, double _12, double _22)
Constructor, create matrix with _11 _21 _12 _22.
Definition: Geometry.h:157
Vector unitary(void) const
Return a unitary vector of same direction.
Definition: Geometry.h:112
Matrix22(double alpha)
Constructor, create rotation matrix of angle alpha in radian.
Definition: Geometry.h:159
double x
x component
Definition: Geometry.h:71
double _22
22 components
Definition: Geometry.h:152
Vector operator-() const
Invert this vector.
Definition: Geometry.h:101
Segment(const Point &p1, const Point &p2)
Constructor, create segment from point p1 to point p2.
Definition: Geometry.h:203
Polygone, which is a vector of points. Anti-clockwise, standard trigonometric orientation.
Definition: Geometry.h:238
double getTriangleHeight(const Point &a, const Point &b, const Point &c)
Returns signed height of triangle abc with base ab.
Definition: Geometry.h:485
void flipX()
Flip coordinates on x.
Definition: Geometry.h:321
bool getAxisAlignedBoundingBox(Point &bottomLeft, Point &topRight) const
Get the axis aligned bounding box and return whether it exists.
Definition: Geometry.h:258
Vector operator/(double f) const
Multiply each component by scalar f and return the resulting vector.
Definition: Geometry.h:97
double _21
21 components
Definition: Geometry.h:148
Segment(double ax, double ay, double bx, double by)
Constructor, create segment from point (ax, ay) to point (bx, by)
Definition: Geometry.h:199
Vector perp(void) const
Return the perpendicular of the same norm in math. orientation (CCW)
Definition: Geometry.h:116
Vector(double array[2])
Constructor, create vector with coordinates (array[0], array[1])
Definition: Geometry.h:82
Vector(double x, double y)
Constructor, create vector with coordinates (x, y)
Definition: Geometry.h:80
Point operator*(const Point &v) const
Multiply vector v and return the resulting vector.
Definition: Geometry.h:186
void zeros()
Fill with zero.
Definition: Geometry.h:164
Point b
End point.
Definition: Geometry.h:208
A segment in a 2D space, basically two points.
Definition: Geometry.h:196
Point a
Start point.
Definition: Geometry.h:206
void flipY()
Flip coordinates on y.
Definition: Geometry.h:334
double _12
12 components
Definition: Geometry.h:150
void translate(const double x, const double y)
Translate of a specific distance, overload for convenience.
Definition: Geometry.h:307
double dist(const Point &p) const
Compute the distance of p to this segment.
Definition: Geometry.h:211
double normalizeAngle(double angle)
Normlize an angle to be between -PI and +PI.
Definition: Geometry.h:356