minimal_rectangle_2d.h
Go to the documentation of this file.
00001 
00063 #ifndef MINIMAL_RECTANGLE_2D_H__
00064 #define MINIMAL_RECTANGLE_2D_H__
00065 
00066 #include <Eigen/StdVector>
00067 #include <Eigen/Core>
00068 #include <iostream>
00069 
00070 namespace cob_3d_mapping
00071 {
00076   class MinimalRectangle2D
00077   {
00078     private:
00079     typedef Eigen::Vector2f PT;
00080 
00081     class Line
00082     {
00083       public:
00084       Line(int point, const PT& dir)
00085         : idx(point)
00086         , direction(dir)
00087         , stop(false)
00088       { }
00089 
00090       float getDot(const std::vector<PT>& edges)
00091       { return fabs(direction.dot(edges[idx])); }
00092 
00093       void rotate(const std::vector<PT>& edges)
00094       {
00095         direction = edges[idx];
00096         ++idx;
00097         if( idx >= edges.size() ) idx = 0;
00098         stop = true;
00099         next->makeOrthogonalTo(direction);
00100       }
00101 
00102       void makeOrthogonalTo(const PT& dir)
00103       {
00104         if (stop) { stop = false; return; }
00105         direction[0] = dir[1];
00106         direction[1] = -dir[0];
00107         next->makeOrthogonalTo(direction);
00108       }
00109 
00110       int idx;
00111       PT direction;
00112       bool stop;
00113       Line* next;
00114     };
00115 
00116     public:
00117     MinimalRectangle2D() { }
00118 
00119     /* set input, convex hull is required, will be copied to local lists of edges and vertices to
00120      * save some computation */
00121     template<typename T> void setConvexHull(const T& hull)
00122     {
00123       vertices.push_back(PT(hull[0].x, hull[0].y));
00124       PT tmp;
00125       for(int i=1; i<hull.size(); ++i)
00126       {
00127         tmp = PT(hull[i].x - hull[i-1].x, hull[i].y - hull[i-1].y);
00128         edges.push_back(tmp.normalized());
00129         vertices.push_back(PT(hull[i].x, hull[i].y));
00130       }
00131       tmp = PT(hull[0].x - hull[hull.size()-1].x, hull[0].y - hull[hull.size()-1].y);
00132       edges.push_back(tmp.normalized());
00133     }
00134 
00135     /* set input, convex hull is required, will be copied to local lists of edges and vertices to
00136      * save some computation */
00137     template<typename T> void setConvexHullList(const T& hull)
00138     {
00139       vertices.push_back(PT(hull[0][0], hull[0][1]));
00140       PT tmp;
00141       for(int i=1; i<hull.size(); ++i)
00142       {
00143         tmp = PT(hull[i][0] - hull[i-1][0], hull[i][1] - hull[i-1][1]);
00144         edges.push_back(tmp.normalized());
00145         vertices.push_back(PT(hull[i][0], hull[i][1]));
00146       }
00147       tmp = PT(hull[0][0] - hull[hull.size()-1][0], hull[0][1] - hull[hull.size()-1][1]);
00148       edges.push_back(tmp.normalized());
00149     }
00150 
00151     inline Line* minAngle(Line* lhs, Line* rhs)
00152     { return ( lhs->getDot(edges) < rhs->getDot(edges) ? rhs : lhs ); }
00153 
00154     inline Line* minAngle(Line* i, Line* j, Line* k, Line* l)
00155     { return minAngle( minAngle(i,j), minAngle(k,l) ); }
00156 
00157     inline void getIntersection(const Line& l1, const Line& l2, PT& point)
00158     { point = (vertices[l2.idx] - vertices[l1.idx]).dot(l1.direction) * l1.direction + vertices[l1.idx]; }
00159 
00160     // cross product: (p1-p2) x (p3-p2)
00161     inline float computeArea(const PT& p1, const PT& p2, const PT& p3)
00162     { return fabs( ((p1[0]-p2[0]) * (p3[1]-p2[1])) - ((p3[0]-p2[0]) * (p1[1]-p2[1])) ); }
00163 
00164     void rotatingCalipers(PT& origin, PT& ccw, PT& cw)
00165     {
00166       float xmin = std::numeric_limits<float>::max();
00167       float ymax = - std::numeric_limits<float>::max();
00168       float xmax = - std::numeric_limits<float>::max();
00169       float ymin = std::numeric_limits<float>::max();
00170       float amin = std::numeric_limits<float>::max();
00171 
00172       int i, j, k, l;
00173       for (int it=0; it<vertices.size(); ++it)
00174       {
00175         if     (vertices[it][0] < xmin) { xmin = vertices[it][0]; i = it; }
00176         else if(vertices[it][0] > xmax) { xmax = vertices[it][0]; k = it; }
00177         if     (vertices[it][1] < ymin) { ymin = vertices[it][1]; l = it; }
00178         else if(vertices[it][1] > ymax) { ymax = vertices[it][1]; j = it; }
00179       }
00180 
00181       // create inital rectangle parallel to xy-axis
00182       Line vi(i, PT(0,1)); // min x, parallel to y-axis
00183       Line vj(j, PT(1,0)); // max y, parallel to x-axis
00184       Line vk(k, PT(0,-1)); // max x, parallel to y-axis
00185       Line vl(l, PT(-1,0)); // min y, parallel to x-axis
00186       vi.next = &vj;
00187       vj.next = &vk;
00188       vk.next = &vl;
00189       vl.next = &vi;
00190 
00191       PT ref(0,1);
00192       // the rectangle keeps rotating clock-wise until vi is parallel to x-axis
00193       while(vi.direction.dot(ref) > 0)
00194       {
00195         Line* ls = minAngle(&vi, &vj, &vk, &vl); // get the new supporting line
00196         ls->rotate(edges); // rotate line and move one point forward
00197         /*
00198         std::cout << "i: " << vertices[vi.idx][0] <<"," << vertices[vi.idx][1] << std::endl;
00199         std::cout << "j: " << vertices[vj.idx][0] <<"," << vertices[vj.idx][1] << std::endl;
00200         std::cout << "k: " << vertices[vk.idx][0] <<"," << vertices[vk.idx][1] << std::endl;
00201         std::cout << "l: " << vertices[vl.idx][0] <<"," << vertices[vl.idx][1] << std::endl;
00202         */
00203         PT p1, p2, p3; // p1 -> p2 -> p3
00204         getIntersection(vl, vi, p1);
00205         getIntersection(vi, vj, p2);
00206         getIntersection(vj, vk, p3);
00207         float area = computeArea(p1, p2, p3);
00208         /*std::cout << "l-i: " << p1(0) <<","<<p1(1)<<std::endl;
00209         std::cout << "i-j: " << p2(0) <<","<<p2(1)<<std::endl;
00210         std::cout << "j-k: " << p3(0) <<","<<p3(1)<<std::endl;
00211         std::cout << area << std::endl;*/
00212         if (area < amin)
00213         {
00214           amin = area;
00215           origin = p2;
00216           ccw = p1;
00217           cw = p3;
00218         }
00219       }
00220     }
00221 
00222     private:
00223     std::vector<PT> edges;
00224     std::vector<PT> vertices;
00225   };
00226 }
00227 
00228 #endif // MINIMAL_RECTANGLE_2D_H__


cob_3d_mapping_common
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:02:19