topology.h
Go to the documentation of this file.
00001 /*
00002  * trispline.h
00003  *
00004  *  Created on: 25.10.2012
00005  *      Author: josh
00006  */
00007 
00008 #ifndef TOPOLGY_H_
00009 #define TOPOLGY_H_
00010 
00011 #define CGAL_DISABLE_ROUNDING_MATH_CHECK
00012 
00013 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
00014 #include <CGAL/Cartesian.h>
00015 #include <CGAL/Homogeneous_d.h>
00016 #include <CGAL/leda_integer.h>
00017 #include <CGAL/Delaunay_triangulation_2.h>
00018 #include <CGAL/Triangulation_vertex_base_with_info_2.h>
00019 #include <CGAL/Triangulation_face_base_with_info_2.h>
00020 
00021 #include <unsupported/Eigen/NonLinearOptimization>
00022 #include <eigen3/Eigen/Jacobi>
00023 
00024 #include <cob_3d_mapping_slam/marker/marker_container.h>
00025 
00026 namespace ParametricSurface {
00027 
00028   class Topology
00029   {
00030   public:
00031 
00032     class POINT;
00033 
00034   private:
00035 
00036 #if 0
00037     /* A vertex class with an additionnal handle */
00038     template < class Gt, class Vb = CGAL::Triangulation_vertex_base_2<Gt> >
00039     class Vertex_base_with_ptr
00040     : public  Vb
00041       {
00042       typedef Vb                              Base;
00043       public:
00044       typedef typename Vb::Vertex_handle      Vertex_handle;
00045       typedef typename Vb::Face_handle        Face_handle;
00046       typedef typename Vb::Point              Point;
00047 
00048       template < typename TDS2 >
00049       struct Rebind_TDS {
00050         typedef typename Vb::template Rebind_TDS<TDS2>::Other    Vb2;
00051         typedef My_vertex_base<Gt,Vb2>                           Other;
00052       };
00053 
00054       private:
00055       boost::shared_ptr<POINT>  va_;
00056 
00057       public:
00058       Vertex_base_with_ptr() : Base() {}
00059       Vertex_base_with_ptr(const Point & p) : Base(p) {}
00060       Vertex_base_with_ptr(const Point & p, Face_handle f) : Base(f,p) {}
00061       Vertex_base_with_ptr(Face_handle f) : Base(f) {}
00062 
00063       void set_associated_point(const boost::shared_ptr<POINT> &va) { va_ = va;}
00064       boost::shared_ptr<POINT> get_associated_point() {return va_ ; }
00065       };
00066 #endif
00067     //typedef leda_integer RT;
00068     typedef float RT;
00069     //typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
00070     typedef CGAL::Cartesian<float>                               Kernel;
00071     //typedef CGAL::Homogeneous_d<double>                               Kernel;
00072 
00073     typedef CGAL::Triangulation_vertex_base_with_info_2<boost::shared_ptr<POINT>, Kernel>    Vb;
00074     typedef CGAL::Triangulation_face_base_with_info_2<boost::shared_ptr<ParametricSurface::TriSpline2_Fade>, Kernel>    Vbb;
00075     typedef CGAL::Triangulation_data_structure_2<Vb, Vbb>                    Tds;
00076 
00077     typedef CGAL::Delaunay_triangulation_2<Kernel, Tds> Delaunay_d;
00078     typedef Delaunay_d::Point Point;
00079     typedef Kernel::Vector_2 Vector;
00080     typedef Delaunay_d::Vertex Vertex;
00081     typedef Delaunay_d::Face Face;
00082     typedef Delaunay_d::Face_handle Face_handle;
00083     typedef Delaunay_d::Face_iterator Face_iterator;
00084     typedef Delaunay_d::All_edges_iterator Edge_iterator;
00085 
00086     //typedef Delaunay_d::Simplex_handle Simplex_handle;
00087     //typedef Delaunay_d::Simplex_const_iterator Simplex_const_iterator;
00088     //typedef Delaunay_d::Point_const_iterator Point_const_iterator;
00089     //typedef Delaunay_d::Simplex_iterator Simplex_iterator;
00090     typedef Delaunay_d::Vertex_handle Vertex_handle;
00091     typedef Delaunay_d::Face_circulator Face_circulator;
00092     typedef Delaunay_d::Vertex_circulator Vertex_circulator;
00093     typedef Delaunay_d::Vertex_iterator Vertex_iterator;
00094 
00095     public:
00096 
00097     struct  POINT {
00098       Eigen::Vector2f uv;
00099       Eigen::Vector3f pt, n, n2;
00100       Vertex_handle vh;
00101       float weight_;
00102 
00103       POINT(): weight_(1) {}
00104 
00105       void transform(const Eigen::Matrix3f &rot, const Eigen::Vector3f &tr) {
00106         pt = rot*pt + tr;
00107         n  = rot*n;
00108         n2 = rot*n2;
00109       }
00110     };
00111 
00112 
00113     private:
00114 
00115     Delaunay_d del_;
00116     std::vector< boost::shared_ptr<POINT> > pts_;
00117     std::vector< boost::shared_ptr<ParametricSurface::TriSpline2_Fade> > tris_;
00118     //    std::map< Vertex*, boost::shared_ptr<POINT> > map_pts_;
00119     //    std::map< Face*, boost::shared_ptr<ParametricSurface::TriSpline2_Fade> > map_tris_;
00120     float thr_;
00121 
00122     bool isOnBorder(const boost::shared_ptr<POINT> &pt) const {
00123       if(pts_.size()<=3)
00124         return true;
00125 #if 0
00126       //1. if its part of border -> don't delete (for now)
00127       //      std::cout<<"addr1 "<<pt.get()<<"\n";
00128       //      std::cout<<"addr2 "<<&*pt->vh<<"\n";
00129       //Face_handle fh = pt->vh->face();
00130       Face_circulator fc = pt->vh->incident_faces();
00131       if (fc != 0) {
00132         int n=0;
00133         bool b1=false, b2=false;
00134         Vector p;
00135         do {
00136           Vertex_handle v1 = fc->vertex(0), v2 = fc->vertex(1);
00137           if(v1==pt->vh) v1 = fc->vertex(2);
00138           if(v2==pt->vh) v2 = fc->vertex(2);
00139 
00140           //          std::cout<<"p1\n"<<v1->point()<<"\n";
00141           //          std::cout<<"p2\n"<<v2->point()<<"\n";
00142 
00143           if(!n) {
00144             p = v1->point()-pt->vh->point();
00145           }
00146           float f;
00147           Vector v;
00148 
00149           v = v1->point()-pt->vh->point();
00150           if( v.x()*p.x()+v.y()*p.y()<=0 ) {
00151             f = v.x()*p.y()-v.y()*p.x();
00152             if(f>0) b1=true; else if(f<0) b2=true;
00153 
00154             //            std::cout<<"b "<<b1<<" "<<b2<<"\n";
00155             //            std::cout<<"f2 "<<f<<"\n";
00156           }
00157 
00158           v = v2->point()-pt->vh->point();
00159           if( v.x()*p.x()+v.y()*p.y()<=0 ) {
00160             f = v.x()*p.y()-v.y()*p.x();
00161             if(f>0) b1=true; else if(f<0) b2=true;
00162 
00163             //            std::cout<<"b "<<b1<<" "<<b2<<"\n";
00164             //            std::cout<<"f2 "<<f<<"\n";
00165           }
00166 
00167           if(b1&&b2) break;
00168           ++n;
00169         } while (++fc != pt->vh->incident_faces());
00170 
00171         if(!b1||!b2) return true;
00172       }
00173       else
00174         return true;
00175 #else
00176       Vertex_circulator start = del_.incident_vertices(del_.infinite_vertex());
00177       Vertex_circulator vc(start);
00178       do {
00179 //        std::cout<<"border check "<<(pt->vh->point()==vc->point())<<"\n";
00180         if(pt->vh->point()==vc->point())
00181           return true;
00182       } while( (++vc)!=start);
00183 #endif
00184       return false;
00185     }
00186 
00187     bool canRemove(const boost::shared_ptr<POINT> &pt) const {
00188       //2. get PCA of \delta of each edge connecting vertex
00189       //   -> if smallest eigen value less than threshold
00190       //   -> delete
00191       Eigen::Matrix3f V = Eigen::Matrix3f::Zero();
00192 
00193       Face_circulator fc = pt->vh->incident_faces();
00194       float n=0;
00195       do {
00196         //ROS_ASSERT(map_tris_.find(&*fc)!=map_tris_.end());
00197 
00198         if( fc->info() ) { //TODO: check why this is needed
00199           Eigen::Matrix3f delta = fc->info()->delta();
00200           for(int i=0; i<3; i++)
00201             V+=delta.col(i)*delta.col(i).transpose() / (fc->info()->getEdge(i)-fc->info()->getEdge((i+1)%3)).squaredNorm();
00202           n+=3.f;
00203         }
00204       } while (++fc != pt->vh->incident_faces());
00205 
00206       Eigen::JacobiSVD<Eigen::Matrix3f> svd (V, Eigen::ComputeFullU | Eigen::ComputeFullV);
00207 //      std::cout<<"SVD\n"<<svd.singularValues()<<"\n";
00208 
00209       return
00210           //std::min(std::min(std::abs(svd.singularValues()(0)),std::abs(svd.singularValues()(1))),std::abs(svd.singularValues()(2)))
00211           std::abs(svd.singularValues()(2))
00212       <thr_*n;
00213     }
00214 
00215     void removePoint(const size_t i) {
00216       //map_pts_.erase(&*pts_[i]->vh);
00217       ROS_ASSERT(pts_[i]->vh->info()==*(pts_.begin()+i));
00218 //      ROS_ASSERT( !del_.test_dim_down(pts_[i]->vh) );
00219       del_.remove(pts_[i]->vh);
00220 
00221 //      std::list<Edge> hole;
00222 //      del_.make_hole(v, hole);
00223 //      del_.fill_hole_delaunay(hole);
00224 //      del_.delete_vertex(v);
00225 
00226       pts_.erase(pts_.begin()+i);
00227     }
00228 
00229     // for LM
00230     struct Functor {
00231       Eigen::Vector3f pt_;
00232       const Topology &top_;
00233       ParametricSurface::TriSpline2_Fade *last_;
00234 
00235       Functor(const Topology &t, const Eigen::Vector3f &pt):pt_(pt), top_(t), last_(NULL)
00236       {}
00237 
00238       ParametricSurface::TriSpline2_Fade *getLast() const {return last_;}
00239 
00240       void init(Eigen::VectorXf &x) {
00241         last_ = top_.locate(x);
00242 
00243         Eigen::Vector3f delta = ((*last_)((Eigen::Vector2f)x)-pt_);
00244         Eigen::Matrix<float,3,2> M = last_->normal(x);
00245 
00246 //        std::cout<<"start\n"<<x<<"\n"<<M<<"\n";
00247 //        std::cout<<"a "<<-M.col(0).dot( delta )<<"\n";
00248 //        std::cout<<"b "<<-M.col(1).dot( delta )<<"\n";
00249 
00250         Eigen::VectorXf x2 = x;
00251         x2(0) -= M.col(0).dot( delta );
00252         x2(1) -= M.col(1).dot( delta );
00253 
00254         if(last_->inside(x2))
00255           x = x2;
00256       }
00257 
00258       int operator()(const Eigen::VectorXf &x, Eigen::VectorXf &fvec) const
00259       {
00260         // distance
00261         if(!last_->inside(x))
00262           ((Functor*)this)->last_ = top_.locate(x);
00263         ParametricSurface::TriSpline2_Fade *l = top_.locate(x);
00264         fvec(0) = (pt_ - (*l)((Eigen::Vector2f)x)).squaredNorm();
00265         fvec(1) = 0;
00266 
00267 //        std::cout<<"x\n"<<x<<"\n";
00268 //        std::cout<<"dist "<<fvec(0)<<"\n";
00269         return 0;
00270       }
00271 
00272       int df(const Eigen::VectorXf &x, Eigen::MatrixXf &fjac) const
00273       {
00274         //Jacobian
00275 #if 0
00276         Eigen::Matrix4f p = top_.normalAtUV(x);
00277 
00278         Eigen::Vector3f vx, vy;
00279         vx = p.col(3).head<3>().cross(p.col(1).head<3>()).cross(p.col(3).head<3>());
00280         vy = p.col(3).head<3>().cross(p.col(2).head<3>()).cross(p.col(3).head<3>());
00281 
00282         vx.normalize();
00283         vy.normalize();
00284 
00285         Eigen::Matrix3f M;
00286         M.col(0) = vx;
00287         M.col(1) = -vy;
00288         M.col(2) = p.col(3).head<3>();
00289 
00290         fjac.row(0) = 2*(M.inverse()*(p.col(0).head<3>()-pt_)).head<2>();
00291 
00292         std::cout<<"o1 "<<vx.dot(p.col(0).head<3>()-pt_)<<"\n";
00293         std::cout<<"o2 "<<vx.dot(p.col(1).head<3>()-pt_)<<"\n";
00294         std::cout<<"p\n"<<p<<"\n";
00295 #else
00296         if(!last_->inside(x))
00297           ((Functor*)this)->last_ = top_.locate(x);
00298         ParametricSurface::TriSpline2_Fade *l = top_.locate(x);
00299         Eigen::Vector3f v = (*l)((Eigen::Vector2f)x)-pt_;
00300         Eigen::Matrix<float,3,2> M = l->normal(x);
00301 
00302         fjac(0,0) = 2*M.col(0).dot( v );
00303         fjac(0,1) = 2*M.col(1).dot( v );
00304 #endif
00305 
00306         //        fjac(0,0) = 2*( p.col(1)(3)* p.col(3).head<3>().dot(p.col(0).head<3>()-pt_) + vx.dot(p.col(0).head<3>()-pt_));
00307         //        fjac(0,1) = -2*( p.col(2)(3)* p.col(3).head<3>().dot(p.col(0).head<3>()-pt_) + vy.dot(p.col(0).head<3>()-pt_));
00308         fjac(1,0) = fjac(1,1) = 0;
00309 
00310 //        std::cout<<"x\n"<<x<<"\n";
00311 //        std::cout<<"fjac\n"<<fjac<<"\n";
00312 //        std::cout<<"d\n"<<M<<"\n";
00313 
00314         return 0;
00315       }
00316 
00317       int inputs() const { return 2; }
00318       int values() const { return 2; } // number of constraints
00319     };
00320 
00321     friend class Functor;
00322 
00323     static float sqDistLinePt(const Eigen::Vector2f &uv, const Eigen::Vector2f &r1, const Eigen::Vector2f &r2) {
00324       float f = (uv-r1).dot(r2-r1) / (r2-r1).squaredNorm();
00325       if(f>1) f=1;
00326       else if(f<0) f=0;
00327       return (uv - f*(r2-r1) - r1).squaredNorm();
00328     }
00329 
00330     inline ParametricSurface::TriSpline2_Fade* locate(const Eigen::Vector2f &uv) const {
00331       bool inside;
00332       return locate(uv,inside);
00333     }
00334     inline ParametricSurface::TriSpline2_Fade* locate(const Eigen::Vector2f &uv, bool &inside) const {
00335       Face_handle sh = del_.locate( Point(uv(0),uv(1)) );
00336 
00337       /*if(sh==del_.faces_end()) {
00338         ROS_WARN("invalid pt requested");
00339         return tris_[0].get();
00340       }*/
00341 
00342       if(!sh->info().get()) {
00343         ParametricSurface::TriSpline2_Fade* r=NULL;
00344         inside=false;
00345 
00346         float mi = std::numeric_limits<float>::max();
00347         for(std::vector< boost::shared_ptr<ParametricSurface::TriSpline2_Fade> >::const_iterator it = tris_.begin();
00348             it!=tris_.end(); ++it)
00349         {
00350 
00351           Eigen::Vector2f p1 = (*it)->getUV(0),p2=(*it)->getUV(1),p3=(*it)->getUV(2);
00352 
00353           //const float A = ((*it)->getEdge(1)-(*it)->getEdge(0)).cross((*it)->getEdge(2)-(*it)->getEdge(0)).squaredNorm();
00354 
00355           const float dist = std::min( sqDistLinePt(uv, p1,p2), std::min(sqDistLinePt(uv, p2,p3), sqDistLinePt(uv, p3,p1)));
00356 
00357           //std::cout<<"dist "<<dist<<"\n";
00358           if(dist<mi) {
00359             mi = dist;
00360             r = it->get();
00361           }
00362 
00363         }
00364 
00365         //std::cout<<"tri size "<<tris_.size()<<std::endl;
00366 
00367         ROS_ASSERT(r);
00368         return r;
00369       }
00370       else {
00371         //ROS_ASSERT(sh->info().get());
00372         inside=true;
00373         return sh->info().get();
00374       }
00375 
00376     }
00377 
00378     public:
00379 
00380     Topology(const float thr): thr_(thr)
00381     {
00382     }
00383 
00384     Topology(const Topology &o) {
00385       *this = o;
00386     }
00387 
00388     void operator=(const Topology &o) {
00389       thr_ = o.thr_;
00390 #if 0
00391       del_ = o.del_;
00392 
00393       for(size_t i=0; i<o.pts_.size(); i++) {
00394         pts_.push_back( boost::shared_ptr<POINT>( new POINT(*o.pts_[i])) );
00395 
00396         pts_.back()->vh = del_.nearest_vertex( Point(pts_.back()->uv(0), pts_.back()->uv(1)) );
00397         pts_.back()->vh->info() = pts_[i];
00398       }
00399 #else
00400       for(size_t i=0; i<o.pts_.size(); i++)
00401         insertPointWithoutUpdate( *o.pts_[i] );
00402 #endif
00403 
00404       update();
00405     }
00406 
00407     void insertPoint(const POINT &pt) {
00408       insertPointWithoutUpdate(pt);
00409       update();
00410     }
00411 
00412     void finish() {
00413 //      std::cout<<"FINISH----------\n";
00414       std::vector<bool> border(pts_.size());
00415       for(size_t i=0; i<pts_.size(); i++)
00416         border[i] = isOnBorder(pts_[i]);
00417 
00418       for(size_t i=0; /*pts_.size()>3 &&*/ i<pts_.size(); i++) {
00419         if( !border[i] && canRemove(pts_[i]) ) {
00420 //          std::cout<<"remove point "<<i<<"\n"<<pts_[i]->uv<<"\n";
00421 //          ROS_ASSERT(pts_.size()>3);
00422           border.erase(border.begin()+i);
00423           removePoint(i);
00424           update();
00425           --i;
00426         }
00427       }
00428 
00429 //      for(Vertex_iterator it = del_.vertices_begin(); it!=del_.vertices_end(); it++) {
00430 //        //ROS_ASSERT( it->info()->vh == it);
00431 //        ROS_ASSERT(it->point().x()==it->info()->uv(0));
00432 //        ROS_ASSERT(it->point().y()==it->info()->uv(1));
00433 //      }
00434 //
00435 //      for(size_t i=0; i<pts_.size(); i++) {
00438 //        ROS_ASSERT(pts_[i]->vh->point().x()==pts_[i]->uv(0));
00439 //        ROS_ASSERT(pts_[i]->vh->point().y()==pts_[i]->uv(1));
00440 //      }
00441 
00442       bool found = true;
00443       while(found && pts_.size()>3) {
00444         found = false;
00445 //        std::cout<<tris_.size()<<"\n";
00446 //        std::cout<<del_.number_of_faces()<<"\n";
00447         for(Edge_iterator ei=del_.all_edges_begin(); ei!=del_.all_edges_end(); ei++) {
00448           // Get a vertex from the edge
00449           Face_handle f = (ei->first);
00450           int i = ei->second;
00451           if(!f->info()) continue;
00452           Vertex_handle vs = f->vertex(f->cw(i));
00453           Vertex_handle vt = f->vertex(f->ccw(i));
00454           if(!vs->info() || !vt->info() || vs==vt || vs->point()==vt->point()) continue;
00455           if( (vt->info()->pt-vs->info()->pt).squaredNorm() < 0.03f*0.03f) {
00456 //            std::cout<<"XXX "<<&*f<<" "<<f->info()<<" "<<i<<"\n";
00457 //            ROS_INFO("merging uv pts");
00458 //            std::cout<<vs->info()->uv<<"\n";
00459 //            std::cout<<vt->info()->uv<<"\n";
00460 //            std::cout<<vs->point().x()<<" "<<vs->point().y()<<"\n";
00461 //            std::cout<<vt->point().x()<<" "<<vt->point().y()<<"\n";
00462 
00463             POINT pt;
00464             pt.uv = (vt->info()->uv*vt->info()->weight_ + vs->info()->uv*vs->info()->weight_)/(vt->info()->weight_+vs->info()->weight_);
00465             pt.pt = (vt->info()->pt*vt->info()->weight_ + vs->info()->pt*vs->info()->weight_)/(vt->info()->weight_+vs->info()->weight_);
00466             pt.n  = (vt->info()->n *vt->info()->weight_ + vs->info()->n *vs->info()->weight_)/(vt->info()->weight_+vs->info()->weight_);
00467             pt.n2 = (vt->info()->n2*vt->info()->weight_ + vs->info()->n2*vs->info()->weight_)/(vt->info()->weight_+vs->info()->weight_);
00468 
00469             for(size_t j=0; j<pts_.size(); j++)
00470               if(pts_[j]==vt->info()||pts_[j]==vs->info()) {
00471                 removePoint(j);
00472                 border.erase(border.begin()+j);
00473                 --j;
00474                 found = true;
00475 //                std::cout<<"remove point2\n";
00476               }
00477             ROS_ASSERT(found);
00478 
00479             insertPoint(pt);
00480 
00481             break;
00482           }
00483         }
00484 //        std::cout<<del_.number_of_faces()<<"\n";
00485       }
00486 
00487       found = true;
00488       while(found && pts_.size()>3) {
00489         found = false;
00490         for(size_t k=0; k<tris_.size(); k++) {
00491           if( (tris_[k]->getEdge(1)-tris_[k]->getEdge(0)).cross( tris_[k]->getEdge(2)-tris_[k]->getEdge(0) ).squaredNorm() < 0.02f*0.02f*0.02f) {
00492 //            ROS_INFO("merging uv pts3 %f", (tris_[k]->getEdge(1)-tris_[k]->getEdge(0)).cross( tris_[k]->getEdge(2)-tris_[k]->getEdge(0) ).squaredNorm());
00493 
00494             size_t n=(size_t)-1;
00495             size_t m=(size_t)-1;
00496             for(size_t j=0; j<pts_.size(); j++)
00497               if(pts_[j]->uv==tris_[k]->getUV(0)) {
00498                 n=j;
00499                 break;
00500               }
00501 //            if(n==-1) {
00502 //              for(size_t j=0; j<pts_.size(); j++)
00503 //                std::cout<<"uv\n"<<pts_[j]->uv<<"\n";
00504 //              std::cout<<"searching\n"<<tris_[k]->getUV(0)<<std::endl;
00505 //            }
00506             ROS_ASSERT(n!=(size_t)-1);
00507             for(size_t j=0; j<pts_.size(); j++)
00508               if(pts_[j]->uv==tris_[k]->getUV(1)) {
00509                 m=j;
00510                 break;
00511               }
00512 //            if(m==-1) {
00513 //              for(size_t j=0; j<pts_.size(); j++)
00514 //                std::cout<<"uv\n"<<pts_[j]->uv<<"\n";
00515 //              std::cout<<"searching\n"<<tris_[k]->getUV(1)<<std::endl;
00516 //            }
00517             ROS_ASSERT(m!=(size_t)-1);
00518 
00519             if(border[m]||border[n])
00520               continue;
00521 
00522             found = true;
00523             POINT pt;
00524             pt.uv = (pts_[m]->uv*pts_[m]->weight_ + pts_[n]->uv*pts_[n]->weight_)/(pts_[m]->weight_+pts_[n]->weight_);
00525             pt.pt = (pts_[m]->pt*pts_[m]->weight_ + pts_[n]->pt*pts_[n]->weight_)/(pts_[m]->weight_+pts_[n]->weight_);
00526             pt.n  = (pts_[m]->n *pts_[m]->weight_ + pts_[n]->n *pts_[n]->weight_)/(pts_[m]->weight_+pts_[n]->weight_);
00527             pt.n2 = (pts_[m]->n2*pts_[m]->weight_ + pts_[n]->n2*pts_[n]->weight_)/(pts_[m]->weight_+pts_[n]->weight_);
00528 
00529             std::cout<<pt.uv<<std::endl;
00530             removePoint(m);
00531             border.erase(border.begin()+m);
00532             if(n>m) --n;
00533             removePoint(n);
00534             border.erase(border.begin()+n);
00535             insertPoint(pt);
00536             break;
00537           }
00538         }
00539 //        std::cout<<del_.number_of_faces()<<"\n";
00540       }
00541 
00542     }
00543 
00544     void insertPointWithoutUpdate(const POINT &pt) {
00545       ROS_ASSERT( pcl_isfinite(pt.uv.sum()) );
00546 
00547       pts_.push_back(boost::shared_ptr<POINT>( new POINT(pt)));
00548       pts_.back()->vh = del_.insert(Point(pt.uv(0),pt.uv(1)));
00549       if( pts_.back()->vh->info() ) {
00550         ROS_WARN("pt (%f, %f) already there", pt.uv(0), pt.uv(1));
00551         pts_.erase(pts_.end()-1);
00552         return;
00553       }
00554       pts_.back()->vh->info() = pts_.back();
00555     }
00556 
00557     void update() {
00558 
00559       tris_.clear();
00560       for(Face_iterator it = del_.faces_begin(); it!=del_.faces_end(); it++) {
00561         //          std::cout<<"addr2 "<<&*it->vertex(0)<<"\n";
00562         //          POINT *a = map_pts_[&*it->vertex(0)].get();
00563         //          POINT *b = map_pts_[&*it->vertex(1)].get();
00564         //          POINT *c = map_pts_[&*it->vertex(2)].get();
00565         POINT *a = it->vertex(0)->info().get();
00566         POINT *b = it->vertex(1)->info().get();
00567         POINT *c = it->vertex(2)->info().get();
00568         Eigen::Vector3f w;
00569         w(0) = a->weight_;
00570         w(1) = b->weight_;
00571         w(2) = c->weight_;
00572         tris_.push_back( boost::shared_ptr<ParametricSurface::TriSpline2_Fade>(new ParametricSurface::TriSpline2_Fade(
00573             a->pt,      b->pt,  c->pt,
00574             a->n,       b->n,   c->n,
00575             a->n2,      b->n2,  c->n2,
00576             a->uv,      b->uv,  c->uv,
00577             w, 2.f
00578         ) ));
00579 
00580         it->info() = tris_.back();
00581         //it->pp = tris_.back().get();
00582         //map_tris_[&*it] = tris_.back();
00583       }
00584 
00585     }
00586 
00587     inline Eigen::Vector2f nextPoint(const Eigen::Vector3f &p, ParametricSurface::TriSpline2_Fade **used=NULL) const {
00588       //std::cout<<"nP\n"<<p<<"\n";
00589       Eigen::VectorXf r(2);
00590 
00591       r = p.head<2>();
00592       float dis = (project2world(r)-p).squaredNorm();
00593 //      float dis = std::numeric_limits<float>::max();
00594       /*for(std::vector< boost::shared_ptr<ParametricSurface::TriSpline2_Fade> >::const_iterator it = tris_.begin();
00595           it!=tris_.end(); ++it)
00596       {
00597         const float d = ((*it)->getMid()-p).squaredNorm();
00598         if(d<dis) {
00599           dis = d;
00600           r = (*it)->getMidUV();
00601         }
00602       }*/
00603       for(size_t i=0; i<pts_.size(); i++)
00604       {
00605         const float d = (pts_[i]->pt-p).squaredNorm();
00606         //std::cout<<"wuv "<<d<<"\n"<<pts_[i]->uv<<"\n";
00607         if(d<dis) {
00608           dis = d;
00609           r = pts_[i]->uv;
00610         }
00611       }
00612       /*for(size_t i=0; i<tris_.size(); i++)
00613       {
00614         const float d = ((tris_[i]->getEdge(2)-p).squaredNorm()+(tris_[i]->getEdge(1)-p).squaredNorm()+(tris_[i]->getEdge(0)-p).squaredNorm()) /
00615         ((tris_[i]->getEdge(2)-tris_[i]->getEdge(1)).squaredNorm()+(tris_[i]->getEdge(1)-tris_[i]->getEdge(0)).squaredNorm()+(tris_[i]->getEdge(2)-tris_[i]->getEdge(0)).squaredNorm());
00616         //std::cout<<"wuv "<<d<<"\n"<<pts_[i]->uv<<"\n";
00617         if(d<dis) {
00618           dis = d;
00619           r = pts_[i]->uv;
00620         }
00621       }*/
00622       //std::cout<<"start\n"<<r<<"\n";
00623       Functor functor(*this, p);
00624       functor.init(r);
00625 #if 0
00626       Eigen::HybridNonLinearSolver<Functor, float> lm(functor);
00627       lm.parameters.maxfev = 50; //not to often (performance)
00628       lm.solve(r);
00629 #else
00630       Eigen::LevenbergMarquardt<Functor, float> lm(functor);
00631       lm.parameters.maxfev = 50; //not to often (performance)
00632 //      std::cout<<"xtol "<<lm.parameters.xtol<<"\n";
00633 //      std::cout<<"ftol "<<lm.parameters.ftol<<"\n";
00634       lm.parameters.xtol = 0.001f;
00635       lm.parameters.ftol = 0.001f;
00636       //lm.parameters.factor = 10;
00637       lm.minimize(r);
00638 
00639 
00640       /*Eigen::LevenbergMarquardtSpace::Status status = lm.minimizeInit(r);
00641       do {
00642           status = lm.minimizeOneStep(r);
00643           std::cout<<"status "<<status<<"\n";
00644       } while (status==Eigen::LevenbergMarquardtSpace::Running);*/
00645 #endif
00646 
00647       if(used)
00648         *used = functor.getLast();
00649 
00650       ROS_ASSERT( pcl_isfinite(r.sum()) );
00651 
00652       return r;
00653     }
00654 
00655     inline Eigen::Vector3f project2world(const Eigen::Vector2f &uv) const {
00656       if(tris_.size()<3) Eigen::Vector3f::Zero();
00657       Eigen::Vector3f r = (*locate(uv))(uv);
00658 
00659       if( !pcl_isfinite(r.sum()) ) {
00660         locate(uv)->print();
00661         std::cout<<"uv is\n"<<uv<<std::endl;
00662         std::cout<<"r is\n"<<r<<std::endl;
00663         ROS_ASSERT( pcl_isfinite(r.sum()) );
00664       }
00665 
00666       return r;
00667     }
00668 
00669     inline Eigen::Vector3f normalAt(const Eigen::Vector2f &uv) const {
00670       if(tris_.size()<3) Eigen::Vector3f::Zero();
00671       Eigen::Vector3f v = locate(uv)->normalAt(uv);
00672       if(v.squaredNorm()>0.00001f) v.normalize();
00673       ROS_ASSERT(pcl_isfinite(v.sum()));
00674       return v;
00675     }
00676 
00677     inline Eigen::Matrix<float,3,2> normal(const Eigen::Vector2f &uv) const {
00678       if(tris_.size()<3) Eigen::Matrix<float,3,2>::Zero();
00679       return locate(uv)->normal(uv);
00680     }
00681 
00682     inline Eigen::Vector3f normalAt2(const Eigen::Vector2f &uv, bool &inside, float &w) const {
00683       if(tris_.size()<3) Eigen::Vector3f::Zero();
00684       ParametricSurface::TriSpline2_Fade *tri = locate(uv, inside);
00685       Eigen::Vector3f bc = tri->UV2BC(uv);
00686       w = bc.dot(tri->getWeight());
00687       Eigen::Vector3f v = tri->normalAt2(uv);
00688       if(v.squaredNorm()>0.00001f) v.normalize();
00689       ROS_ASSERT(pcl_isfinite(v.sum()));
00690       return v;
00691     }
00692 
00693     /*inline Eigen::Matrix4f normalAtUV(const Eigen::Vector2f &uv) const {
00694       return locate(uv)->normalAtUV(uv);
00695     }*/
00696 
00697     float operator+=(const Topology &o) {
00698       ROS_ASSERT(this!=&o);
00699 
00700       float er=0;
00701       int num=0;
00702 
00703 //      ROS_INFO("merge");
00704       //for(Face_iterator it = del_.faces_begin(); it!=del_.faces_end(); it++)
00705       //std::cout<<"addr2 "<<&*it->vertex(0)<<"\n";
00706       //      for(std::map< Vertex*, boost::shared_ptr<POINT> >::iterator it = map_pts_.begin(); it!=map_pts_.end(); it++)
00707       //        std::cout<<"addr3 "<<it->first<<"\n";
00708       //      std::cout<<"vertex addr3 "<<map_pts_.begin()->first<<" "<<(--map_pts_.end())->first<<"\n";
00709       //      ROS_INFO("size %d", map_pts_.size());
00710 
00711       if(pts_.size()<3)
00712       {
00713 //        ROS_INFO("copy %d", pts_.size());
00714 
00715         for(size_t i=0; i<o.pts_.size(); i++) {
00716           insertPointWithoutUpdate(*o.pts_[i]);
00717         }
00718       }
00719       else {
00720 //        ROS_INFO("add %d",o.pts_.size());
00721 
00722         std::vector<POINT> temp;
00723         for(size_t i=0; i<o.pts_.size(); i++) {
00724           POINT p = *o.pts_[i];
00725 
00726 #if 0
00727           //check for near points
00728           bool found = false;
00729           for(size_t j=0; j<pts_.size(); j++) {
00730             if( (pts_[j]->pt-p.pt).squaredNorm()<0.0001f ) {
00731 #error
00732               pts_[j]->n2 = (p.weight_*p.n2 + pts_[j]->weight*pts_[j].n2)/(p.weight_+pts_[j].weight);
00733               const float d = std::acos( pts_[j]->n.dot(p.n) );
00734               pts_[j]->n = (p.weight_*p.n + pts_[j]->weight*pts_[j].n)/(p.weight_+pts_[j].weight);
00735               pts_[j]->n.normalize();
00736 
00737               er += (p.pt-pts_[j]->pt).squaredNorm()+0.1f*d*t.squaredNorm();
00738 
00739               pts_[j]->pt = (p.weight_*p.pt + w*pts_[j].pt)/(p.weight_+pts_[j].weight);
00740               pts_[j]->weight_ += p.weight;
00741 
00742               ++num;
00743             }
00744           }
00745 
00746           if(found) continue;
00747 #endif
00748 
00749           bool inside;
00750           ParametricSurface::TriSpline2_Fade *tri = NULL;
00751           p.uv = nextPoint(p.pt, &tri);
00752           //tri = locate(p.uv);
00753 
00754           float w;// = tri->getWeight();
00755           //inside=true;
00756           Eigen::Vector3f t = normalAt2(p.uv, inside, w);
00757           if(inside) {
00758 //            std::cout<<"normal2 "<<t<<"\n";
00759             p.n2 = (p.weight_*p.n2 + w*t)/(p.weight_+w);
00760             p.n2.normalize();
00761 
00762 //            std::cout<<"w "<<p.weight_<<"\n";
00763 //            std::cout<<"n bef\n"<<p.n<<"\n";
00764 
00765             t = normalAt(p.uv);
00766             const float d = std::acos( t.dot(p.n) );
00767             p.n = (p.weight_*p.n + w*t)/(p.weight_+w);
00768             p.n.normalize();
00769 
00770 //            std::cout<<"n after\n"<<p.n<<"\n";
00771 
00772             t = project2world(p.uv);
00773             p.pt = (p.weight_*p.pt + w*t)/(p.weight_+w);
00774             p.weight_ += w;
00775 
00776             er += (p.pt-t).squaredNorm()+0.1f*d*t.squaredNorm();
00777             ++num;
00778           }
00779           //ROS_ASSERT( tri==locate(p.uv) );
00780           tri=locate(p.uv);
00781 //          bool b=tri->inside(p.uv);
00782           Eigen::Vector2f uv_tmp;
00783           if(!tri->polating(p.pt, p.uv, inside, p.uv, uv_tmp)) {
00784             ROS_ASSERT( !locate(p.uv)->complete_inside(p.uv)||!locate(uv_tmp)->complete_inside(uv_tmp) );
00785             if(locate(p.uv)->inside(p.uv))
00786               p.uv = uv_tmp;
00787             ROS_ASSERT( inside==locate(p.uv)->complete_inside(p.uv) );
00788             if(locate(p.uv)->inside(p.uv))
00789               continue;
00790           }
00791 //          std::cout<<b<<"  "<<locate(p.uv)->inside(p.uv)<<std::endl;
00792 //          ROS_ASSERT( pcl_isfinite( p.uv.sum() ) );
00793           temp.push_back(p);
00794         }
00795         for(size_t i=0; i<pts_.size(); i++) {
00796           Eigen::Vector2f uv = o.nextPoint(pts_[i]->pt);
00797           bool inside;
00798           float w;
00799           Eigen::Vector3f t = o.normalAt2(uv,inside,w);
00800           if(inside) {
00801             pts_[i]->n2 = (pts_[i]->weight_*pts_[i]->n2 + w*t)/(pts_[i]->weight_+w);
00802             pts_[i]->n2.normalize();
00803 
00804             t = o.normalAt(uv);
00805             const float d = std::acos( t.dot(pts_[i]->n) );
00806             pts_[i]->n = (pts_[i]->weight_*pts_[i]->n + w*t)/(pts_[i]->weight_+w);
00807             pts_[i]->n.normalize();
00808 
00809             t = o.project2world(uv);
00810             pts_[i]->pt = (pts_[i]->weight_*pts_[i]->pt + w*t)/(pts_[i]->weight_+w);
00811             pts_[i]->weight_ += w;
00812 
00813             er += (pts_[i]->pt-t).squaredNorm()+0.1f*d*t.squaredNorm();
00814             ++num;
00815           }
00816         }
00817         try {
00818         for(size_t i=0; i<temp.size(); i++) {
00819           insertPointWithoutUpdate(temp[i]);
00820         }
00821         } catch(...) {
00822           ROS_ERROR("CGAL error   CGAL error   CGAL error   CGAL error   CGAL error   CGAL error   ");
00823           return 1000.f;
00824         }
00825 
00826         if(!num || !pcl_isfinite(er))
00827           er = 1000.f;
00828       }
00829       //      ROS_INFO("size %d", map_pts_.size());
00830       //      for(std::map< Vertex*, boost::shared_ptr<POINT> >::iterator it = map_pts_.begin(); it!=map_pts_.end(); it++)
00831       //        std::cout<<"addr3 "<<it->first<<"\n";
00832       //      std::cout<<"vertex addr3 "<<map_pts_.begin()->first<<" "<<(--map_pts_.end())->first<<"\n";
00833       update();
00834 
00835       finish();
00836 
00837       return er/std::max(num,1);
00838     }
00839 
00840     void transform(const Eigen::Matrix3f &rot, const Eigen::Vector3f &tr) {
00841       for(size_t i=0; i<pts_.size(); i++) {
00842         pts_[i]->transform(rot, tr);
00843       }
00844 
00845       for(std::vector< boost::shared_ptr<ParametricSurface::TriSpline2_Fade> >::iterator it = tris_.begin();
00846           it!=tris_.end(); ++it)
00847       {
00848         (*it)->transform(rot, tr);
00849       }
00850     }
00851 
00852     void print() const {
00853       /*for(size_t i=0; i<pts_.size(); i++) {
00854         std::cout<<"uv\n"<<pts_[i]->uv<<"\n";
00855         std::cout<<"pt\n"<<pts_[i]->pt<<"\n";
00856       }*/
00857     }
00858 
00859     void add(cob_3d_marker::MarkerList_Line &ml) const {
00860       for(std::vector< boost::shared_ptr<ParametricSurface::TriSpline2_Fade> >::const_iterator it = tris_.begin();
00861           it!=tris_.end(); ++it)
00862       {
00863         ParametricSurface::_Line l[6];
00864         (*it)->test_setup(l);
00865         //        for(int i=0; i<6; i++)
00866         //          ml.addLine( l[i].o, l[i].o+l[i].u*0.1f, 0,1,0);
00867         for(int i=0; i<3; i++) {
00868           ml.addLine( (*it)->getEdge(i), (*it)->getEdge((i+1)%3) );
00869 
00870           ml.addLine( (*it)->getEdge(i), (*it)->getFade(i)(1,0).head(3) , 0.8f,0.1f,0.1f);
00871           ml.addLine( (*it)->getFade(i)(1,0).head(3), (*it)->getFade(i)(0,1).head(3) , 0.8f,0.1f,0.1f);
00872           ml.addLine( (*it)->getFade(i)(0,1).head(3), (*it)->getEdge((i+1)%3) , 0.8f,0.1f,0.1f);
00873         }
00874       }
00875     }
00876 
00877     void add(cob_3d_marker::MarkerList_Triangles &mt, ParametricSurface::TriSpline2_Fade &tri,
00878              const Eigen::Vector3f &a, const Eigen::Vector3f &b, const Eigen::Vector3f &c, const int depth=0) const {
00879       if(depth>=2) {
00880         Eigen::Matrix<float,3,2> M = tri.normalBC( ((a+b+c)/3).head<2>() );
00881         M.col(0) = M.col(0).cross(M.col(1));
00882         M.col(0).normalize();
00883         M.col(1).fill(0);M.col(1)(2)=1;
00884         float f=std::abs(M.col(0).dot(M.col(1)));
00885         mt.addTriangle( tri(a), tri(b), tri(c), f,f,f );
00886       }
00887       else {
00888         add(mt, tri, a, (a+b+c)/3, (a+b)/2, depth+1);
00889         add(mt, tri, a, (a+b+c)/3, (a+c)/2, depth+1);
00890 
00891         add(mt, tri, b, (a+b+c)/3, (a+b)/2, depth+1);
00892         add(mt, tri, b, (a+b+c)/3, (b+c)/2, depth+1);
00893 
00894         add(mt, tri, c, (a+b+c)/3, (c+b)/2, depth+1);
00895         add(mt, tri, c, (a+b+c)/3, (a+c)/2, depth+1);
00896       }
00897     }
00898 
00899     void add(cob_3d_marker::MarkerList_Triangles &mt) const {
00900       for(std::vector< boost::shared_ptr<ParametricSurface::TriSpline2_Fade> >::const_iterator it = tris_.begin();
00901           it!=tris_.end(); ++it)
00902       {
00903         Eigen::Vector3f a,b,c;
00904         a=b=c=Eigen::Vector3f::Zero();
00905         a(0)=b(1)=c(2)=1;
00906         add(mt, *(*it), a,b,c);
00907       }
00908     }
00909 
00910     void add(cob_3d_marker::MarkerList_Arrow &ma) const {
00911       for(std::vector< boost::shared_ptr<ParametricSurface::TriSpline2_Fade> >::const_iterator it = tris_.begin();
00912           it!=tris_.end(); ++it)
00913       {
00914         for(int i=0; i<3; i++) {
00915           ma.addArrow((*it)->getEdge(i), (*it)->getEdge(i)+(*it)->getNormal(i)*0.25f);
00916 
00917           ma.addArrow((*it)->getEdge(i), (*it)->getEdge(i)+(*it)->getNormal2(i)*0.2f, 1,0,0);
00918         }
00919       }
00920     }
00921 
00922     void add(cob_3d_marker::MarkerList_Text &mt) const {
00923       for(std::vector< boost::shared_ptr<ParametricSurface::TriSpline2_Fade> >::const_iterator it = tris_.begin();
00924           it!=tris_.end(); ++it)
00925       {
00926         for(int i=0; i<3; i++) {
00927           char buf[128];
00928           sprintf(buf,"uv: %f %f", (*it)->getUV(i)(0), (*it)->getUV(i)(1));
00929           mt.addText((*it)->getEdge(i), buf, 0.02f);
00930         }
00931       }
00932     }
00933 
00934   };
00935 
00936 }
00937 
00938 #endif /* TOPOLGY_H_ */


cob_3d_mapping_slam
Author(s): Joshua Hampp
autogenerated on Wed Aug 26 2015 11:04:51