00001
00002
00003
00004
00005
00006
00007
00008 #ifndef FORM_H_
00009 #define FORM_H_
00010
00011 #include "polygon_merger.h"
00012
00013 namespace Slam_CurvedPolygon
00014 {
00015
00016 class Outline
00017 {
00018
00019 static void debug_svg_text(FILE *fp, float x, float y, float e, const char *color) {
00020 char buffer[1024];
00021 sprintf(buffer,"<text x=\"%f\" y=\"%f\" style=\"stroke:%s; stroke-width:2px;\">%.2f</text>",x,y,color,e);
00022 fputs(buffer,fp);
00023 }
00024 static void debug_svg_line(FILE *fp, float x, float y, float x2, float y2, float e, const char *color="black") {
00025 char buffer[1024];
00026 sprintf(buffer,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:%s; stroke-width:2px;\" />",x,y,x2,y2,color);
00027 if(pcl_isfinite(e))
00028 debug_svg_text(fp,(x+x2)/2,(y+y2)/2,e,color);
00029 fputs(buffer,fp);
00030 }
00031 static void debug_svg_line(FILE *fp, float x, float y, float x2, float y2, const char *color="black") {
00032 char buffer[1024];
00033 sprintf(buffer,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:%s; stroke-width:2px;\" />",x,y,x2,y2,color);
00034 fputs(buffer,fp);
00035 }
00036
00037 public:
00038 std::vector<Eigen::Vector3f> segments_;
00039 float weight_;
00040 bool open_;
00041
00042 Outline(): weight_(1.f), open_(false)
00043 {}
00044
00045 void operator+=(const Eigen::Vector3f &v) {
00046 segments_.push_back(v);
00047 if(!pcl_isfinite(segments_.back()(2)) ) {
00048 std::cout<<"v is not finite\n"<<segments_.back()<<std::endl;
00049 ROS_ERROR("v is not finite");
00050 segments_.back()(2) = 0.f;
00051 }
00052 }
00053
00054 struct OUTPUTSVG {
00055 FILE *fp;
00056 std::string fn;
00057
00058 OUTPUTSVG(const char *fn):fn(fn) {
00059 fp=fopen((std::string("/tmp/")+fn).c_str(),"w");
00060 fputs("<?xml version=\"1.0\" encoding=\"ISO-8859-1\" standalone=\"no\" ?>",fp);
00061 fputs("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">",fp);
00062 fputs("<svg width=\"1640\" height=\"1480\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">",fp);
00063 }
00064
00065 ~OUTPUTSVG()
00066 {
00067 fputs("</svg>",fp);
00068 fclose(fp);
00069 }
00070 };
00071
00072 boost::shared_ptr<OUTPUTSVG> debug_svg(const char *fn, const float f=100, const float o=300, const char *color="black") const {
00073 boost::shared_ptr<OUTPUTSVG> out(new OUTPUTSVG(fn));
00074 return debug_svg(out,f,o, color);
00075 }
00076
00077 boost::shared_ptr<OUTPUTSVG> debug_svg(boost::shared_ptr<OUTPUTSVG> out, const float f=100, const float o=300, const char *color="black") const {
00078 FILE *fp2=fopen((std::string("/tmp/data_")+out->fn+".txt").c_str(),"a");
00079
00080 fprintf(fp2,"\n\n");
00081
00082 for(size_t i=0; i<segments_.size(); i++)
00083 {
00084 Eigen::Vector2f p=segments_[(i+1)%segments_.size()].head<2>();
00085 Eigen::Vector2f p2=segments_[i].head<2>();
00086 Eigen::Vector2f d=p2-p;
00087 debug_svg_line(out->fp, segments_[i](0)*f+o, segments_[i](1)*f+o,
00088 segments_[(i+1)%segments_.size()](0)*f+o, segments_[(i+1)%segments_.size()](1)*f+o
00089 ,segments_[(i+1)%segments_.size()](2)/weight_
00090 ,color
00091 );
00092 debug_svg_line(out->fp, p(0)*f+o,p(1)*f+o,
00093 (p(0)+0.1*d(0)+0.1*d(1))*f+o,(p(1)+0.1*d(1)-0.1*d(0))*f+o,color);
00094 debug_svg_line(out->fp, p(0)*f+o,p(1)*f+o,
00095 (p(0)+0.1*d(0)-0.1*d(1))*f+o,(p(1)+0.1*d(1)+0.1*d(0))*f+o,color);
00096 debug_svg_text(out->fp,p2(0)*f+o,p2(1)*f+o,i,color);
00097
00098 fprintf(fp2,"ADD_POINT(OUTLINE, %f,%f, \t%f);\n",segments_[i](0),segments_[i](1),segments_[i](2));
00099 }
00100
00101 fclose(fp2);
00102 return out;
00103 }
00104
00105 struct COR
00106 {
00107 bool other;
00108 size_t ind;
00109 Eigen::Vector3f p;
00110 };
00111
00112 template<typename T>
00113 static size_t nextLine(const std::vector<T> &segments_, const Eigen::Vector2f &p, const Eigen::Vector2f &n, T &r) {
00114 size_t ind = (size_t)-1;
00115 Eigen::Matrix2f M;
00116 M.col(0) = n;
00117 float mi = std::numeric_limits<float>::max();
00118 for(size_t i=0; i<segments_.size(); i++)
00119 {
00120 Eigen::Vector2f p3 = segments_[i].head(2);
00121 Eigen::Vector2f p4 = segments_[(i+1)%segments_.size()].head(2);
00122
00123 M.col(1) = p3-p4;
00124
00125 Eigen::Vector2f m = (M.inverse()*(p3-p));
00126 float d;
00127
00128 if(m(1)>=0.f && m(1)<=1.f)
00129 d = (m(0)*n).squaredNorm();
00130 if(m(1)<0)
00131 d = (p3-p).squaredNorm();
00132 else
00133 d = (p4-p).squaredNorm();
00134
00135
00136
00137 if(d<mi)
00138 {
00139 mi = d;
00140 ind = (i+1)%segments_.size();
00141 if(m(1)>0.f && m(1)<1.f) {
00142 r.head(2) = m(0)*n+p;
00143 r(2) = segments_[ind](2);
00144 r(3) = segments_[ind](3);
00145 }
00146 else if(m(1)<=0) {
00147 r.head(2) = p3;
00148 r(2) = std::max(segments_[ind](2),segments_[i](2));
00149 if(segments_[ind](2)>segments_[i](2))
00150 r(3) = segments_[ind](3);
00151 else
00152 r(3) = segments_[i](3);
00153 ind = i;
00154 }
00155 else {
00156 r.head(2) = p4;
00157 r(2) = std::max(segments_[ind](2),segments_[(ind+1)%segments_.size()](2));
00158 if(segments_[ind](2)>segments_[(ind+1)%segments_.size()](2))
00159 r(3) = segments_[ind](3);
00160 else
00161 r(3) = segments_[(ind+1)%segments_.size()](3);
00162 }
00163 }
00164
00165
00166
00167
00168 }
00169 return ind;
00170 }
00171
00172 size_t _nextPoint(const Eigen::Vector2f &p) const {
00173 size_t ind = (size_t)-1;
00174 float mi = std::numeric_limits<float>::max();
00175 for(size_t i=0; i<segments_.size(); i++)
00176 {
00177 const float d= (segments_[i].head<2>()-p).squaredNorm();
00178
00179 if(d<mi)
00180 {
00181 mi = d;
00182 ind = i;
00183 }
00184 }
00185 return ind;
00186 }
00187
00188 size_t _nextPoint2(const Eigen::Vector2f &p, Eigen::Vector2f &r) const {
00189 size_t ind = (size_t)-1;
00190 float mi = std::numeric_limits<float>::max();
00191 for(size_t i=0; i<segments_.size(); i++)
00192 {
00193 Eigen::Vector2f p1 = segments_[i].head<2>();
00194 Eigen::Vector2f p2 = segments_[(i+1)%segments_.size()].head<2>();
00195
00196 Eigen::Vector2f d1 = (p-p1);
00197 Eigen::Vector2f d2 = p2-p1;
00198 float f = d1.dot(d2)/d2.squaredNorm();
00199 float d;
00200 Eigen::Vector2f n;
00201
00202 size_t tmp = i+1;
00203 if(f>=1){
00204 d = (p-p2).norm();
00205 n = p2-p;
00206 }
00207 else if(f<=0) {
00208 d = (p-p1).norm();
00209 n = p1-p;
00210 tmp--;
00211 }
00212 else {
00213 d = (d1(0)*d2(1)-d1(1)*d2(0))/(d2).norm();
00214 n(0) = -(p2(1)-p1(1));
00215 n(1) = (p2(0)-p1(0));
00216 }
00217
00218 if(d<mi)
00219 {
00220 mi = d;
00221 ind = tmp;
00222 r = n+p;
00223 }
00224 }
00225 return ind;
00226 }
00227
00228 operator std::vector<Eigen::Vector4f>() const {
00229 std::vector<Eigen::Vector4f> r;
00230 for(size_t i=0; i<size(); i++)
00231 {
00232 Eigen::Vector4f v;
00233 v.head<3>() = (*this)[i];
00234 v(3) = weight_;
00235 r.push_back(v);
00236 }
00237 return r;
00238 }
00239
00240 static size_t _hasIntersection(const std::vector<Eigen::Vector4f> &segments_, const Eigen::Vector2f &p1, const Eigen::Vector2f &p2, const bool open=false) {
00241 Eigen::Matrix2f M;
00242 M.col(0) = p2-p1;
00243 for(size_t i=0; i<segments_.size()-(open?1:0); i++)
00244 {
00245 Eigen::Vector2f p3 = segments_[i].head(2);
00246 Eigen::Vector2f p4 = segments_[(i+1)%segments_.size()].head(2);
00247 M.col(1) = p3-p4;
00248
00249 Eigen::Vector2f m = (M.inverse()*(p3-p1));
00250
00251 if(m(0)>0.001&&m(0)<0.99999 && m(1)>0.001&&m(1)<0.99999) {
00252
00253
00254
00255 return i+1;
00256 }
00257 }
00258 return 0;
00259 }
00260
00261 static size_t _nextPoint3(const std::vector<Eigen::Vector4f> &segments_, const Eigen::Vector2f &p, Eigen::Vector4f &r, const bool open=false) {
00262 size_t ind = (size_t)-1;
00263 float mi = std::numeric_limits<float>::max();
00264 for(size_t i=0; i<segments_.size()-(open?1:0); i++)
00265 {
00266 Eigen::Vector2f p1 = segments_[i].head<2>();
00267 Eigen::Vector2f p2 = segments_[(i+1)%segments_.size()].head<2>();
00268
00269 Eigen::Vector2f d1 = (p-p1);
00270 Eigen::Vector2f d2 = p2-p1;
00271 float f = d1.dot(d2)/(d2.squaredNorm());
00272 float d;
00273 Eigen::Vector2f n;
00274
00275 size_t tmp = i+1;
00276 if(f>0&&f<1) {
00277 d = (d1(0)*d2(1)-d1(1)*d2(0))/(d2).norm();
00278 n = f*d2 + p1;
00279 }
00280 else if(f>=1){
00281 d = (p-p2).norm();
00282 n = p2;
00283 }
00284 else {
00285 d = (p-p1).norm();
00286 n = p1;
00287 tmp--;
00288 }
00289
00290 if(d<mi)
00291 {
00292
00293 if(_hasIntersection(segments_,p,n))
00294 continue;
00295
00296 mi = d;
00297 ind = tmp;
00298 r.head<2>() = n;
00299 if(f>0&&f<1) {
00300 r(2) = segments_[(i+1)%segments_.size()](2);
00301 r(3) = segments_[(i+1)%segments_.size()](3);
00302 }
00303 else if(f>=1){
00304 if( segments_[(i+1)%segments_.size()](2)/segments_[(i+1)%segments_.size()](3) >
00305 segments_[(i+2)%segments_.size()](2)/segments_[(i+2)%segments_.size()](3)) {
00306 r(2) = segments_[(i+1)%segments_.size()](2);
00307 r(3) = segments_[(i+1)%segments_.size()](3);
00308 } else {
00309 r(2) = segments_[(i+2)%segments_.size()](2);
00310 r(3) = segments_[(i+2)%segments_.size()](3); }
00311 }
00312 else{
00313 if( segments_[(i+1)%segments_.size()](2)/segments_[(i+1)%segments_.size()](3) >
00314 segments_[i](2)/segments_[i](3)) {
00315 r(2) = segments_[(i+1)%segments_.size()](2);
00316 r(3) = segments_[(i+1)%segments_.size()](3);
00317 } else {
00318 r(2) = segments_[i](2);
00319 r(3) = segments_[i](3); }
00320 }
00321 }
00322 }
00323 return ind;
00324 }
00325
00326 static void run2(const std::vector<Eigen::Vector4f> &segments_, const std::vector<Eigen::Vector4f> &o, const size_t begin, const size_t end, Outline &res, const bool proc=true) {
00327 size_t last_ind, start_ind;
00328 bool start = true;
00329 Eigen::Vector3f r2;
00330
00331
00332 for(size_t j=begin; j<(end>begin?end:end+segments_.size()); j++)
00333 {
00334 size_t i = j%segments_.size();
00335
00336 Eigen::Vector2f n1,n2;
00337 Eigen::Vector4f r;
00338 n1=segments_[i].head<2>()-segments_[(i-1+segments_.size())%segments_.size()].head<2>();
00339 n1.normalize();
00340 n2=segments_[(i+1)%segments_.size()].head<2>()-segments_[i].head<2>();
00341 n2.normalize();
00342 n2+=n1;
00343 n1(0) = -n2(1);
00344 n1(1) = n2(0);
00345 size_t ind = nextLine(o, segments_[i].head<2>(), n1, r);
00346 if(ind!=(size_t)-1) {
00347
00348 if(!start && ind!=last_ind && proc) {
00349 run2(o, segments_, last_ind, ind, res, false);
00350
00351
00352 }
00353 else if(start) {
00354 start = false;
00355 start_ind = ind;
00356 }
00357 last_ind = ind;
00358
00359 const float p1 = std::max(segments_[i](2), segments_[(i+1)%segments_.size()](2))+0.001f;
00360 float weight;
00361 if(segments_[i](2)>segments_[(i+1)%segments_.size()](2))
00362 weight = segments_[i](3);
00363 else
00364 weight = segments_[(i+1)%segments_.size()](3);
00365 const float p2 = r(2)+0.001f;
00366
00367 const float ramp = std::max((p1-0.001f)/weight,r(2)/r(3));
00368 const bool out = n1.dot(r.head<2>()-segments_[i].head<2>())<0;
00369 const float w1 = (!out?1.f:ramp);
00370 const float w2 = (out?1.f:ramp);
00371 r2.head<2>() = w1*p2/(w2*p1+w1*p2)*(r.head<2>()-segments_[i].head<2>()) + segments_[i].head<2>();
00372 r2(2) = (p1+p2-0.002f)/(weight+r(3));
00373
00374 res += r2;
00375
00376
00377
00378
00379
00380 }
00381
00382
00383 }
00384 if(start_ind!=last_ind&&proc)
00385 run2(o, segments_, last_ind, start_ind, res, false);
00386 }
00387
00388 #if 0
00389 void run(const Outline &o, const size_t begin, const size_t end, Outline &res, const bool proc=true) const {
00390 size_t last_ind, start_ind;
00391 bool start = true;
00392 Eigen::Vector3f r2;
00393
00394 ROS_ERROR("%d %d",begin, end);
00395 for(size_t j=begin; j<(end>begin?end:end+segments_.size()); j++)
00396 {
00397 size_t i = j%segments_.size();
00398
00399 Eigen::Vector2f n1,n2;
00400 Eigen::Vector3f r;
00401 n1=segments_[i].head<2>()-segments_[(i-1+segments_.size())%segments_.size()].head<2>();
00402 n1.normalize();
00403 n2=segments_[(i+1)%segments_.size()].head<2>()-segments_[i].head<2>();
00404 n2.normalize();
00405 n2+=n1;
00406 n1(0) = -n2(1);
00407 n1(1) = n2(0);
00408 size_t ind = o.nextLine(segments_[i].head<2>(), n1, r);
00409 if(ind!=(size_t)-1) {
00410 ROS_ERROR("%d",ind);
00411 if(!start && ind!=last_ind && proc) {
00412 o.run(*this, last_ind, ind, res, false);
00413
00414
00415 }
00416 else if(start) {
00417 start = false;
00418 start_ind = ind;
00419 }
00420 last_ind = ind;
00421
00422 const float p1 = std::max(segments_[i](2), segments_[(i+1)%segments_.size()](2))+0.001f;
00423 const float p2 = r(2)+0.001f;
00424
00425 const float ramp = std::max((p1-0.001f)/weight_,(p2-0.001f)/o.weight_);
00426 const bool out = n1.dot(r.head<2>()-segments_[i].head<2>())<0;
00427 const float w1 = (!out?1.f:ramp);
00428 const float w2 = (out?1.f:ramp);
00429 r2.head<2>() = w1*p2/(w2*p1+w1*p2)*(r.head<2>()-segments_[i].head<2>()) + segments_[i].head<2>();
00430 r2(2) = (p1+p2-0.002f)/(o.weight_+weight_);
00431
00432 res += r2;
00433
00434
00435
00436
00437
00438 }
00439
00440
00441 }
00442 if(start_ind!=last_ind&&proc)
00443 o.run(*this, last_ind, start_ind, res, false);
00444 }
00445 #endif
00446
00447 #if 0
00448 void run(const Outline &o, const size_t begin, const size_t end, Outline &res, const bool proc=true) const {
00449 size_t last_ind, start_ind;
00450 bool start = true;
00451 Eigen::Vector3f r2;
00452
00453 ROS_ERROR("%d %d",begin, end);
00454 for(size_t j=begin; j<(end>begin?end:end+segments_.size()); j++)
00455 {
00456 size_t i = j%segments_.size();
00457
00458 size_t ind = o._nextPoint(segments_[i].head<2>());
00459 if(ind!=(size_t)-1) {
00460 ROS_ERROR("%d",ind);
00461 if(!start && ind!=last_ind && proc) {
00462 o.run(*this, last_ind+1, ind, res, false);
00463
00464
00465 }
00466 else if(start) {
00467 start = false;
00468 start_ind = ind;
00469 }
00470 last_ind = ind;
00471
00472 Eigen::Vector2f n = segments_[i].head<2>()-segments_[(i+1)%segments_.size()].head<2>();
00473 std::swap(n(0),n(1));
00474 n(0) = -n(0);
00475
00476 const float p1 = std::max(segments_[i](2), segments_[(i+1)%segments_.size()](2))+0.001f;
00477 const float p2 = std::max(o.segments_[ind](2), o.segments_[(ind+1)%segments_.size()](2))+0.001f;
00478
00479 const float ramp = std::max((p1-0.001f)/weight_,(p2-0.001f)/o.weight_);
00480 const bool out = n.dot(o.segments_[ind].head<2>()-segments_[i].head<2>())<0;
00481 const float w1 = (!out?1.f:ramp);
00482 const float w2 = (out?1.f:ramp);
00483 r2.head<2>() = w1*p2/(w2*p1+w1*p2)*(o.segments_[ind].head<2>()-segments_[i].head<2>()) + segments_[i].head<2>();
00484 r2(2) = (p1+p2-0.002f)/(o.weight_+weight_);
00485
00486 res += r2;
00487
00488
00489
00490
00491
00492 }
00493
00494
00495 }
00496 if(start_ind!=last_ind&&proc)
00497 o.run(*this, last_ind+1, start_ind, res, false);
00498 }
00499 #endif
00500
00501 #if 0
00502 void run(const Outline &o, const size_t begin, const size_t end, Outline &res, const bool proc=true) const {
00503 size_t last_ind, start_ind;
00504 bool start = true;
00505 Eigen::Vector3f r2;
00506
00507 ROS_ERROR("%d %d",begin, end);
00508 for(size_t j=begin; j<(end>begin?end:end+segments_.size()); j++)
00509 {
00510 size_t i = j%segments_.size();
00511
00512 size_t ind = o._nextPoint2(segments_[i].head<2>());
00513 if(ind!=(size_t)-1) {
00514 ROS_ERROR("%d",ind);
00515 if(!start && ind!=last_ind && proc) {
00516 o.run(*this, last_ind+1, ind, res, false);
00517
00518
00519 }
00520 else if(start) {
00521 start = false;
00522 start_ind = ind;
00523 }
00524 last_ind = ind;
00525
00526 Eigen::Vector2f n = segments_[i].head<2>()-segments_[(i+1)%segments_.size()].head<2>();
00527 std::swap(n(0),n(1));
00528 n(0) = -n(0);
00529
00530 const float p1 = std::max(segments_[i](2), segments_[(i+1)%segments_.size()](2))+0.001f;
00531 const float p2 = std::max(o.segments_[ind](2), o.segments_[(ind+1)%segments_.size()](2))+0.001f;
00532
00533 const float ramp = std::max((p1-0.001f)/weight_,(p2-0.001f)/o.weight_);
00534 const bool out = n.dot(o.segments_[ind].head<2>()-segments_[i].head<2>())<0;
00535 const float w1 = (!out?1.f:ramp);
00536 const float w2 = (out?1.f:ramp);
00537 r2.head<2>() = w1*p2/(w2*p1+w1*p2)*(o.segments_[ind].head<2>()-segments_[i].head<2>()) + segments_[i].head<2>();
00538 r2(2) = (p1+p2-0.002f)/(o.weight_+weight_);
00539
00540 res += r2;
00541
00542
00543
00544
00545
00546 }
00547
00548
00549 }
00550 if(start_ind!=last_ind&&proc)
00551 o.run(*this, last_ind+1, start_ind, res, false);
00552 }
00553 #endif
00554
00555 bool isPointIn(const Eigen::Vector2f &pt) const {
00556 bool c=false;
00557 size_t j=segments_.size()-1;
00558 for(size_t i=0; i<segments_.size(); i++)
00559 {
00560 if( (segments_[i](1)>pt(1))!=(segments_[j](1)>pt(1)) &&
00561 (pt(0)<(segments_[j](0)-segments_[i](0))*(pt(1)-segments_[i](1))/(segments_[j](1)-segments_[i](1))+segments_[i](0))
00562 )
00563 c=!c;
00564 j=i;
00565 }
00566 return c;
00567 }
00568
00569 bool check() const {
00570 bool ASS=true;
00571
00572 for(size_t i=0; i<size(); i++)
00573 {
00574 size_t id = _hasIntersection(*this, (*this)[i].head<2>(), (*this)[(i+1)%size()].head<2>());
00575 if(id && id-1!=i) {
00576 ROS_ERROR("err at %d (%d)",i,id-1);
00577 ASS=false;
00578 break;
00579 }
00580 }
00581
00582 if(!ASS) {
00583 char buffer[128];
00584 static int n=0;
00585 sprintf(buffer, "error%d.svg",n++);
00586 debug_svg(buffer,300,600);
00587 }
00588
00589 return ASS;
00590 }
00591
00592 void run(const Outline &o, const size_t begin, const size_t end, Outline &res, const bool proc=true) const {
00593 std::vector<Eigen::Vector4f> inner, outer;
00594
00595 std::vector<Eigen::Vector4f> l1, l2;
00596 int type = -1;
00597
00598
00599 bool found=false, found1;
00600 size_t i=0;
00601 for(; i<segments_.size(); i++)
00602 {
00603 if(o.isPointIn(segments_[i].head<2>())) {
00604 found=true;
00605 break;
00606 }
00607 }
00608 found1 = found;
00609
00610 if(found==false)
00611 {
00612 for(size_t i=0; i<o.segments_.size(); i++)
00613 {
00614 if(isPointIn(o.segments_[i].head<2>())) {
00615 found=true;
00616 break;
00617 }
00618 }
00619 }
00620
00621 if(found)
00622 {
00623
00624 bool other=false;
00625 size_t j=0, last_j=0, start_j=0;
00626 for(size_t kk=0; kk<segments_.size(); kk++)
00627 {
00628 i%=segments_.size();
00629
00630 Eigen::Matrix2f M;
00631 Eigen::Vector2f p1 = segments_[i].head<2>();
00632 Eigen::Vector2f p2 = segments_[(i+1)%segments_.size()].head<2>();
00633
00634 Eigen::Vector4f p14;
00635 p14.head<3>() = segments_[i];
00636 p14(3) = weight_;
00637 l1.push_back(p14);
00638
00639 M.col(0) = p2-p1;
00640
00641 if(type==-1)
00642 {
00643 float mi=10;
00644 size_t mm=0;
00645 for(size_t k=0; k<o.segments_.size(); k++)
00646 {
00647 j%=o.segments_.size();
00648 Eigen::Vector2f p3 = o.segments_[j].head<2>();
00649 Eigen::Vector2f p4 = o.segments_[(j+1)%o.segments_.size()].head<2>();
00650
00651 M.col(1) = p3-p4;
00652
00653 Eigen::Vector2f m = (M.inverse()*(p3-p1));
00654
00655 if(m(0)>=0.f && m(0)<1.f && m(1)>=0.f && m(1)<1.f)
00656 {
00657 if(m(0)<mi) {
00658 mi=m(0);
00659 mm=j;
00660 }
00661 }
00662
00663 ++j;
00664 }
00665
00666 if(mi<=1)
00667 j=mm;
00668 }
00669 for(size_t k=0; k<o.segments_.size(); k++)
00670 {
00671 j%=o.segments_.size();
00672 Eigen::Vector2f p3 = o.segments_[j].head<2>();
00673 Eigen::Vector2f p4 = o.segments_[(j+1)%o.segments_.size()].head<2>();
00674
00675 M.col(1) = p3-p4;
00676
00677 Eigen::Vector2f m = (M.inverse()*(p3-p1));
00678
00679 if(m(0)>0.f && m(0)<1.f && m(1)>0.f && m(1)<1.f)
00680 {
00681 Eigen::Vector3f v1,v2;
00682 v1.head<2>() = M.col(0);
00683 v2.head<2>() = M.col(1);
00684 v1(2)=v2(2)=0;
00685 const bool out = v1.cross(v2)(2)<=0;
00686
00687
00688
00689 if(type!=-1) {
00690 size_t end = j;
00691
00692 if(last_j!=end)
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 for(size_t t=(last_j+1)%o.segments_.size(); true; t=(t+1)%o.segments_.size()) {
00704 Eigen::Vector4f p34;
00705 p34.head<3>() = o.segments_[t];
00706 p34(3) = o.weight_;
00707 l2.push_back(p34);
00708
00709 if(t==end)
00710 break;
00711 }
00712 }
00713 else
00714 start_j = j;
00715
00716 Eigen::Vector4f p;
00717 p.head<2>() = m(0)*M.col(0) + p1;
00718
00719 p(2) = segments_[i](2);
00720 p(3) = weight_;
00721 l1.push_back(p);
00722 p(2) = o.segments_[j](2);
00723 p(3) = o.weight_;
00724 l2.push_back(p);
00725
00726
00727 std::vector<Eigen::Vector4f> *pl1=&l1, *pl2=&l2;
00728 if(out) {
00729 std::swap(pl1,pl2);
00730 type=0;
00731 }
00732 else
00733 type=1;
00734
00735
00736
00737 for(size_t l=0; l<pl1->size(); l++)
00738 inner.push_back( (*pl1)[l] );
00739 for(size_t l=0; l<pl2->size(); l++)
00740 outer.push_back( (*pl2)[l] );
00741
00742
00743
00744
00745 l1.clear();
00746 l2.clear();
00747
00748 last_j=j;
00749
00750 if(last_j!=start_j)
00751 other=true;
00752 }
00753
00754 ++j;
00755 }
00756 j=last_j;
00757
00758 ++i;
00759 }
00760
00761 std::vector<Eigen::Vector4f> *pl1=&l1, *pl2=&l2;
00762 if(type==1) {
00763 std::swap(pl1,pl2);
00764 }
00765 if(type==1 || type==0) {
00766
00767 if(last_j!=start_j || !other)
00768 for(size_t t=(last_j+1)%o.segments_.size(); true; t=(t+1)%o.segments_.size()) {
00769 Eigen::Vector4f p34;
00770 p34.head<3>() = o.segments_[t];
00771 p34(3) = o.weight_;
00772 l2.push_back(p34);
00773
00774 if(t==start_j)
00775 break;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786 for(size_t l=0; l<pl1->size(); l++)
00787 inner.push_back( (*pl1)[l] );
00788 for(size_t l=0; l<pl2->size(); l++)
00789 outer.push_back( (*pl2)[l] );
00790 }
00791
00792 }
00793
00794 if(type==-1)
00795 {
00796 Eigen::Vector4f v;
00797 for(size_t l=0; l<segments_.size(); l++) {
00798 v.head<3>() = segments_[l];
00799 v(3) = weight_;
00800 outer.push_back( v );
00801 }
00802 for(size_t l=0; l<o.segments_.size(); l++) {
00803 v.head<3>() = o.segments_[l];
00804 v(3) = o.weight_;
00805 inner.push_back( v );
00806 }
00807
00808 if(found1)
00809 std::swap(outer,inner);
00810 }
00811
00812
00813
00814 if(!(outer.size()<=2*(size()+o.size())) || !(inner.size()<=2*(size()+o.size())))
00815 {
00816 o.debug_svg(debug_svg("error.svg"),100,300,"red");
00817
00818 Outline oi, oo;
00819 for(size_t i=0; i<inner.size(); i++)
00820 {
00821 Eigen::Vector3f r2;
00822 r2.head<2>() = inner[i].head<2>();
00823 r2(2) = inner[i](2)/inner[i](3);
00824 oi += r2;
00825 }
00826 for(size_t i=0; i<outer.size(); i++)
00827 {
00828 Eigen::Vector3f r2;
00829 r2.head<2>() = outer[i].head<2>();
00830 r2(2) = outer[i](2)/outer[i](3);
00831 oo += r2;
00832 }
00833 oo.debug_svg(oi.debug_svg("error_io.svg"),100,300,"red");
00834 }
00835
00836
00837
00838
00839
00840 #if 1
00841 bool ASS=false;
00842
00843 for(size_t i=0; i<outer.size(); i++)
00844 {
00845 Eigen::Vector3f r2;
00846 Eigen::Vector4f r;
00847
00848 size_t ind = _nextPoint3(inner,outer[i].head<2>(),r);
00849
00850 if(0&&ind<inner.size())
00851 {
00852
00853 const float p1 = outer[i](2)+0.001f;
00854 float weight = outer[i](3);
00855 const float p2 = r(2)+0.001f;
00856
00857 const float ramp = std::max((p1-0.001f)/weight,r(2)/r(3));
00858 const float w1 = ramp;
00859 const float w2 = 1.f;
00860 ROS_ERROR("%f %f",ramp,w1*p2/(w2*p1+w1*p2));
00861
00862 r2.head<2>() = w1*p2/(w2*p1+w1*p2)*(r.head<2>()-outer[i].head<2>()) + outer[i].head<2>();
00863 r2(2) = (w2*p1+w1*p2-0.002f)/(w2*weight+w1*r(3));
00864 }
00865 else
00866 {
00867 r2.head<2>() = outer[i].head<2>();
00868 r2(2) = outer[i](2)/outer[i](3);
00869 }
00870
00871 if(res.size() && _hasIntersection(res,res.segments_.back().head<2>(),r2.head<2>(), true)) {
00872 o.debug_svg(debug_svg("error.svg",300,600),300,600,"red");
00873
00874 Outline oi, oo;
00875 for(size_t i=0; i<inner.size(); i++)
00876 {
00877 Eigen::Vector3f r2;
00878 r2.head<2>() = inner[i].head<2>();
00879 r2(2) = inner[i](2)/inner[i](3);
00880 oi += r2;
00881 }
00882 for(size_t i=0; i<outer.size(); i++)
00883 {
00884 Eigen::Vector3f r2;
00885 r2.head<2>() = outer[i].head<2>();
00886 r2(2) = outer[i](2)/outer[i](3);
00887 oo += r2;
00888 }
00889 oo.debug_svg(oi.debug_svg("error_io.svg",300,600),300,600,"red");
00890 ASS=true;
00891 break;
00892 }
00893
00894 res += r2;
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 if(ASS) {
00906 res.debug_svg(o.debug_svg(debug_svg("error.svg",300,600),300,600,"red"),300,600,"green");
00907 }
00908
00909 #endif
00910 if(!res.check()) {
00911 res.debug_svg(o.debug_svg(debug_svg("error.svg",300,600),300,600,"red"),300,600,"green");
00912
00913 Outline oi, oo;
00914 for(size_t i=0; i<inner.size(); i++)
00915 {
00916 Eigen::Vector3f r2;
00917 r2.head<2>() = inner[i].head<2>();
00918 r2(2) = inner[i](2)/inner[i](3);
00919 oi += r2;
00920 }
00921 for(size_t i=0; i<outer.size(); i++)
00922 {
00923 Eigen::Vector3f r2;
00924 r2.head<2>() = outer[i].head<2>();
00925 r2(2) = outer[i](2)/outer[i](3);
00926 oo += r2;
00927 }
00928 oo.debug_svg(oi.debug_svg("error_io.svg"),100,300,"red");
00929
00930 }
00931 }
00932
00933 Outline operator+(const Outline &o) const
00934 {
00935
00936
00937 Outline res;
00938 run(o, 0, segments_.size(), res);
00939
00940
00941
00942
00943 return res;
00944 }
00945
00946 #if 0
00947 Outline operator+(const Outline &o) const
00948 {
00949
00950 std::vector<COR> cors;
00951
00952 for(size_t i=0; i<o.segments_.size(); i++)
00953 {
00954 COR c;
00955 c.other = true;
00956 c.ind = i;
00957 cors.push_back(c);
00958 }
00959
00960 for(size_t i=0; i<segments_.size(); i++)
00961 {
00962 bool out = false;
00963 float mi = std::numeric_limits<float>::max(), mi2 = std::numeric_limits<float>::max();
00964 Eigen::Vector2f nmi = Eigen::Vector2f::Zero();
00965 size_t ind=cors.size();
00966 for(size_t j=0; j<cors.size(); j++)
00967 {
00968 if(!cors[j].other) continue;
00969
00970 Eigen::Vector2f n;
00971 Eigen::Vector2f p1,p2, x, x2, d1,d2;
00972 x = segments_[i].head<2>();
00973 x2 = segments_[(i+1)%segments_.size()].head<2>();
00974 p1 = o.segments_[cors[j].ind].head<2>();
00975 p2 = o.segments_[(cors[j].ind+1)%o.segments_.size()].head<2>();
00976
00977 d1 = (x-p1);
00978 d2 = p2-p1;
00979 float f = d1.dot(d2)/d2.squaredNorm();
00980 float d;
00981 if(f>1){
00982 d = (x-p2).norm();
00983 n = p2-x;
00984 }
00985 else if(f<0) {
00986 d = d1.norm();
00987 n = p1-x;
00988 }
00989 else {
00990 d = (d1(0)*d2(1)-d1(1)*d2(0))/(d2).norm();
00991 n(0) = -(p2(1)-p1(1));
00992 n(1) = (p2(0)-p1(0));
00993 }
00994
00995 const float dd = d / std::max(0.0001f, (x-x2).dot(p1-p2)/((x-x2).norm()*(p1-p2).norm()) );
00996
00997
00998
00999 if(std::abs(dd)<std::abs(mi2))
01000 {
01001 nmi = n;
01002 mi = d;
01003 mi2 = dd;
01004 ind = j;
01005 out = d*(-d2(1)*n(0)+d2(0)*n(1))>-0.001f;
01006
01007 }
01008 }
01009
01010 if(cors.size()==ind)
01011 return Outline();
01012
01013 ROS_ASSERT(cors.size()!=ind);
01014
01015
01016
01017 for(size_t k=0; k<cors.size(); k++)
01018 {
01019 ind = (ind+1)%cors.size();
01020
01021 if(cors[ind].other || std::abs((int)cors[ind].ind-(int)i)>std::abs((int)cors[ind].ind+segments_.size()-(int)i))
01022 break;
01023 }
01024
01025 COR c;
01026 c.other = false;
01027 c.ind = i;
01028 const float p1 = std::min(segments_[i](2), segments_[(i+1)%segments_.size()](2))+0.001f;
01029 const float p2 = o.segments_[(cors[ind].ind-1+o.segments_.size())%o.segments_.size()](2)+0.001f;
01030 nmi/=nmi.norm();
01031 const float ramp = std::max((p1-0.001f)/weight_,(p2-0.001f)/o.weight_);
01032 const float w1 = (!out?1.f:ramp);
01033 const float w2 = (out?1.f:ramp);
01034 c.p.head<2>() = w1*p2/(w2*p1+w1*p2)*mi*nmi + segments_[i].head<2>();
01035
01036 c.p(2) = (p1+p2-0.002f)/(o.weight_+weight_);
01037 cors.insert(cors.begin()+ind, c);
01038
01039 std::cout<<"p1 "<<p1/weight_<<" p2 "<<p2/o.weight_<<" --> "<<c.p(2)<<"\n";
01040 }
01041
01042
01043
01044
01045
01046
01047 for(size_t j=0; j<cors.size(); j++)
01048 {
01049 if(!cors[j].other) {
01050
01051 continue;
01052 }
01053
01054 size_t next = j+1, bef = j-1;
01055 for(size_t i=0; i<cors.size(); i++)
01056 {
01057 ROS_ASSERT(i+1!=cors.size());
01058
01059 next %= cors.size();
01060 bef += cors.size();
01061 bef %= cors.size();
01062
01063 if(!cors[next].other && !cors[bef].other) break;
01064
01065 if(cors[next].other) next++;
01066 if(cors[bef].other) bef--;
01067 }
01068
01069 ROS_ASSERT(!cors[next].other);
01070 ROS_ASSERT(!cors[bef].other);
01071
01072 bef = cors[bef].ind;
01073 next= cors[next].ind;
01074
01075 float d;
01076 Eigen::Vector2f n,x;
01077 bool out;
01078 {
01079 Eigen::Vector2f p1,p2, d1,d2;
01080 x = o.segments_[cors[j].ind].head<2>();
01081 p1 = segments_[bef].head<2>();
01082 p2 = segments_[next].head<2>();
01083
01084 d1 = (x-p1);
01085 d2 = p2-p1;
01086 float f = d1.dot(d2)/d2.squaredNorm();
01087 if(f>1){
01088 d = (x-p2).norm();
01089 n = p2-x;
01090 }
01091 else if(f<0) {
01092 d = d1.norm();
01093 n = p1-x;
01094 }
01095 else {
01096 d = (d1(0)*d2(1)-d1(1)*d2(0))/(d2).norm();
01097 n(0) = -(p2(1)-p1(1));
01098 n(1) = (p2(0)-p1(0));
01099 }
01100
01101 out = d*(-d2(1)*n(0)+d2(0)*n(1))>-0.001f;
01102 }
01103
01104
01105
01106
01107 const float p1 = std::min(o.segments_[cors[j].ind](2), o.segments_[(cors[j].ind+1)%o.segments_.size()](2))+0.001f;
01108 const float p2 = segments_[next](2)+0.001f;
01109 n/=n.norm();
01110 const float ramp = std::max((p1-0.001f)/o.weight_,(p2-0.001f)/weight_);
01111 const float w1 = (!out?1.f:ramp);
01112 const float w2 = (out?1.f:ramp);
01113 cors[j].p.head<2>() = w1*p2/(w2*p1+w1*p2)*d*n + x;
01114
01115 cors[j].p(2) = (p1+p2-0.002f)/(o.weight_+weight_);
01116
01117
01118 std::cout<<"p1 "<<p1/o.weight_<<" p2 "<<p2/weight_<<" --> "<<cors[j].p(2)<<"\n";
01119
01120
01121
01122 }
01123
01124 ROS_ASSERT(cors.size() == (segments_.size()+o.segments_.size()) );
01125
01126 Outline res;
01127
01128 for(size_t j=0; j<cors.size(); j++)
01129 {
01130 res += cors[j].p;
01131 }
01132
01133 return res;
01134 }
01135 #endif
01136
01137 Outline operator|(const Outline &o) const
01138 {
01139
01140 std::vector<COR> cors;
01141
01142 for(size_t i=0; i<o.segments_.size(); i++)
01143 {
01144 COR c;
01145 c.other = true;
01146 c.ind = i;
01147 cors.push_back(c);
01148 }
01149
01150 if(cors.size()<2)
01151 return *this;
01152
01153 size_t num_last = cors.size();
01154
01155 for(size_t i=0; i<segments_.size(); i++)
01156 {
01157 bool out = false;
01158 float mi = std::numeric_limits<float>::max();
01159 Eigen::Vector2f nmi = Eigen::Vector2f::Zero();
01160 size_t ind=cors.size();
01161 for(size_t j=0; j<cors.size(); j++)
01162 {
01163 if(!cors[j].other) continue;
01164
01165 Eigen::Vector2f n;
01166 Eigen::Vector2f p1,p2, x, d1,d2;
01167 x = segments_[i].head<2>();
01168 p1 = o.segments_[cors[j].ind].head<2>();
01169 p2 = o.segments_[(cors[j].ind+1)%o.segments_.size()].head<2>();
01170
01171 d1 = (x-p1);
01172 d2 = p2-p1;
01173 float f = d1.dot(d2)/d2.squaredNorm();
01174 float d;
01175 if(f>1){
01176 d = (x-p2).norm();
01177 n = p2-x;
01178 }
01179 else if(f<0) {
01180 d = d1.norm();
01181 n = p1-x;
01182 }
01183 else {
01184 d = (d1(0)*d2(1)-d1(1)*d2(0))/(d2).norm();
01185 n(0) = -(p2(1)-p1(1));
01186 n(1) = (p2(0)-p1(0));
01187 }
01188
01189 ROS_INFO("%f %f %f",f,d,mi);
01190
01191 if(std::abs(d)<std::abs(mi))
01192 {
01193 nmi = n;
01194 mi = d;
01195 ind = j;
01196 out = d*(-d2(1)*n(0)+d2(0)*n(1))>0.001f;
01197 ROS_INFO("out2 %f",d*(-d2(1)*n(0)+d2(0)*n(1)));
01198 }
01199 }
01200
01201 if(out) continue;
01202
01203 if(cors.size()==ind)
01204 return Outline();
01205
01206 ROS_ASSERT(cors.size()!=ind);
01207
01208 ROS_INFO("-------------");
01209
01210 for(size_t k=0; k<cors.size(); k++)
01211 {
01212 ind = (ind+1)%cors.size();
01213 ROS_INFO("cmp %d %d", (int)std::abs((int)cors[ind].ind-(int)i), (int)std::abs((int)cors[ind].ind+segments_.size()-(int)i));
01214 if(cors[ind].other || std::abs((int)cors[ind].ind-(int)i)>std::abs((int)cors[ind].ind+segments_.size()-(int)i))
01215 break;
01216 }
01217
01218 COR c;
01219 c.other = false;
01220 c.ind = i;
01221 const float p1 = std::max(segments_[i](2), segments_[(i+1)%segments_.size()](2))+0.001f;
01222 const float p2 = o.segments_[(cors[ind].ind-1+o.segments_.size())%o.segments_.size()](2)+0.001f;
01223 nmi/=nmi.norm();
01224 c.p.head<2>() = p2*mi*nmi + segments_[i].head<2>();
01225 c.p(2) = std::max(p1,p2)-0.001f;
01226 cors.insert(cors.begin()+ind, c);
01227 }
01228
01229 if(cors.size()-num_last<2)
01230 return o;
01231
01232 for(size_t j=0; j<cors.size(); j++)
01233 {
01234 if(!cors[j].other) {
01235 ROS_INFO("%d", (int)cors[j].ind);
01236 continue;
01237 }
01238
01239 size_t next = j+1, bef = j-1;
01240 for(size_t i=0; i<cors.size(); i++)
01241 {
01242 ROS_ASSERT(i+1!=cors.size());
01243
01244 next %= cors.size();
01245 bef += cors.size();
01246 bef %= cors.size();
01247
01248 if(!cors[next].other && !cors[bef].other) break;
01249
01250 if(cors[next].other) next++;
01251 if(cors[bef].other) bef--;
01252 }
01253
01254 ROS_ASSERT(!cors[next].other);
01255 ROS_ASSERT(!cors[bef].other);
01256
01257 bef = cors[bef].ind;
01258 next= cors[next].ind;
01259
01260 float d;
01261 Eigen::Vector2f n,x;
01262 bool out;
01263 {
01264 Eigen::Vector2f p1,p2, d1,d2;
01265 x = o.segments_[cors[j].ind].head<2>();
01266 p1 = segments_[bef].head<2>();
01267 p2 = segments_[next].head<2>();
01268
01269 d1 = (x-p1);
01270 d2 = p2-p1;
01271 float f = d1.dot(d2)/d2.squaredNorm();
01272 if(f>1){
01273 d = (x-p2).norm();
01274 n = p2-x;
01275 }
01276 else if(f<0) {
01277 d = d1.norm();
01278 n = p1-x;
01279 }
01280 else {
01281 d = (d1(0)*d2(1)-d1(1)*d2(0))/(d2).norm();
01282 n(0) = -(p2(1)-p1(1));
01283 n(1) = (p2(0)-p1(0));
01284 }
01285
01286 out = d*(-d2(1)*n(0)+d2(0)*n(1))>0.001f;
01287
01288
01289 }
01290
01291 if(out) continue;
01292
01293 std::cout<<segments_[bef].head<2>()<<"\n";
01294 std::cout<<segments_[next].head<2>()<<"\n";
01295
01296 const float p1 = std::max(o.segments_[cors[j].ind](2), o.segments_[(cors[j].ind+1)%o.segments_.size()](2))+0.001f;
01297 const float p2 = segments_[next](2)+0.001f;
01298 n/=n.norm();
01299 cors[j].p.head<2>() = p2*d*n + x;
01300 cors[j].p(2) = std::max(p1,p2)-0.001f;
01301
01302
01303 std::cout<<o.segments_[cors[j].ind]<<"\n\n";
01304 std::cout<<n<<"\n\n";
01305 std::cout<<cors[j].p<<"\n\n";
01306 }
01307
01308 Outline res;
01309
01310 for(size_t j=0; j<cors.size(); j++)
01311 {
01312 res += cors[j].p;
01313 }
01314
01315 return res;
01316 }
01317
01318 void reverse(const bool fw=true)
01319 {
01320 if(segments_.size()<2) return;
01321
01322 if(fw)
01323 {
01324 float t = segments_[segments_.size()-1](2);
01325 for(size_t i=0; i<segments_.size()-1; i++)
01326 {
01327 segments_[(i-1+segments_.size())%segments_.size()](2) = segments_[i](2);
01328 ROS_INFO("gets %f", segments_[i](2));
01329 }
01330 segments_[(segments_.size()-2)%segments_.size()](2) = t;
01331 }
01332 else
01333 {
01334 float t = segments_[0](2);
01335 for(size_t i=segments_.size()-1; i>0; i--)
01336 {
01337 segments_[(i+1)%segments_.size()](2) = segments_[i](2);
01338 }
01339 segments_[1](2) = t;
01340 }
01341
01342 std::reverse(segments_.begin(), segments_.end());
01343 }
01344
01345 inline size_t size() const {return segments_.size();}
01346 inline Eigen::Vector3f &operator[](const size_t ind) {return segments_[ind];}
01347 inline Eigen::Vector3f operator[](const size_t ind) const {return segments_[ind];}
01348 inline const std::vector<Eigen::Vector3f> &get() const {return segments_;}
01349
01350 Eigen::Vector3f nextPoint(const Eigen::Vector3f &search) const {
01351 bool out = false;
01352 float mi = std::numeric_limits<float>::max();
01353 Eigen::Vector2f nmi = Eigen::Vector2f::Zero();
01354 size_t ind=segments_.size();
01355 for(size_t j=0; j<segments_.size(); j++)
01356 {
01357 Eigen::Vector2f n;
01358 Eigen::Vector2f p1,p2, x, d1,d2;
01359 x = search.head<2>();
01360 p1 = segments_[j].head<2>();
01361 p2 = segments_[(j+1)%segments_.size()].head<2>();
01362
01363 d1 = (x-p1);
01364 d2 = p2-p1;
01365 float f = d1.dot(d2)/d2.squaredNorm();
01366 float d;
01367 if(f>1){
01368 d = (x-p2).norm();
01369 n = p2-x;
01370 }
01371 else if(f<0) {
01372 d = d1.norm();
01373 n = p1-x;
01374 }
01375 else {
01376 d = (d1(0)*d2(1)-d1(1)*d2(0))/(d2).norm();
01377 n(0) = -(p2(1)-p1(1));
01378 n(1) = (p2(0)-p1(0));
01379 }
01380
01381 if(std::abs(d)<std::abs(mi))
01382 {
01383 nmi = n;
01384 mi = d;
01385 ind = j;
01386 out = d*(-d2(1)*n(0)+d2(0)*n(1))>-0.001f;
01387 }
01388 }
01389
01390 if(segments_.size()==ind) {
01391 ROS_ERROR("err X7Z");
01392 return search;
01393 }
01394
01395 Eigen::Vector3f r;
01396 r(2) = segments_[(ind+segments_.size())%segments_.size()](2);
01397 nmi/=nmi.norm();
01398 r.head<2>() = r(2)*mi*nmi + search.head<2>();
01399
01400 return r;
01401 }
01402 };
01403
01404
01405 }
01406
01407
01408 #endif