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 
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   // Line
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); // Defined after the definition of LineRT
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       // Check if we have just a point, and process it
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       // Compute the line
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       // Process the points of the line
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   // LineRT
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   // Conversion functions
00483 
00484   // Documented above
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 /* GEOM_HH */

Generated on Tue Apr 8 09:58:19 2008 for GoCam by  doxygen 1.4.6