00001 #ifndef GEOM_HH
00002 #define GEOM_HH
00003
00004 #include <math.h>
00005 #include <vector>
00006 #include <assert.h>
00007 #include "util.hh"
00008
00010 namespace geom {
00011
00012 class LineRT;
00013
00014
00015
00017
00018
00019
00021 struct Point {
00022
00024 Point() : x(0), y(0) { }
00025
00030 Point(float x, float y) : x(x), y(y) { }
00031
00033 Point& rot90()
00034 {
00035 *this = Point(y, -x);
00036 return *this;
00037 }
00038
00042 Point get_rot90() const
00043 {
00044 return Point(y, -x);
00045 }
00046
00051 float dot(const Point &p) const { return x * p.x + y * p.y; }
00052
00057 Point& add(const Point &p, float scale = 1)
00058 {
00059 x += scale * p.x;
00060 y += scale * p.y;
00061 return *this;
00062 }
00063
00068 Point get_add(const Point &p, float scale = 1) const
00069 {
00070 return Point(x + scale * p.x, y + scale * p.y);
00071 }
00072
00077 Point& sub(const Point &p, float scale = 1)
00078 {
00079 x -= scale * p.x;
00080 y -= scale * p.y;
00081 return *this;
00082 }
00083
00088 Point get_sub(const Point &p, float scale = 1) const
00089 {
00090 return Point(x - scale * p.x, y - scale * p.y);
00091 }
00092
00096 Point& scale(float scale)
00097 {
00098 x *= scale;
00099 y *= scale;
00100 return *this;
00101 }
00102
00106 Point get_scale(float scale)
00107 {
00108 return Point(x * scale, y * scale);
00109 }
00110
00114 Point& mean(Point point)
00115 {
00116 add(point).scale(0.5);
00117 return *this;
00118 }
00119
00123 Point get_mean(Point point)
00124 {
00125 return get_add(point).get_scale(0.5);
00126 }
00127
00135 float angle() const { return atan2(y, x); }
00136
00140 float length() const { return sqrt(x * x + y * y); }
00141
00145 Point& normalize(float length = 1)
00146 {
00147 float len = this->length();
00148 x /= len;
00149 y /= len;
00150 return *this;
00151 }
00152
00154 float x, y;
00155 };
00156
00157
00158
00160
00161
00162
00164 struct Line {
00165
00167 Line() { }
00168
00173 Line(Point a, Point b) : a(a), b(b) { }
00174
00181 Line(float x1, float y1, float x2, float y2) : a(x1, y1), b(x2, y2) { }
00182
00189 Line(const LineRT &line);
00190
00195 void add(Point p, float scale = 1)
00196 {
00197 a.add(p, scale);
00198 b.add(p, scale);
00199 }
00200
00202 float length() const
00203 {
00204 return b.get_sub(a).length();
00205 }
00206
00211 Point normal() const
00212 {
00213 return b.get_sub(a).rot90();
00214 }
00215
00220 Point tangent() const
00221 {
00222 return b.get_sub(a);
00223 }
00224
00229 Point intersection(const Line &line) const
00230 {
00231 Point line_normal = line.normal();
00232 Point tangent = this->tangent();
00233 float k = line.a.get_sub(a).dot(line_normal) / tangent.dot(line_normal);
00234 return a.get_add(tangent, k);
00235 }
00236
00246 Line& cut(const Line &line1, const Line &line2)
00247 {
00248 a = this->intersection(line1);
00249 b = this->intersection(line2);
00250 return *this;
00251 }
00252
00262 Line get_cut(const Line &line1, const Line &line2) const
00263 {
00264 return Line(this->intersection(line1), this->intersection(line2));
00265 }
00266
00271 Point closest(const Point &point) const
00272 {
00273 Line line(point, point.get_add(this->normal()));
00274 return this->intersection(line);
00275 }
00276
00277 Point a;
00278 Point b;
00279
00284 Point mirror(const Point &point, float scale = 1) const
00285 {
00286 Point mirror_point = this->closest(point);
00287 return point.get_add(mirror_point.sub(point), 1 + scale);
00288 }
00289
00294 Line& mirror(const Line &mirror, float scale = 1)
00295 {
00296 a = mirror.mirror(a, scale);
00297 b = mirror.mirror(b, scale);
00298 return *this;
00299 }
00300
00304 Line get_mirror(const Line &mirror) const
00305 {
00306 return Line(mirror.mirror(a), mirror.mirror(b));
00307 }
00308
00309
00322 template <typename T>
00323 T&
00324 map(T &obj)
00325 {
00326
00327 if ((int)(a.x + 0.5) == (int)(b.x + 0.5) &&
00328 (int)(a.y + 0.5) == (int)(b.y + 0.5))
00329 {
00330 obj((int)(a.x + 0.5), (int)(b.y + 0.5));
00331 return obj;
00332 }
00333
00334
00335 float dx = b.x - a.x;
00336 float dy = b.y - a.y;
00337 float div = util::max(util::abs(dx), util::abs(dy));
00338 dx /= div;
00339 dy /= div;
00340
00341
00342 for (int i = 0; i <= div; i++) {
00343 int x = (int)(a.x + i * dx + 0.5);
00344 int y = (int)(a.y + i * dy + 0.5);
00345 obj(x, y);
00346 }
00347
00348 return obj;
00349 }
00350
00351 };
00352
00353
00354
00356
00357
00358
00369 struct LineRT {
00370
00372 LineRT() : rho(0), theta(0) { }
00373
00378 LineRT(float rho, float theta) : rho(rho), theta(theta) { }
00379
00383 LineRT(const Line &line)
00384 {
00385 Point p = line.closest(Point(0, 0));
00386 rho = p.length();
00387 theta = p.angle();
00388 }
00389
00391 bool operator<(const LineRT &line) const
00392 {
00393 if (rho < line.rho)
00394 return true;
00395 return false;
00396 }
00397
00398 float rho;
00399 float theta;
00400 };
00401
00402
00403
00405 struct Grid {
00406
00411 Grid(int width, int height) : width(width), height(height),
00412 points(width * height) { }
00413
00426 Grid(const std::vector<Line> &lines1, const std::vector<Line> &lines2)
00427 : width(lines2.size()), height(lines1.size()), points(width * height)
00428 {
00429 for (int l1 = 0; l1 < (int)lines1.size(); l1++)
00430 for (int l2 = 0; l2 < (int)lines2.size(); l2++)
00431 (*this)(l2, l1) = lines1[l1].intersection(lines2[l2]);
00432 }
00433
00441 Point &operator()(int x, int y)
00442 {
00443 assert(x >= 0 && x < width);
00444 assert(y >= 0 && y < height);
00445 return points[y * width + x];
00446 }
00447
00454 Point &operator[](int index)
00455 {
00456 assert(index >= 0 && index < (int)points.size());
00457 return points[index];
00458 }
00459
00460
00461 int width;
00462 int height;
00463
00465 std::vector<Point> points;
00466 };
00467
00473 inline
00474 Point
00475 mean(Point p1, Point p2, float weight = 0.5)
00476 {
00477 p2.sub(p1);
00478 return p1.add(p2, 1.0 - weight);
00479 }
00480
00482
00483
00484
00485 inline
00486 Line::Line(const LineRT &line)
00487 {
00488 Point normal(cos(line.theta), sin(line.theta));
00489 a = normal.get_scale(line.rho);
00490 b = a.get_add(normal.get_rot90());
00491 }
00492
00497 inline
00498 float rad(float angle) { return angle / 180 * M_PI; }
00499
00504 inline
00505 float deg(float angle) { return angle * 180 / M_PI; }
00506 }
00507
00508 #endif