Main Page | Namespace List | Class List | File List | Namespace Members | Class Members | Related Pages

geom.hh

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; // Forward declaration for Line::Line(const LineRT &line)
00013 
00014 
00015 
00017   // Point
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   // Line
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); // Defined after the definition of LineRT
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       // Check if we have just a point, and process it
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       // Compute the line
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       // Process the points of the line
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   // LineRT
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   // Conversion functions
00447 
00448   // Documented above
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 /* GEOM_HH */

Generated on Sat Feb 26 22:54:39 2005 for GoCam by doxygen 1.3.4