00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef __ENKI_GEOMETRY_H
00035 #define __ENKI_GEOMETRY_H
00036
00037 #ifdef WIN32
00038 #define _USE_MATH_DEFINES
00039 #define NOMINMAX
00040 #endif
00041 #include <cmath>
00042 #include <vector>
00043 #include <limits>
00044 #include <ostream>
00045 #include <algorithm>
00046
00047 #ifdef _MSC_VER
00048 #define round(x) floor((x) + 0.5)
00049 #endif
00050
00055 namespace Enki
00056 {
00058
00065 struct Vector
00066 {
00068 double x;
00070 double y;
00071
00073 Vector() { x = y = 0; }
00075 Vector(double v) { this->x = v; this->y = v; }
00077 Vector(double x, double y) { this->x = x; this->y = y; }
00079 Vector(double array[2]) { x = array[0]; y = array[1]; }
00080
00082 void operator +=(const Vector &v) { x += v.x; y += v.y; }
00084 void operator -=(const Vector &v) { x -= v.x; y -= v.y; }
00086 void operator *=(double f) { x *= f; y *= f; }
00088 void operator /=(double f) { x /= f; y /= f; }
00090 Vector operator +(const Vector &v) const { Vector n; n.x = x + v.x; n.y = y + v.y; return n; }
00092 Vector operator -(const Vector &v) const { Vector n; n.x = x - v.x; n.y = y - v.y; return n; }
00094 Vector operator /(double f) const { Vector n; n.x = x/f; n.y = y/f; return n; }
00096 Vector operator *(double f) const { Vector n; n.x = x*f; n.y = y*f; return n; }
00098 Vector operator -() const { return Vector(-x, -y); }
00099
00101 double operator *(const Vector &v) const { return x*v.x + y*v.y; }
00103 double norm(void) const { return sqrt(x*x + y*y); }
00105 double norm2(void) const { return x*x+y*y; }
00107 double cross(const Vector &v) const { return x * v.y - y * v.x; }
00109 Vector unitary(void) const { if (norm() < std::numeric_limits<double>::epsilon()) return Vector(); return *this / norm(); }
00111 double angle(void) const { return atan2(y, x); }
00113 Vector perp(void) const { return Vector(-y, x); }
00114
00116 Vector crossWithZVector(double l) const { return Vector(y * l, -x * l); }
00118 Vector crossFromZVector(double l) const { return Vector(-y * l, x * l); }
00119
00121 bool operator <(const Vector& that) const { if (this->x == that.x) return (this->y < that.y); else return (this->x < that.x); }
00122 };
00123
00125 std::ostream & operator << (std::ostream & outs, const Vector &vector);
00126
00128
00129 typedef Vector Point;
00130
00132
00139 struct Matrix22
00140 {
00141
00143 double _11;
00145 double _21;
00147 double _12;
00149 double _22;
00150
00152 Matrix22() { _11 = _21 = _12 = _22 = 0; }
00154 Matrix22(double _11, double _21, double _12, double _22) { this->_11 = _11; this->_21 = _21; this->_12 = _12; this->_22 = _22; }
00156 Matrix22(double alpha) { _11 = cos(alpha); _21 = sin(alpha); _12 = -_21; _22 = _11; }
00158 Matrix22(double array[4]) { _11=array[0]; _21=array[1]; _12=array[2]; _22=array[3]; }
00159
00161 void zeros() { _11 = _21 = _12 = _22 = 0; }
00162
00164 void operator +=(const Matrix22 &v) { _11 += v._11; _21 += v._21; _12 += v._12; _22 += v._22; }
00166 void operator -=(const Matrix22 &v) { _11 -= v._11; _21 -= v._21; _12 -= v._12; _22 -= v._22; }
00168 void operator *=(double f) { _11 *= f; _21 *= f; _12 *= f; _22 *= f; }
00170 void operator /=(double f) { _11 /= f; _21 /= f; _12 /= f; _22 /= f; }
00172 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; }
00174 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; }
00176 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; }
00178 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; }
00179
00181 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; }
00182
00184 static Matrix22 fromDiag(double _1, double _2 ) { return Matrix22(_1, 0, 0, _2); }
00185 };
00186
00188
00189 struct Segment
00190 {
00192 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; }
00194 Segment(double array[4]) { a.x = array[0]; a.y = array[1]; b.x = array[2]; b.y = array[3]; }
00196 Segment(const Point &p1, const Point &p2) { a = p1; b = p2; }
00197
00199 Point a;
00201 Point b;
00202
00204 double dist(const Point &p) const
00205 {
00206 const Vector n(a.y-b.y, b.x-a.x);
00207 const Vector u = n.unitary();
00208 const Vector ap = p-a;
00209 return ap * u;
00210 }
00211
00213 bool doesIntersect(const Segment &o) const
00214 {
00215 const double s2da = dist (o.a);
00216 const double s2db = dist (o.b);
00217 const double s1da = o.dist (a);
00218 const double s1db = o.dist (b);
00219 return (s2da*s2db<0) && (s1da*s1db<0);
00220 }
00221 };
00222
00224
00225 struct Polygone: public std::vector<Point>
00226 {
00228 bool isPointInside(const Point& p) const
00229 {
00230 for (size_t i = 0; i < size(); i++)
00231 {
00232 Segment s((*this)[i], (*this)[(i + 1) % size()]);
00233 if (s.dist(p) < 0)
00234 return false;
00235 }
00236 return true;
00237 }
00238
00240 bool getAxisAlignedBoundingBox(Point& bottomLeft, Point& topRight) const
00241 {
00242 if (empty())
00243 return false;
00244
00245 bottomLeft = (*this)[0];
00246 topRight = (*this)[0];
00247
00248 extendAxisAlignedBoundingBox(bottomLeft, topRight);
00249
00250 return true;
00251 }
00252
00254 void extendAxisAlignedBoundingBox(Point& bottomLeft, Point& topRight) const
00255 {
00256 for (const_iterator it = begin(); it != end(); ++it)
00257 {
00258 const Point& p = *it;
00259
00260 if (p.x < bottomLeft.x)
00261 bottomLeft.x = p.x;
00262 else if (p.x > topRight.x)
00263 topRight.x = p.x;
00264
00265 if (p.y < bottomLeft.y)
00266 bottomLeft.y = p.y;
00267 else if (p.y > topRight.y)
00268 topRight.y = p.y;
00269 }
00270 }
00271
00273 double getBoundingRadius() const
00274 {
00275 double radius = 0;
00276 for (size_t i = 0; i < size(); i++)
00277 radius = std::max<double>(radius, (*this)[i].norm());
00278 return radius;
00279 }
00280
00282 void translate(const Vector& delta)
00283 {
00284 for (iterator it = begin(); it != end(); ++it)
00285 *it += delta;
00286 }
00287
00289 void translate(const double& x, const double& y)
00290 {
00291 translate(Vector(x,y));
00292 }
00293
00295 void rotate(double angle)
00296 {
00297 Matrix22 rot(angle);
00298 for (iterator it = begin(); it != end(); ++it)
00299 *it = rot * (*it);
00300 }
00301
00303 void flipX()
00304 {
00305 for (size_t i = 0; i < size(); i++)
00306 (*this)[i].x = -(*this)[i].x;
00307 for (size_t i = 0; i < size() / 2; i++)
00308 {
00309 Point p = (*this)[i];
00310 (*this)[i] = (*this)[size() - i - 1];
00311 (*this)[size() - i - 1] = p;
00312 }
00313 }
00314
00316 void flipY()
00317 {
00318 for (size_t i = 0; i < size(); i++)
00319 (*this)[i].y = -(*this)[i].y;
00320 for (size_t i = 0; i < size() / 2; i++)
00321 {
00322 Point p = (*this)[i];
00323 (*this)[i] = (*this)[size() - i - 1];
00324 (*this)[size() - i - 1] = p;
00325 }
00326 }
00327
00329 Polygone& operator << (const Point& p) { push_back(p); return *this; }
00330 };
00331
00333 std::ostream & operator << (std::ostream & outs, const Polygone &polygone);
00334
00336
00337 inline double normalizeAngle(double angle)
00338 {
00339 while (angle > M_PI)
00340 angle -= 2*M_PI;
00341 while (angle < -M_PI)
00342 angle += 2*M_PI;
00343 return angle;
00344 }
00345
00349
00350 inline Point getIntersection(const Segment &s1, const Segment &s2)
00351 {
00352
00353 const double c1 = s1.a.y + (-s1.a.x / (s1.b.x - s1.a.x)) * (s1.b.y - s1.a.y);
00354 const double m1 = (s1.b.y - s1.a.y) / (s1.b.x - s1.a.x);
00355
00356
00357 const double c2 = s2.a.y + (-s2.a.x / (s2.b.x - s2.a.x)) * (s2.b.y - s2.a.y);
00358 const double m2 = (s2.b.y - s2.a.y) / (s2.b.x - s2.a.x);
00359
00360
00361 if (m1 == m2)
00362 return Point(HUGE_VAL, HUGE_VAL);
00363
00364 double x1 = s1.a.x;
00365 double x2 = s1.b.x;
00366 double x3 = s2.a.x;
00367 double x4 = s2.b.x;
00368 double y1 = s1.a.y;
00369 double y2 = s1.b.y;
00370 double y3 = s2.a.y;
00371 double y4 = s2.b.y;
00372
00373
00374 if (x1 > x2)
00375 {
00376 double temp = x1;
00377 x1 = x2;
00378 x2 = temp;
00379 }
00380
00381
00382 if (x3 > x4)
00383 {
00384 double temp = x3;
00385 x3 = x4;
00386 x4 = temp;
00387 }
00388
00389
00390 if (y1 > y2)
00391 {
00392 double temp = y1;
00393 y1 = y2;
00394 y2 = temp;
00395 }
00396
00397
00398 if (y3 > y4)
00399 {
00400 double temp = y3;
00401 y3 = y4;
00402 y4 = temp;
00403 }
00404
00405
00406 double x;
00407 double y;
00408
00409
00410 if (x1 == x2)
00411 {
00412 x = x1;
00413 y = m2 * x1 + c2;
00414 if (x > x3 && x < x4 && y > y1 && y <y2)
00415 return Point(x, y);
00416 else
00417 return Point(HUGE_VAL, HUGE_VAL);
00418 }
00419
00420
00421 if (x3 == x4)
00422 {
00423 x = x3;
00424 y = m1 * x3 + c1;
00425 if (x > x1 && x < x2 && y > y3 && y < y4)
00426 return Point(x, y);
00427 else
00428 return Point(HUGE_VAL, HUGE_VAL);
00429 }
00430
00431
00432 x = (c2 - c1) / (m1 - m2);
00433
00434
00435 if (x > x1 && x < x2 && x > x3 && x < x4)
00436 return Point(x, m1 * x + c1);
00437
00438 return Point(HUGE_VAL, HUGE_VAL);
00439 }
00440 }
00441
00442 #endif