00001
00002
00003
00004
00005
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
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
00068 typedef float RT;
00069
00070 typedef CGAL::Cartesian<float> Kernel;
00071
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
00087
00088
00089
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
00119
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
00127
00128
00129
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
00141
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
00155
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
00164
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
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
00189
00190
00191 Eigen::Matrix3f V = Eigen::Matrix3f::Zero();
00192
00193 Face_circulator fc = pt->vh->incident_faces();
00194 float n=0;
00195 do {
00196
00197
00198 if( fc->info() ) {
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
00208
00209 return
00210
00211 std::abs(svd.singularValues()(2))
00212 <thr_*n;
00213 }
00214
00215 void removePoint(const size_t i) {
00216
00217 ROS_ASSERT(pts_[i]->vh->info()==*(pts_.begin()+i));
00218
00219 del_.remove(pts_[i]->vh);
00220
00221
00222
00223
00224
00225
00226 pts_.erase(pts_.begin()+i);
00227 }
00228
00229
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
00247
00248
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
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
00268
00269 return 0;
00270 }
00271
00272 int df(const Eigen::VectorXf &x, Eigen::MatrixXf &fjac) const
00273 {
00274
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
00307
00308 fjac(1,0) = fjac(1,1) = 0;
00309
00310
00311
00312
00313
00314 return 0;
00315 }
00316
00317 int inputs() const { return 2; }
00318 int values() const { return 2; }
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
00338
00339
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
00354
00355 const float dist = std::min( sqDistLinePt(uv, p1,p2), std::min(sqDistLinePt(uv, p2,p3), sqDistLinePt(uv, p3,p1)));
00356
00357
00358 if(dist<mi) {
00359 mi = dist;
00360 r = it->get();
00361 }
00362
00363 }
00364
00365
00366
00367 ROS_ASSERT(r);
00368 return r;
00369 }
00370 else {
00371
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
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; i<pts_.size(); i++) {
00419 if( !border[i] && canRemove(pts_[i]) ) {
00420
00421
00422 border.erase(border.begin()+i);
00423 removePoint(i);
00424 update();
00425 --i;
00426 }
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00438
00439
00440
00441
00442 bool found = true;
00443 while(found && pts_.size()>3) {
00444 found = false;
00445
00446
00447 for(Edge_iterator ei=del_.all_edges_begin(); ei!=del_.all_edges_end(); ei++) {
00448
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
00457
00458
00459
00460
00461
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
00476 }
00477 ROS_ASSERT(found);
00478
00479 insertPoint(pt);
00480
00481 break;
00482 }
00483 }
00484
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
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
00502
00503
00504
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
00513
00514
00515
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
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
00562
00563
00564
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
00582
00583 }
00584
00585 }
00586
00587 inline Eigen::Vector2f nextPoint(const Eigen::Vector3f &p, ParametricSurface::TriSpline2_Fade **used=NULL) const {
00588
00589 Eigen::VectorXf r(2);
00590
00591 r = p.head<2>();
00592 float dis = (project2world(r)-p).squaredNorm();
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 for(size_t i=0; i<pts_.size(); i++)
00604 {
00605 const float d = (pts_[i]->pt-p).squaredNorm();
00606
00607 if(d<dis) {
00608 dis = d;
00609 r = pts_[i]->uv;
00610 }
00611 }
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 Functor functor(*this, p);
00624 functor.init(r);
00625 #if 0
00626 Eigen::HybridNonLinearSolver<Functor, float> lm(functor);
00627 lm.parameters.maxfev = 50;
00628 lm.solve(r);
00629 #else
00630 Eigen::LevenbergMarquardt<Functor, float> lm(functor);
00631 lm.parameters.maxfev = 50;
00632
00633
00634 lm.parameters.xtol = 0.001f;
00635 lm.parameters.ftol = 0.001f;
00636
00637 lm.minimize(r);
00638
00639
00640
00641
00642
00643
00644
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
00694
00695
00696
00697 float operator+=(const Topology &o) {
00698 ROS_ASSERT(this!=&o);
00699
00700 float er=0;
00701 int num=0;
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 if(pts_.size()<3)
00712 {
00713
00714
00715 for(size_t i=0; i<o.pts_.size(); i++) {
00716 insertPointWithoutUpdate(*o.pts_[i]);
00717 }
00718 }
00719 else {
00720
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
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
00753
00754 float w;
00755
00756 Eigen::Vector3f t = normalAt2(p.uv, inside, w);
00757 if(inside) {
00758
00759 p.n2 = (p.weight_*p.n2 + w*t)/(p.weight_+w);
00760 p.n2.normalize();
00761
00762
00763
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
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
00780 tri=locate(p.uv);
00781
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
00792
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
00830
00831
00832
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
00854
00855
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
00866
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