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
00118 float angle() const { return atan2(y, x); }
00119
00123 float length() const { return sqrt(x * x + y * y); }
00124
00128 Point& normalize(float length = 1)
00129 {
00130 float len = this->length();
00131 x /= len;
00132 y /= len;
00133 return *this;
00134 }
00135
00137 float x, y;
00138 };
00139
00140
00141
00143
00144
00145
00147 struct Line {
00148
00150 Line() { }
00151
00156 Line(Point a, Point b) : a(a), b(b) { }
00157
00164 Line(float x1, float y1, float x2, float y2) : a(x1, y1), b(x2, y2) { }
00165
00172 Line(const LineRT &line);
00173
00178 void add(Point p, float scale = 1)
00179 {
00180 a.add(p, scale);
00181 b.add(p, scale);
00182 }
00183
00188 Point normal() const
00189 {
00190 return b.get_sub(a).rot90();
00191 }
00192
00197 Point tangent() const
00198 {
00199 return b.get_sub(a);
00200 }
00201
00206 Point intersection(const Line &line) const
00207 {
00208 Point line_normal = line.normal();
00209 Point tangent = this->tangent();
00210 float k = line.a.get_sub(a).dot(line_normal) / tangent.dot(line_normal);
00211 return a.get_add(tangent, k);
00212 }
00213
00223 Line& cut(const Line &line1, const Line &line2)
00224 {
00225 a = this->intersection(line1);
00226 b = this->intersection(line2);
00227 return *this;
00228 }
00229
00239 Line get_cut(const Line &line1, const Line &line2) const
00240 {
00241 return Line(this->intersection(line1), this->intersection(line2));
00242 }
00243
00248 Point closest(const Point &point) const
00249 {
00250 Line line(point, point.get_add(this->normal()));
00251 return this->intersection(line);
00252 }
00253
00254 Point a;
00255 Point b;
00256
00260 Point mirror(const Point &point) const
00261 {
00262 Point mirror_point = this->closest(point);
00263 return point.get_add(mirror_point.sub(point), 2);
00264 }
00265
00269 Line& mirror(const Line &mirror)
00270 {
00271 a = mirror.mirror(a);
00272 b = mirror.mirror(b);
00273 return *this;
00274 }
00275
00279 Line get_mirror(const Line &mirror) const
00280 {
00281 return Line(mirror.mirror(a), mirror.mirror(b));
00282 }
00283
00284
00297 template <typename T>
00298 T&
00299 map(T &obj)
00300 {
00301
00302 if ((int)(a.x + 0.5) == (int)(b.x + 0.5) &&
00303 (int)(a.y + 0.5) == (int)(b.y + 0.5))
00304 {
00305 obj((int)(a.x + 0.5), (int)(b.y + 0.5));
00306 return obj;
00307 }
00308
00309
00310 float dx = b.x - a.x;
00311 float dy = b.y - a.y;
00312 float div = util::max(util::abs(dx), util::abs(dy));
00313 dx /= div;
00314 dy /= div;
00315
00316
00317 for (int i = 0; i <= div; i++) {
00318 int x = (int)(a.x + i * dx + 0.5);
00319 int y = (int)(a.y + i * dy + 0.5);
00320 obj(x, y);
00321 }
00322
00323 return obj;
00324 }
00325
00326 };
00327
00328
00329
00331
00332
00333
00344 struct LineRT {
00345
00347 LineRT() : rho(0), theta(0) { }
00348
00353 LineRT(float rho, float theta) : rho(rho), theta(theta) { }
00354
00358 LineRT(const Line &line)
00359 {
00360 Point p = line.closest(Point(0, 0));
00361 rho = p.length();
00362 theta = p.angle();
00363 }
00364
00366 bool operator<(const LineRT &line) const
00367 {
00368 if (rho < line.rho)
00369 return true;
00370 return false;
00371 }
00372
00373 float rho;
00374 float theta;
00375 };
00376
00377
00378
00380 struct Grid {
00381
00386 Grid(int width, int height) : width(width), height(height),
00387 points(width * height) { }
00388
00401 Grid(const std::vector<Line> &lines1, const std::vector<Line> &lines2)
00402 : width(lines2.size()), height(lines1.size()), points(width * height)
00403 {
00404 for (int l1 = 0; l1 < (int)lines1.size(); l1++)
00405 for (int l2 = 0; l2 < (int)lines2.size(); l2++)
00406 (*this)(l2, l1) = lines1[l1].intersection(lines2[l2]);
00407 }
00408
00416 Point &operator()(int x, int y)
00417 {
00418 assert(x >= 0 && x < width);
00419 assert(y >= 0 && y < height);
00420 return points[y * width + x];
00421 }
00422
00429 Point &operator[](int index)
00430 {
00431 assert(index >= 0 && index < (int)points.size());
00432 return points[index];
00433 }
00434
00435
00436 int width;
00437 int height;
00438
00440 std::vector<Point> points;
00441 };
00442
00443
00444
00446
00447
00448
00449 inline
00450 Line::Line(const LineRT &line)
00451 {
00452 Point normal(cos(line.theta), sin(line.theta));
00453 a = normal.get_scale(line.rho);
00454 b = a.get_add(normal.get_rot90());
00455 }
00456
00461 inline
00462 float rad(float angle) { return angle / 180 * M_PI; }
00463
00468 inline
00469 float deg(float angle) { return angle * 180 / M_PI; }
00470 }
00471
00472 #endif