polygon.h
Go to the documentation of this file.
00001 
00059 /*
00060  * polygon.h
00061  *
00062  *  Created on: 14.06.2012
00063  *      Author: josh
00064  */
00065 
00066 #ifndef POLYGON_H_
00067 #define POLYGON_H_
00068 
00069 #include "sub_structures.h"
00070 #include <eigen3/Eigen/Dense>
00071 #include <unsupported/Eigen/NonLinearOptimization>
00072 #include <cob_3d_mapping_msgs/CurvedPolygon.h>
00073 #include <polypartition/polypartition.h>
00074 
00075 namespace Segmentation
00076 {
00077 
00078 #ifdef USE_BOOST_POLYGONS_
00079 #include <boost/polygon/polygon.hpp>
00080 #include <boost/geometry.hpp>
00081 #include <boost/geometry/geometries/geometries.hpp>
00082 #include <boost/geometry/multi/geometries/multi_polygon.hpp>
00083 #include <boost/geometry/algorithms/envelope.hpp>
00084 #include <boost/geometry/geometries/polygon.hpp>
00085 #include <boost/geometry/geometries/point_xy.hpp>
00086   using namespace boost::polygon::operators;
00087 
00088   typedef boost::polygon::polygon_with_holes_data<int> BoostPolygon;
00089   typedef BoostPolygon::point_type BoostPoint;
00090   typedef std::vector<BoostPolygon> BoostPolygonSet;
00091   typedef boost::polygon::polygon_90_set_traits<BoostPolygonSet> BoostTraits;
00092 #endif
00093 
00094   template<int Degree>
00095   struct S_POLYGON {
00096         enum {DEGREE=Degree};
00097         typedef SubStructure::Model<Degree> Model;
00098         
00099     std::vector<std::vector<Eigen::Vector3f> >  segments_;
00100     std::vector<std::vector<Eigen::Vector2i> >  segments2d_;
00101 #ifdef USE_BOOST_POLYGONS_
00102     std::vector<std::vector<BoostPoint> >       segments2d_;
00103 #endif
00104     float weight_; //number of points used for this model
00105 #ifdef CHECK_CONNECTIVITY
00106     S_POLYGON_CONNECTIVITY connectivity_;
00107 #endif
00108     SubStructure::Model<Degree> model_;
00109     Eigen::Vector3f middle_;
00110     int mark_;
00111 
00112     typename SubStructure::Param<Degree>::VectorU param_xy_;
00113     sensor_msgs::ImagePtr img_;
00114     float color_[3];
00115 
00116 #ifdef USE_CLASSIFICATION_
00117     Classification::Form::Ptr form_;
00118 #endif
00119 
00120     Eigen::Vector3f feature_;
00121 
00122     S_POLYGON()
00123 #ifdef USE_CLASSIFICATION_
00124     :form_(new Classification::Form)
00125 #endif
00126     {
00127       int color = rand();
00128       color_[0] = ((color>>0)&0xff)/255.f;
00129       color_[1] = ((color>>8)&0xff)/255.f;
00130       color_[2] = ((color>>16)&0xff)/255.f;
00131     }
00132 
00133     bool isLinear() const
00134     {
00135       for(size_t i=3; i<SubStructure::Param<Degree>::NUM; i++)
00136         if(std::abs(model_.p(i))>0.01f) return false;
00137       return true;
00138     }
00139 
00140     void buildForm(const bool debug=false) {
00141       if(segments_.size()<1)
00142         return;
00143 
00144       std::vector<Eigen::Vector3f> pts;
00145       for(size_t i=0; i<segments_[0].size(); i++)
00146       {
00147         Eigen::Vector3f v;
00148 #ifdef USE_BOOST_POLYGONS_
00149         v(0)=segments2d_[0][i].x();
00150         v(1)=segments2d_[0][i].y();
00151 #endif
00152         pts.push_back(v);
00153         //ROS_ERROR("%f %f",segments_[0][i](0),segments_[0][i](1));
00154       }
00155 
00156 #ifdef USE_CLASSIFICATION_
00157       Classification::Classification cl;
00158       Classification::QuadBB qbb;
00159 
00160       form_->curvature_ = getInvariantCurvature();
00161       cl.setPoints(segments_[0]);
00162       //cl.setPoints(pts);
00163 
00164       int mains[2];
00165       form_->n_=cl.buildLocalTree(debug,&qbb,&form_->compressed_energy_,mains);
00166       form_->outline_ = qbb.getOutline();
00167 
00168       feature_ = project2world(segments_[0][mains[0]].head<2>());
00169       feature_-= project2world(segments_[0][mains[1]].head<2>());
00170       //feature_.normalize();
00171 
00172       if(feature_(0)<0) feature_=-feature_;
00173 #endif
00174     }
00175 
00176     Eigen::Vector2f project2plane(const float x, const float y, const SubStructure::Model<Degree> &model) {
00177       ROS_ERROR("TODO:");
00178       Eigen::Vector2f mv;
00179       mv(0)=x;
00180       mv(1)=y;
00181       float mz;
00182       mz=model.intersect(mv(0), mv(1));
00183       //mv=mv*mz-getCenter();
00184       Eigen::Vector3f v;
00185       v.head<2>() = mz * mv;
00186       v(2) = mz;
00187       //mv(0) = (v-param_.col(0)).dot(proj2plane_.col(0))/proj2plane_.col(0).squaredNorm();
00188       //mv(1) = (v-param_.col(0)).dot(proj2plane_.col(1))/proj2plane_.col(1).squaredNorm();
00189       return mv;
00190     }
00191 
00192 #ifdef USE_BOOST_POLYGONS_
00193     BoostPolygonSet getBoostPolygon2D() const {
00194       //TODO: holes
00195       BoostPolygon poly;
00196       BoostPolygonSet r;
00197       if(segments2d_.size()==0) return r;
00198       poly.set(segments2d_[0].begin(), segments2d_[0].end());
00199       //poly.set_holes(segments2d_.begin(), segments2d_.end());
00200       r.push_back(poly);
00201       return r;
00202     }
00203 
00204     BoostPolygonSet getBoostPolygon2D_Centered() const {
00205       //TODO: holes
00206       BoostPolygon poly;
00207       BoostPolygonSet r;
00208       if(segments2d_.size()==0) return r;
00209       {
00210         poly.set(segments2d_[0].begin(), segments2d_[0].end());
00211         //poly.set_holes(segments2d_.begin(), segments2d_.end());
00212 
00213         BoostPoint cnt;
00214         boost::polygon::center(cnt,poly);
00215         std::vector<BoostPoint> temp;
00216 
00217         for(size_t i=0; i<segments2d_[0].size(); i++) {
00218           temp.push_back( BoostPoint(segments2d_[0][i].x()-cnt.x(), segments2d_[0][i].y()-cnt.y()));
00219         }
00220 
00221         poly.set(temp.begin(), temp.end());
00222 
00223         r.push_back(poly);
00224       }
00225       return r;
00226     }
00227 #endif
00228 
00229     Eigen::Vector3f project2plane(const float x, const float y, const float mz, const float b) {
00230       ROS_ERROR("TODO:");//TODO:
00231       return Eigen::Vector3f::Zero();
00232       /*Eigen::Vector2f mv;
00233       Eigen::Vector3f mv3;
00234       mv(0)=x;
00235       mv(1)=y;
00236       mv=mv*mz-getCenter();
00237       //mv(0)/=proj2plane_(0,0);
00238       //mv(1)/=proj2plane_(1,1);
00239 #if DEBUG_LEVEL >70
00240       if(!pcl_isfinite(mv(0))) {
00241         ROS_ERROR("mistXYZ");
00242         std::cerr<<x<<","<<y<<","<<mz<<"\nmv:\n";
00243         std::cerr<<mv<<"\np\n";
00244         std::cerr<<"mz: "<<mz<<"\nmv:\n";
00245         //getchar();
00246       }
00247 #endif
00248       mv3(2)=b;
00249       mv3(0)=mv(0);
00250       mv3(1)=mv(1);
00251       return mv3;*/
00252     }
00253 
00254     Eigen::Vector3f project2plane(const float x, const float y, const SubStructure::Model<Degree> &model, const float b) {
00255       Eigen::Vector2f mv;
00256       Eigen::Vector3f mv3;
00257       mv(0)=x;
00258       mv(1)=y;
00259       float mz;
00260       mz=model.intersect(mv(0), mv(1));
00261 
00262       mv3(0) = mv(0)*mz;
00263       mv3(1) = mv(1)*mz;
00264       mv3(2) = mz;
00265 
00266       return mv3;
00267     }
00268 
00269     /*Eigen::Vector2f getCenter() const {
00270       Eigen::Vector2f r;
00271       r(0)=param_(0,0);
00272       r(1)=param_(1,0);
00273       return r;
00274     }*/
00275 
00276     Eigen::Vector3f project2world(const Eigen::Vector2f &pt) const {
00277       Eigen::Vector3f v;
00278       v.head<2>() = pt;
00279       v(2) = model_.model(pt(0),pt(1));
00280       return v;
00281     }
00282   
00288    inline Eigen::Quaternionf get_orientation() const {
00289            Eigen::Vector2f mid, dir, mean; mid(0) = model_.x(); mid(1) = model_.y();
00290            mean(0) = model_.param.model_(0,1);
00291            mean(1) = model_.param.model_(0,2);
00292            Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> evd (model_.param.model_.block(1,1, 2,2)-mean*mean.transpose()/model_.param.model_(0,0));
00293            Eigen::Vector3f x = model_.getNormal(model_.x(), model_.y());
00294            dir(0) = evd.eigenvectors().col(1)(1);
00295            dir(1) = evd.eigenvectors().col(1)(0);
00296 
00297            Eigen::Vector3f y = project2world(0.1f*dir+mid)-project2world(mid);
00298            y.normalize();
00299            
00300            Eigen::Matrix3f M;
00301            M.col(0) = -x.cross(y).normalized();
00302            M.col(1) = y;
00303            M.col(2) = x;        //normal
00304            
00305            return Eigen::Quaternionf(M);
00306    }
00307 
00308     Eigen::Vector3f normalAt(const Eigen::Vector2f &v) const {
00309       return model_.getNormal(v(0),v(1));
00310     }
00311 
00312     /*float getFeature(Eigen::Vector2f &ra,Eigen::Vector2f &rb,Eigen::Vector3f &rc) const {
00313 
00314       rc=feature_;
00315 
00316       float a=param_(0,2), b=param_(1,2), c=param_(2,2);
00317 
00318       float x1 =  sqrtf((a-b)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00319       float x2 = -sqrtf((b-a)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00320       float y1=sqrtf(1-x1*x1);
00321       float y2=sqrtf(1-x2*x2);
00322 
00323       ra(0)=x1;
00324       ra(1)=y1;
00325 
00326       rb(0)=x2;
00327       rb(1)=y2;
00328 
00329       Eigen::Vector3f t=getInvariantCurvature();
00330 
00331       return std::max( std::abs(t(0)), std::max(std::abs(t(1)),std::abs(t(2))) );
00332     }
00333 
00334     Eigen::Vector3f getInvariantCurvature() const {
00335       Eigen::Vector3f r;
00336       float a=param_(0,2), b=param_(1,2), c=param_(2,2);
00337 
00338       float x1 =  sqrtf((a-b)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00339       float x2 = -sqrtf((b-a)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00340       float y1=sqrtf(1-x1*x1);
00341       float y2=sqrtf(1-x2*x2);
00342 
00343       r(0)=atanf( (a*x1*x1+b*y1*y1+c*x1*y1) /30.f);
00344       r(1)=atanf( (a*x2*x2+b*y2*y2+c*x2*y2) /30.f);
00345       r(2)=0.f;
00346 
00347       return r;
00348     }*/
00349 
00350     void update() {
00351       Eigen::Vector3f x,y;
00352       x(0)=1.f;
00353       y(1)=1.f;
00354       x(1)=x(2)=y(0)=y(2)=0.f;
00355     }
00356 
00357     void operator=(const SubStructure::Model<Degree> &model) {
00358       feature_.fill(0);
00359       param_xy_ = model.p;
00360       model_ = model;
00361       weight_ = model.param.model_(0,0);
00362 
00363       update();
00364 
00365       middle_(0) = model_.x();
00366       middle_(1) = model_.y();
00367       middle_(2) = model_.z();
00368 
00369       middle_ = project2world(nextPoint(middle_));
00370     }
00371 
00372     void print() {
00373       for(size_t j=0; j<segments_.size(); j++){
00374         std::cout<<"---------------\n";
00375         for(size_t i=0; i<segments_[j].size(); i++)
00376           std::cout<<segments_[j][i]<<"\n";
00377       }
00378     }
00379 
00380     void toRosMsg(cob_3d_mapping_msgs::CurvedPolygon *msg, const ros::Time &time) const
00381     {
00382       static int nextID = 0;
00383       msg->stamp = time;
00384       msg->ID = nextID++;
00385       msg->weight = model_.param.model_(0,0);
00386 
00387       for(int i=0; i<model_.p.rows(); i++)      //TODO: check
00388         msg->parameter[i] = model_.p(i);
00389 
00390       msg->polyline.clear();
00391       if(segments_.size()>0) {
00392         for(size_t i=0; i<segments_[0].size(); i++) {
00393           cob_3d_mapping_msgs::PolylinePoint pt;
00394           pt.x=segments_[0][i](0);
00395           pt.y=segments_[0][i](1);
00396           pt.edge_prob=segments_[0][i](2);
00397           msg->polyline.push_back(pt);
00398         }
00399       }
00400 
00401       cob_3d_mapping_msgs::Feature ft;
00402 
00403       //nearest point
00404       ft.ID = 1;
00405       Eigen::Vector3f nxtPt = project2world(nextPoint(Eigen::Vector3f::Zero()));
00406       ft.x=nxtPt(0);
00407       ft.y=nxtPt(1);
00408       ft.z=nxtPt(2);
00409       msg->features.push_back(ft);
00410 
00411       //feature from form
00412       ft.ID = 2;
00413       ft.x=feature_(0);
00414       ft.y=feature_(1);
00415       ft.z=feature_(2);
00416       msg->features.push_back(ft);
00417 
00418       //mid of outer hull
00419       ft.ID = 3;
00420       ft.x=middle_(0);
00421       ft.y=middle_(1);
00422       ft.z=middle_(2);
00423       msg->features.push_back(ft);
00424 
00425       Eigen::Vector2f ft1,ft2;
00426       Eigen::Vector3f ft3,n=model_.getNormal(middle_(0),middle_(1)),ft1p,ft2p;
00427       //getFeature(ft1,ft2,ft3);        //TODO:
00428 
00429       ft1p(0)=ft1(0);
00430       ft1p(1)=ft1(1);
00431       ft2p(0)=ft2(0);
00432       ft2p(1)=ft2(1);
00433       ft1p(2)=ft2p(2)=0.f;
00434 
00435       //curvature feature 1
00436       ft.ID = 4;
00437       ft3=ft1p.cross(n);
00438       ft.x = ft3(0);
00439       ft.y = ft3(1);
00440       ft.z = ft3(2);
00441       //if(pcl_isfinite(ft3.sum()))
00442       msg->features.push_back(ft);
00443 
00444       //curvature feature 2
00445       ft.ID = 5;
00446       ft3=ft2p.cross(n);
00447       ft.x = ft3(0);
00448       ft.y = ft3(1);
00449       ft.z = ft3(2);
00450       //if(pcl_isfinite(ft3.sum()))
00451       msg->features.push_back(ft);
00452 
00453     }
00454 
00455 
00457 //    Eigen::Vector2f _nextPoint(const Eigen::Vector3f &v, Eigen::Vector3f p, const int depth=0) const
00458 //    {
00459 //      if(depth>10)
00460 //      {
00461 //        return p.head<2>();
00462 //      }
00463 //
00464 //      //      std::cout<<"p\n"<<p<<"\n";
00465 //      p(2) = param_.col(2)(0)*p(0)*p(0)+param_.col(2)(1)*p(1)*p(1)+param_.col(2)(2)*p(0)*p(1)
00466 //                  + param_.col(1)(0)*p(0)+param_.col(1)(1)*p(1);
00467 //      //      std::cout<<"p\n"<<p<<"\n";
00468 //
00469 //      Eigen::Vector3f n;
00470 //      n(0) = -(param_.col(2)(0)*2*p(0)+param_.col(2)(2)*p(1)+param_.col(1)(0));
00471 //      n(1) = -(param_.col(2)(1)*2*p(1)+param_.col(2)(2)*p(0)+param_.col(1)(1));
00472 //      n(2) = 1;
00473 //
00474 //      Eigen::Vector3f d = ((p-v).dot(n)/n.squaredNorm()*n+(v-p));
00475 //
00476 //      //      std::cout<<"d\n"<<d<<"\n";
00477 //      //      std::cout<<"n\n"<<n<<"\n";
00478 //      //      std::cout<<"pv\n"<<(p-v)/(p-v)(2)<<"\n";
00479 //      //      std::cout<<"pv\n"<<(p-v)<<"\n";
00480 //      //      std::cout<<"dd\n"<<(p-v).dot(n)/n.squaredNorm()*n<<"\n";
00481 //      //ROS_ASSERT(std::abs(d(2))<=std::abs(z));
00482 //
00483 //      if(!pcl_isfinite(d.sum()) || d.head<2>().squaredNorm()<0.001f*0.001f)
00484 //      {
00485 //        //        std::cout<<"---------------\n";
00486 //        return (p+d).head<2>();
00487 //      }
00488 //      return _nextPoint(v,p+d,depth+1);
00489 //    }
00490 
00491     struct MyFunctor
00492     {
00493       const SubStructure::Model<Degree> &model;
00494       const float x0,y0,z0;
00495 
00496       int operator()(const Eigen::VectorXf &x, Eigen::VectorXf &fvec) const
00497       {
00498         // distance
00499         fvec(0) = std::pow(model.model(x(0),x(1))-z0,2)+std::pow(x(1)-y0,2)+std::pow(x(0)-x0,2);
00500         fvec(1) = 0;
00501 
00502         //        std::cout<<"fvec\n"<<fvec<<std::endl;
00503         return 0;
00504       }
00505 
00506       int df(const Eigen::VectorXf &x, Eigen::MatrixXf &fjac) const
00507       {
00508         //Jacobian
00509         const float delta = model.model(x(0),x(1))-z0;
00510         const Eigen::Vector3f n = model.getNormal_(x(0),x(1));
00511         fjac(0,0) = n(0)*delta+2*(x(0)-x0);
00512         fjac(0,1) = n(1)*delta+2*(x(1)-y0);
00513         fjac(1,0) = fjac(1,1) = 0;
00514         return 0;
00515       }
00516 
00517       int inputs() const { return 2; }
00518       int values() const { return 2; } // number of constraints
00519     };
00520 
00522     Eigen::Vector2f _nextPoint(const Eigen::Vector3f &v, Eigen::Vector3f p, const int depth=0) const
00523     {
00524       Eigen::VectorXf r(2);
00525       r = v.head<2>();
00526       MyFunctor functor={model_,
00527                          p(0),p(1),p(2)};
00528       Eigen::LevenbergMarquardt<MyFunctor, float> lm(functor);
00529       lm.parameters.maxfev = 50;
00530       lm.minimize(r);
00531 
00532       return r;
00533     }
00534 
00536     Eigen::Vector2f nextPoint(const Eigen::Vector3f &v) const
00537     {
00538       /*Eigen::Vector3f p, pos0 = project2world(v.head<2>()), n0 = normalAt(v.head<2>()), n0x, n0y;
00539 
00540       n0x = n0y = model_.getNormal_(v(0),v(1));
00541       n0x(1) = 0;
00542       n0y(0) = 0;
00543       n0x.normalize();
00544       n0y.normalize();
00545 
00546       p(0) = (v-pos0).dot(n0x);
00547       p(1) = (v-pos0).dot(n0y);
00548       p(2) = (v-pos0).dot(n0);*/
00549 
00550       Eigen::Vector2f r = _nextPoint(v, v);
00551 
00552       float e1 = (v-project2world(v.head<2>())).norm();
00553       float e2 = (v-project2world(r)).norm();
00554 
00555       if(e1<e2)
00556       {
00557         return v.head<2>();
00558       }
00559 
00560       return r;
00561     }
00562 
00563     bool getPose(Eigen::Matrix3f &P, Eigen::Vector3f &origin, float &h, float &w) const {
00564       if(segments_.size()<1)
00565         return false;
00566 
00567       Eigen::Matrix2f A, C;
00568       Eigen::Vector2f B, v1, v2;
00569 
00570       A(0,0) = model_.param.model_(1,1);
00571       A(1,1) = model_.param.model_(3,3);
00572       A(0,1) = A(1,0) = model_.param.model_(1,3); //TODO: fix
00573 
00574       B(0) = model_.param.model_(0,1);
00575       B(1) = model_.param.model_(0,3);
00576 
00577       C = A-C*C.transpose();
00578 
00579       Eigen::EigenSolver<Eigen::Matrix2f> es(C);
00580 
00581 //      std::cout<<"EV1\n"<<es.eigenvectors().col(0)<<"\n";
00582 //      std::cout<<"EV2\n"<<es.eigenvectors().col(1)<<"\n";
00583 
00584       v1 = es.eigenvectors().col(0).real();
00585       v2 = es.eigenvectors().col(1).real();
00586 
00587       v1.normalize();
00588       v2.normalize();
00589 
00590       P.col(0) = project2world(v1)-project2world(Eigen::Vector2f::Zero());
00591       P.col(1) = project2world(v2)-project2world(Eigen::Vector2f::Zero());
00592       P.col(0).normalize();
00593       P.col(1).normalize();
00594       P.col(2) = P.col(0).cross(P.col(1));
00595 
00596       float h_ma = -std::numeric_limits<float>::max(), h_mi = std::numeric_limits<float>::max();
00597       float w_ma = -std::numeric_limits<float>::max(), w_mi = std::numeric_limits<float>::max();
00598 
00599       for(size_t i=0; i<segments_[0].size(); i++)
00600       {
00601         float f=segments_[0][i].head<2>().dot(v1);
00602         h_ma = std::max(h_ma, f);
00603         h_mi = std::min(h_mi, f);
00604 
00605         f=segments_[0][i].head<2>().dot(v2);
00606         w_ma = std::max(w_ma, f);
00607         w_mi = std::min(w_mi, f);
00608       }
00609 
00610       origin = middle_;
00611       w = (project2world(v1*h_ma)-project2world(v1*h_mi)).norm();
00612       h = (project2world(v2*w_ma)-project2world(v2*w_mi)).norm();
00613 
00614 //      ROS_INFO("%f %f   %f %f", w, h_ma-h_mi, h, w_ma-w_mi);
00615 
00616       return true;
00617     }
00618 
00619     float area() const {
00620 
00621       TPPLPartition pp;
00622       list<TPPLPoly> polys,result;
00623 
00624       //std::cout << "id: " << new_message->id << std::endl;
00625       //std::cout << new_message->centroid << std::endl;
00626       //fill polys
00627       for(size_t i=0; i<segments_.size(); i++) {
00628         pcl::PointCloud<pcl::PointXYZ> pc;
00629         TPPLPoly poly;
00630 
00631         poly.Init(segments_[i].size());
00632         poly.SetHole(i!=0);
00633 
00634         for(size_t j=0; j<segments_[i].size(); j++) {
00635           poly[j].x = segments_[i][j](0);
00636           poly[j].y = segments_[i][j](1);
00637         }
00638         if(i!=0)
00639           poly.SetOrientation(TPPL_CW);
00640         else
00641           poly.SetOrientation(TPPL_CCW);
00642 
00643         polys.push_back(poly);
00644       }
00645 
00646       pp.Triangulate_EC(&polys,&result);
00647 
00648       TPPLPoint p1,p2,p3;
00649       Eigen::Vector3f v1,v2,v3;
00650 
00651       float a=0.f;
00652       for(std::list<TPPLPoly>::iterator it=result.begin(); it!=result.end(); it++) {
00653         if(it->GetNumPoints()!=3) continue;
00654 
00655         p1 = it->GetPoint(0);
00656         p2 = it->GetPoint(1);
00657         p3 = it->GetPoint(2);
00658 
00659         v1(0) = p1.x;
00660         v1(1) = p1.y;
00661         v2(0) = p2.x;
00662         v2(1) = p2.y;
00663         v3(0) = p3.x;
00664         v3(1) = p3.y;
00665 
00666         v1 = project2world(v1.head<2>());
00667         v2 = project2world(v2.head<2>());
00668         v3 = project2world(v3.head<2>());
00669 
00670         a += (v2-v1).cross(v3-v1).norm();
00671       }
00672 
00673       return a;
00674     }
00675 
00676   };
00677 
00678 #ifdef QPPF_SPECIALIZATION_2
00679   template< >
00680   struct S_POLYGON<2> {
00681     Eigen::Matrix3f param_;
00682     std::vector<std::vector<Eigen::Vector3f> >  segments_;
00683     std::vector<std::vector<Eigen::Vector2i> >  segments2d_;
00684 #ifdef USE_BOOST_POLYGONS_
00685     std::vector<std::vector<BoostPoint> >       segments2d_;
00686 #endif
00687     float weight_; //number of points used for this model
00688 #ifdef CHECK_CONNECTIVITY
00689     S_POLYGON_CONNECTIVITY connectivity_;
00690 #endif
00691     SubStructure::Model<2> model_;
00692     Eigen::Vector3f middle_;
00693     int mark_;
00694 
00695     Eigen::Matrix<float,3,2> proj2plane_;
00696     typename SubStructure::Param<2>::VectorU param_xy_;
00697     sensor_msgs::ImagePtr img_;
00698     float color_[3];
00699 
00700 #ifdef USE_CLASSIFICATION_
00701     Classification::Form::Ptr form_;
00702 #endif
00703 
00704     Eigen::Vector3f feature_;
00705 
00706     S_POLYGON()
00707 #ifdef USE_CLASSIFICATION_
00708     :form_(new Classification::Form)
00709 #endif
00710     {
00711       int color = rand();
00712       color_[0] = ((color>>0)&0xff)/255.f;
00713       color_[1] = ((color>>8)&0xff)/255.f;
00714       color_[2] = ((color>>16)&0xff)/255.f;
00715     }
00716 
00717     bool isLinear() const
00718     {
00719       std::cout<<model_.p<<"\n";
00720       return std::abs(model_.p(2))<0.01f && std::abs(model_.p(4))<0.01f && std::abs(model_.p(5))<0.01f;
00721     }
00722 
00723     void buildForm(const bool debug=false) {
00724       if(segments_.size()<1)
00725         return;
00726 
00727       std::vector<Eigen::Vector3f> pts;
00728       for(size_t i=0; i<segments_[0].size(); i++)
00729       {
00730         Eigen::Vector3f v;
00731 #ifdef USE_BOOST_POLYGONS_
00732         v(0)=segments2d_[0][i].x();
00733         v(1)=segments2d_[0][i].y();
00734 #endif
00735         pts.push_back(v);
00736         //ROS_ERROR("%f %f",segments_[0][i](0),segments_[0][i](1));
00737       }
00738 
00739 #ifdef USE_CLASSIFICATION_
00740       Classification::Classification cl;
00741       Classification::QuadBB qbb;
00742 
00743       form_->curvature_ = getInvariantCurvature();
00744       cl.setPoints(segments_[0]);
00745       //cl.setPoints(pts);
00746 
00747       int mains[2];
00748       form_->n_=cl.buildLocalTree(debug,&qbb,&form_->compressed_energy_,mains);
00749       form_->outline_ = qbb.getOutline();
00750 
00751       feature_ = project2world(segments_[0][mains[0]].head<2>());
00752       feature_-= project2world(segments_[0][mains[1]].head<2>());
00753       //feature_.normalize();
00754 
00755       if(feature_(0)<0) feature_=-feature_;
00756 #endif
00757     }
00758 
00759     Eigen::Vector2f project2plane(const float x, const float y, const SubStructure::Model<2> &model) {
00760       Eigen::Vector2f mv;
00761       mv(0)=x;
00762       mv(1)=y;
00763       float mz;
00764       mz=model.intersect(mv(0), mv(1));
00765       //mv=mv*mz-getCenter();
00766       Eigen::Vector3f v;
00767       v.head<2>() = mz * mv;
00768       v(2) = mz;
00769       mv(0) = (v-param_.col(0)).dot(proj2plane_.col(0))/proj2plane_.col(0).squaredNorm();
00770       mv(1) = (v-param_.col(0)).dot(proj2plane_.col(1))/proj2plane_.col(1).squaredNorm();
00771 #if DEBUG_LEVEL >70
00772       if(!pcl_isfinite(mv(0))) {
00773         ROS_ERROR("mist");
00774         std::cerr<<x<<","<<y<<","<<mz<<"\nmv:\n";
00775         std::cerr<<mv<<"\np\n";
00776         std::cerr<<model.p<<"\n";
00777         std::cerr<<"mz: "<<mz<<"\nmv:\n";
00778         //getchar();
00779       }
00780 #endif
00781       return mv;
00782     }
00783 
00784 #ifdef USE_BOOST_POLYGONS_
00785     BoostPolygonSet getBoostPolygon2D() const {
00786       //TODO: holes
00787       BoostPolygon poly;
00788       BoostPolygonSet r;
00789       if(segments2d_.size()==0) return r;
00790       poly.set(segments2d_[0].begin(), segments2d_[0].end());
00791       //poly.set_holes(segments2d_.begin(), segments2d_.end());
00792       r.push_back(poly);
00793       return r;
00794     }
00795 
00796     BoostPolygonSet getBoostPolygon2D_Centered() const {
00797       //TODO: holes
00798       BoostPolygon poly;
00799       BoostPolygonSet r;
00800       if(segments2d_.size()==0) return r;
00801       {
00802         poly.set(segments2d_[0].begin(), segments2d_[0].end());
00803         //poly.set_holes(segments2d_.begin(), segments2d_.end());
00804 
00805         BoostPoint cnt;
00806         boost::polygon::center(cnt,poly);
00807         std::vector<BoostPoint> temp;
00808 
00809         for(size_t i=0; i<segments2d_[0].size(); i++) {
00810           temp.push_back( BoostPoint(segments2d_[0][i].x()-cnt.x(), segments2d_[0][i].y()-cnt.y()));
00811         }
00812 
00813         poly.set(temp.begin(), temp.end());
00814 
00815         r.push_back(poly);
00816       }
00817       return r;
00818     }
00819 #endif
00820 
00821     Eigen::Vector3f project2plane(const float x, const float y, const float mz, const float b) {
00822       Eigen::Vector2f mv;
00823       Eigen::Vector3f mv3;
00824       mv(0)=x;
00825       mv(1)=y;
00826       mv=mv*mz-getCenter();
00827       //mv(0)/=proj2plane_(0,0);
00828       //mv(1)/=proj2plane_(1,1);
00829 #if DEBUG_LEVEL >70
00830       if(!pcl_isfinite(mv(0))) {
00831         ROS_ERROR("mistXYZ");
00832         std::cerr<<x<<","<<y<<","<<mz<<"\nmv:\n";
00833         std::cerr<<mv<<"\np\n";
00834         std::cerr<<"mz: "<<mz<<"\nmv:\n";
00835         //getchar();
00836       }
00837 #endif
00838       mv3(2)=b;
00839       mv3(0)=mv(0);
00840       mv3(1)=mv(1);
00841       return mv3;
00842     }
00843 
00844     Eigen::Vector3f project2plane(const float x, const float y, const SubStructure::Model<2> &model, const float b) {
00845       Eigen::Vector2f mv;
00846       Eigen::Vector3f mv3;
00847       mv(0)=x;
00848       mv(1)=y;
00849       mv3(2)=b;
00850       float mz;
00851       mz=model.intersect(mv(0), mv(1));
00852 
00853       //      Eigen::Vector3f v;
00854       //      v.head<2>() = mz * mv;
00855       //      v(2) = mz;
00856 
00857       mv=mv*mz-param_.col(0).head<2>();
00858       //      mv(0) = (v-param_.col(0)).dot(proj2plane_.col(0))/proj2plane_.col(0).squaredNorm();
00859       //      mv(1) = (v-param_.col(0)).dot(proj2plane_.col(1))/proj2plane_.col(1).squaredNorm();
00860 
00861       //      ROS_INFO("e %f %f", (v-project2world(mv)).norm(), model.model(mz*x,mz*y)-mz);
00862 
00863 #if DEBUG_LEVEL >70
00864       if(!pcl_isfinite(mv(0))) {
00865         ROS_ERROR("mist");
00866         std::cerr<<x<<","<<y<<","<<mz<<"\nmv:\n";
00867         std::cerr<<mv<<"\np\n";
00868         std::cerr<<model.p<<"\n";
00869         std::cerr<<"mz: "<<mz<<"\n";
00870         //getchar();
00871       }
00872 #endif
00873       mv3(0)=mv(0);
00874       mv3(1)=mv(1);
00875       return mv3;
00876     }
00877 
00878     Eigen::Vector2f getCenter() const {
00879       Eigen::Vector2f r;
00880       r(0)=param_(0,0);
00881       r(1)=param_(1,0);
00882       return r;
00883     }
00884 
00885     Eigen::Vector3f project2world(const Eigen::Vector2f &pt) const {
00886       Eigen::Vector3f pt2;
00887       pt2(0)=pt(0)*pt(0);
00888       pt2(1)=pt(1)*pt(1);
00889       pt2(2)=pt(0)*pt(1);
00890 
00891       return param_.col(0) + proj2plane_*pt + proj2plane_.col(0).cross(proj2plane_.col(1)) * (pt2.dot(param_.col(2)) + pt.dot(param_.col(1).head<2>()));
00892     }
00893 
00894     Eigen::Vector3f normalAt(const Eigen::Vector2f &v) const {
00895       Eigen::Vector3f r;
00896 
00897       r(0) = -(param_.col(1)(0) + 2*v(0)*param_.col(2)(0)+v(1)*param_.col(2)(2));
00898       r(1) = -(param_.col(1)(1) + 2*v(1)*param_.col(2)(1)+v(0)*param_.col(2)(2));
00899       r(2) = 1;
00900 
00901       r.normalize();
00902 
00903       Eigen::Matrix3f M;
00904       M.col(0) = proj2plane_.col(0);
00905       M.col(1) = proj2plane_.col(1);
00906       M.col(2) = proj2plane_.col(0).cross(proj2plane_.col(1));
00907 
00908       return M*r;
00909     }
00910 
00911     float getFeature(Eigen::Vector2f &ra,Eigen::Vector2f &rb,Eigen::Vector3f &rc) const {
00912 
00913       rc=feature_;
00914 
00915       float a=param_(0,2), b=param_(1,2), c=param_(2,2);
00916 
00917       float x1 =  sqrtf((a-b)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00918       float x2 = -sqrtf((b-a)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00919       float y1=sqrtf(1-x1*x1);
00920       float y2=sqrtf(1-x2*x2);
00921 
00922       ra(0)=x1;
00923       ra(1)=y1;
00924 
00925       rb(0)=x2;
00926       rb(1)=y2;
00927 
00928       Eigen::Vector3f t=getInvariantCurvature();
00929 
00930       return std::max( std::abs(t(0)), std::max(std::abs(t(1)),std::abs(t(2))) );
00931     }
00932 
00933     Eigen::Vector3f getInvariantCurvature() const {
00934       Eigen::Vector3f r;
00935       float a=param_(0,2), b=param_(1,2), c=param_(2,2);
00936 
00937       float x1 =  sqrtf((a-b)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00938       float x2 = -sqrtf((b-a)*sqrtf(c*c+b*b-2*a*b+a*a)+c*c+b*b-2*a*b+a*a)/(sqrtf(2)*sqrtf(c*c+b*b-2*a*b+a*a));
00939       float y1=sqrtf(1-x1*x1);
00940       float y2=sqrtf(1-x2*x2);
00941 
00942       r(0)=atanf( (a*x1*x1+b*y1*y1+c*x1*y1) /30.f);
00943       r(1)=atanf( (a*x2*x2+b*y2*y2+c*x2*y2) /30.f);
00944       r(2)=0.f;
00945 
00946       return r;
00947     }
00948 
00949     void update() {
00950       Eigen::Vector3f x,y;
00951       x(0)=1.f;
00952       y(1)=1.f;
00953       x(1)=x(2)=y(0)=y(2)=0.f;
00954 
00955       proj2plane_.col(0)=x;
00956       proj2plane_.col(1)=y;
00957 
00958       //proj2plane_.col(0)=param_.col(1).cross(y);
00959       //proj2plane_.col(1)=param_.col(1).cross(x);
00960 
00961       //param_.col(2)(0)*=proj2plane_(0,0)*proj2plane_(0,0);
00962       //param_.col(2)(1)*=proj2plane_(1,1)*proj2plane_(1,1);
00963       //param_.col(2)(2)*=proj2plane_(0,0)*proj2plane_(1,1);
00964     }
00965 
00966     void operator=(const SubStructure::Model<2> &model) {
00967       feature_.fill(0);
00968       param_xy_ = model.p;
00969       model_ = model;
00970 
00971       //      if(std::abs(model.p(5))<0.0001f) {
00972       //        param_.col(0)(0)=-model.p(1)/(2*model.p(2));
00973       //        param_.col(0)(1)=-model.p(3)/(2*model.p(4));
00974       //      }
00975       //      else {
00976       //        param_.col(0)(1)=
00977       //            ((2*model.p(2)*model.p(3))/model.p(5)-model.p(1)) /
00978       //            ( model.p(5)-(4*model.p(2)*model.p(4)/model.p(5)));
00979       //
00980       //        param_.col(0)(0)=-(model.p(1)+model.p(5)*param_.col(0)(1))/(2*model.p(2));
00981       //      }
00982       //
00983       //      if(!pcl_isfinite(param_.col(0)(0)))
00984       //        param_.col(0)(0)=0.f;
00985       //      if(!pcl_isfinite(param_.col(0)(1)))
00986       //        param_.col(0)(1)=0.f;
00987       //
00988       //      param_.col(0)(2)=model.model(param_.col(0)(0), param_.col(0)(1));
00989 
00990       param_.col(0) = Eigen::Vector3f::Zero();
00991       param_.col(0)(2) = model.p(0);
00992 
00993       param_.col(1)(0)=model.p(1);//-(model.p(1)+2*model.p(2)*param_.col(0)(0)+model.p(5)*param_.col(0)(1));
00994       param_.col(1)(1)=model.p(3);//-(model.p(3)+2*model.p(4)*param_.col(0)(1)+model.p(5)*param_.col(0)(0));
00995       param_.col(1)(2)=0;
00996       //      param_.col(1).normalize();
00997 
00998       param_.col(2)(0)=model.p(2);
00999       param_.col(2)(1)=model.p(4);
01000       param_.col(2)(2)=model.p(5);
01001 
01002       weight_ = model.param.model_(0,0);
01003 
01004       update();
01005 
01006       middle_(0) = model_.x();
01007       middle_(1) = model_.y();
01008       middle_(2) = model_.z();
01009 
01010       middle_ = project2world(nextPoint(middle_));
01011     }
01012 
01013     void print() {
01014       std::cout<<"parameter:\n"<<param_<<"\n";
01015       for(size_t j=0; j<segments_.size(); j++){
01016         std::cout<<"---------------\n";
01017         for(size_t i=0; i<segments_[j].size(); i++)
01018           std::cout<<segments_[j][i]<<"\n";
01019       }
01020     }
01021 
01022     void toRosMsg(cob_3d_mapping_msgs::CurvedPolygon *msg, const ros::Time &time) const
01023     {
01024       static int nextID = 0;
01025       msg->stamp = time;
01026       msg->ID = nextID++;
01027       msg->weight = model_.param.model_(0,0);
01028 
01029       for(int i=0; i<model_.p.rows(); i++)      //TODO: check
01030         msg->parameter[i] = model_.p(i);
01031 
01032       msg->polyline.clear();
01033       if(segments_.size()>0) {
01034         for(size_t i=0; i<segments_[0].size(); i++) {
01035           cob_3d_mapping_msgs::PolylinePoint pt;
01036           pt.x=segments_[0][i](0);
01037           pt.y=segments_[0][i](1);
01038           pt.edge_prob=segments_[0][i](2);
01039           msg->polyline.push_back(pt);
01040         }
01041       }
01042 
01043       cob_3d_mapping_msgs::Feature ft;
01044 
01045       //nearest point
01046       ft.ID = 1;
01047       Eigen::Vector3f nxtPt = project2world(nextPoint(Eigen::Vector3f::Zero()));
01048       ft.x=nxtPt(0);
01049       ft.y=nxtPt(1);
01050       ft.z=nxtPt(2);
01051       msg->features.push_back(ft);
01052 
01053       //feature from form
01054       ft.ID = 2;
01055       ft.x=feature_(0);
01056       ft.y=feature_(1);
01057       ft.z=feature_(2);
01058       msg->features.push_back(ft);
01059 
01060       //mid of outer hull
01061       ft.ID = 3;
01062       ft.x=middle_(0);
01063       ft.y=middle_(1);
01064       ft.z=middle_(2);
01065       msg->features.push_back(ft);
01066 
01067       Eigen::Vector2f ft1,ft2;
01068       Eigen::Vector3f ft3,n=model_.getNormal(middle_(0),middle_(1)),ft1p,ft2p;
01069       getFeature(ft1,ft2,ft3);
01070 
01071       ft1p(0)=ft1(0);
01072       ft1p(1)=ft1(1);
01073       ft2p(0)=ft2(0);
01074       ft2p(1)=ft2(1);
01075       ft1p(2)=ft2p(2)=0.f;
01076 
01077       //curvature feature 1
01078       ft.ID = 4;
01079       ft3=ft1p.cross(n);
01080       ft.x = ft3(0);
01081       ft.y = ft3(1);
01082       ft.z = ft3(2);
01083       //if(pcl_isfinite(ft3.sum()))
01084       msg->features.push_back(ft);
01085 
01086       //curvature feature 2
01087       ft.ID = 5;
01088       ft3=ft2p.cross(n);
01089       ft.x = ft3(0);
01090       ft.y = ft3(1);
01091       ft.z = ft3(2);
01092       //if(pcl_isfinite(ft3.sum()))
01093       msg->features.push_back(ft);
01094 
01095     }
01096 
01097 
01099 //    Eigen::Vector2f _nextPoint(const Eigen::Vector3f &v, Eigen::Vector3f p, const int depth=0) const
01100 //    {
01101 //      if(depth>10)
01102 //      {
01103 //        return p.head<2>();
01104 //      }
01105 //
01106 //      //      std::cout<<"p\n"<<p<<"\n";
01107 //      p(2) = param_.col(2)(0)*p(0)*p(0)+param_.col(2)(1)*p(1)*p(1)+param_.col(2)(2)*p(0)*p(1)
01108 //                  + param_.col(1)(0)*p(0)+param_.col(1)(1)*p(1);
01109 //      //      std::cout<<"p\n"<<p<<"\n";
01110 //
01111 //      Eigen::Vector3f n;
01112 //      n(0) = -(param_.col(2)(0)*2*p(0)+param_.col(2)(2)*p(1)+param_.col(1)(0));
01113 //      n(1) = -(param_.col(2)(1)*2*p(1)+param_.col(2)(2)*p(0)+param_.col(1)(1));
01114 //      n(2) = 1;
01115 //
01116 //      Eigen::Vector3f d = ((p-v).dot(n)/n.squaredNorm()*n+(v-p));
01117 //
01118 //      //      std::cout<<"d\n"<<d<<"\n";
01119 //      //      std::cout<<"n\n"<<n<<"\n";
01120 //      //      std::cout<<"pv\n"<<(p-v)/(p-v)(2)<<"\n";
01121 //      //      std::cout<<"pv\n"<<(p-v)<<"\n";
01122 //      //      std::cout<<"dd\n"<<(p-v).dot(n)/n.squaredNorm()*n<<"\n";
01123 //      //ROS_ASSERT(std::abs(d(2))<=std::abs(z));
01124 //
01125 //      if(!pcl_isfinite(d.sum()) || d.head<2>().squaredNorm()<0.001f*0.001f)
01126 //      {
01127 //        //        std::cout<<"---------------\n";
01128 //        return (p+d).head<2>();
01129 //      }
01130 //      return _nextPoint(v,p+d,depth+1);
01131 //    }
01132 
01133     struct MyFunctor
01134     {
01135       const float a,b,c, d,e;
01136       const float x0,y0,z0;
01137 
01138       int operator()(const Eigen::VectorXf &x, Eigen::VectorXf &fvec) const
01139       {
01140         // distance
01141         fvec(0) = std::pow((-z0+b*x(1)*x(1)+c*x(0)*x(1)+a*x(0)*x(0)+d*x(0)+e*x(1)),2)+std::pow(x(1)-y0,2)+std::pow(x(0)-x0,2);
01142         fvec(1) = 0;
01143 
01144         //        std::cout<<"fvec\n"<<fvec<<std::endl;
01145         return 0;
01146       }
01147 
01148       int df(const Eigen::VectorXf &x, Eigen::MatrixXf &fjac) const
01149       {
01150         //Jacobian
01151         //TODO:
01152         fjac(0,0) = 2*(c*x(1)+2*a*x(0)+d)*(-z0+b*x(1)*x(1)+c*x(0)*x(1)+a*x(0)*x(0)+d*x(0)+e*x(1))+2*(x(0)-x0);
01153         fjac(0,1) = 2*(2*b*x(1)+c*x(0)+e)*(-z0+b*x(1)*x(1)+c*x(0)*x(1)+a*x(0)*x(0)+d*x(0)+e*x(1))+2*(x(1)-y0);
01154         fjac(1,0) = fjac(1,1) = 0;
01155         return 0;
01156       }
01157 
01158       int inputs() const { return 2; }
01159       int values() const { return 2; } // number of constraints
01160     };
01161 
01163     Eigen::Vector2f _nextPoint(const Eigen::Vector3f &v, Eigen::Vector3f p, const int depth=0) const
01164     {
01165       Eigen::VectorXf r(2);
01166       r = v.head<2>();
01167       MyFunctor functor={param_.col(2)(0),param_.col(2)(1),param_.col(2)(2),
01168                          param_.col(1)(0),param_.col(1)(1),
01169                          p(0),p(1),p(2)};
01170       Eigen::LevenbergMarquardt<MyFunctor, float> lm(functor);
01171       lm.parameters.maxfev = 50;
01172       lm.minimize(r);
01173 
01174       return r;
01175     }
01176 
01178     Eigen::Vector2f nextPoint(const Eigen::Vector3f &v) const
01179     {
01180       Eigen::Vector3f p;
01181 
01182       p(0) = (v-param_.col(0)).dot(proj2plane_.col(0));
01183       p(1) = (v-param_.col(0)).dot(proj2plane_.col(1));
01184       p(2) = (v-param_.col(0)).dot(proj2plane_.col(0).cross(proj2plane_.col(1)));
01185 
01186       Eigen::Vector2f r = _nextPoint(p, p);
01187 
01188       float e1 = (v-project2world(p.head<2>())).norm();
01189       float e2 = (v-project2world(r)).norm();
01190 
01191       if(e1<e2)
01192       {
01193         return p.head<2>();
01194       }
01195 
01196       return r;
01197     }
01198 
01199     bool getPose(Eigen::Matrix3f &P, Eigen::Vector3f &origin, float &h, float &w) const {
01200       if(segments_.size()<1)
01201         return false;
01202 
01203       Eigen::Matrix2f A, C;
01204       Eigen::Vector2f B, v1, v2;
01205 
01206       A(0,0) = model_.param.model_(1,1);
01207       A(1,1) = model_.param.model_(3,3);
01208       A(0,1) = A(1,0) = model_.param.model_(1,3); //TODO: fix
01209 
01210       B(0) = model_.param.model_(0,1);
01211       B(1) = model_.param.model_(0,3);
01212 
01213       C = A-C*C.transpose();
01214 
01215       Eigen::EigenSolver<Eigen::Matrix2f> es(C);
01216 
01217 //      std::cout<<"EV1\n"<<es.eigenvectors().col(0)<<"\n";
01218 //      std::cout<<"EV2\n"<<es.eigenvectors().col(1)<<"\n";
01219 
01220       v1 = es.eigenvectors().col(0).real();
01221       v2 = es.eigenvectors().col(1).real();
01222 
01223       v1.normalize();
01224       v2.normalize();
01225 
01226       P.col(0) = project2world(v1)-project2world(Eigen::Vector2f::Zero());
01227       P.col(1) = project2world(v2)-project2world(Eigen::Vector2f::Zero());
01228       P.col(0).normalize();
01229       P.col(1).normalize();
01230       P.col(2) = P.col(0).cross(P.col(1));
01231 
01232       float h_ma = -std::numeric_limits<float>::max(), h_mi = std::numeric_limits<float>::max();
01233       float w_ma = -std::numeric_limits<float>::max(), w_mi = std::numeric_limits<float>::max();
01234 
01235       for(size_t i=0; i<segments_[0].size(); i++)
01236       {
01237         float f=segments_[0][i].head<2>().dot(v1);
01238         h_ma = std::max(h_ma, f);
01239         h_mi = std::min(h_mi, f);
01240 
01241         f=segments_[0][i].head<2>().dot(v2);
01242         w_ma = std::max(w_ma, f);
01243         w_mi = std::min(w_mi, f);
01244       }
01245 
01246       origin = middle_;
01247       w = (project2world(v1*h_ma)-project2world(v1*h_mi)).norm();
01248       h = (project2world(v2*w_ma)-project2world(v2*w_mi)).norm();
01249 
01250 //      ROS_INFO("%f %f   %f %f", w, h_ma-h_mi, h, w_ma-w_mi);
01251 
01252       return true;
01253     }
01254 
01255     float area() const {
01256 
01257       TPPLPartition pp;
01258       list<TPPLPoly> polys,result;
01259 
01260       //std::cout << "id: " << new_message->id << std::endl;
01261       //std::cout << new_message->centroid << std::endl;
01262       //fill polys
01263       for(size_t i=0; i<segments_.size(); i++) {
01264         pcl::PointCloud<pcl::PointXYZ> pc;
01265         TPPLPoly poly;
01266 
01267         poly.Init(segments_[i].size());
01268         poly.SetHole(i!=0);
01269 
01270         for(size_t j=0; j<segments_[i].size(); j++) {
01271           poly[j].x = segments_[i][j](0);
01272           poly[j].y = segments_[i][j](1);
01273         }
01274         if(i!=0)
01275           poly.SetOrientation(TPPL_CW);
01276         else
01277           poly.SetOrientation(TPPL_CCW);
01278 
01279         polys.push_back(poly);
01280       }
01281 
01282       pp.Triangulate_EC(&polys,&result);
01283 
01284       TPPLPoint p1,p2,p3;
01285       Eigen::Vector3f v1,v2,v3;
01286 
01287       float a=0.f;
01288       for(std::list<TPPLPoly>::iterator it=result.begin(); it!=result.end(); it++) {
01289         if(it->GetNumPoints()!=3) continue;
01290 
01291         p1 = it->GetPoint(0);
01292         p2 = it->GetPoint(1);
01293         p3 = it->GetPoint(2);
01294 
01295         v1(0) = p1.x;
01296         v1(1) = p1.y;
01297         v2(0) = p2.x;
01298         v2(1) = p2.y;
01299         v3(0) = p3.x;
01300         v3(1) = p3.y;
01301 
01302         v1 = project2world(v1.head<2>());
01303         v2 = project2world(v2.head<2>());
01304         v3 = project2world(v3.head<2>());
01305 
01306         a += (v2-v1).cross(v3-v1).norm();
01307       }
01308 
01309       return a;
01310     }
01311 
01312   };
01313 #endif
01314 }
01315 
01316 #endif /* POLYGON_H_ */
01317 


cob_3d_segmentation
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:03:03