Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpMbTracker.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Generic model based tracker
32  *
33  * Authors:
34  * Romain Tallonneau
35  * Aurelien Yol
36  * Eric Marchand
37  *
38  *****************************************************************************/
39 
45 #include <iostream>
46 #include <limits>
47 #include <algorithm>
48 #include <map>
49 
50 #include <visp3/core/vpMatrix.h>
51 #include <visp3/core/vpMath.h>
52 #include <visp3/core/vpColVector.h>
53 #include <visp3/core/vpPoint.h>
54 #include <visp3/vision/vpPose.h>
55 #include <visp3/core/vpDisplay.h>
56 #ifdef VISP_HAVE_MODULE_GUI
57 # include <visp3/gui/vpDisplayOpenCV.h>
58 # include <visp3/gui/vpDisplayX.h>
59 # include <visp3/gui/vpDisplayGDI.h>
60 #endif
61 #include <visp3/core/vpPixelMeterConversion.h>
62 #include <visp3/core/vpCameraParameters.h>
63 #include <visp3/core/vpColor.h>
64 #include <visp3/core/vpIoTools.h>
65 #include <visp3/core/vpException.h>
66 #ifdef VISP_HAVE_MODULE_IO
67 # include <visp3/io/vpImageIo.h>
68 #endif
69 #include <visp3/mbt/vpMbTracker.h>
70 #include <visp3/core/vpMatrixException.h>
71 #include <visp3/core/vpIoTools.h>
72 
73 #ifdef VISP_HAVE_COIN3D
74 //Inventor includes
75 #include <Inventor/nodes/SoSeparator.h>
76 #include <Inventor/VRMLnodes/SoVRMLIndexedFaceSet.h>
77 #include <Inventor/VRMLnodes/SoVRMLIndexedLineSet.h>
78 #include <Inventor/VRMLnodes/SoVRMLCoordinate.h>
79 #include <Inventor/actions/SoWriteAction.h>
80 #include <Inventor/actions/SoSearchAction.h>
81 #include <Inventor/misc/SoChildList.h>
82 #include <Inventor/actions/SoGetMatrixAction.h>
83 #include <Inventor/actions/SoGetPrimitiveCountAction.h>
84 #include <Inventor/actions/SoToVRML2Action.h>
85 #include <Inventor/VRMLnodes/SoVRMLGroup.h>
86 #include <Inventor/VRMLnodes/SoVRMLTransform.h>
87 #include <Inventor/VRMLnodes/SoVRMLShape.h>
88 #endif
89 
90 
91 
92 #ifndef DOXYGEN_SHOULD_SKIP_THIS
93 
94 namespace {
98  struct SegmentInfo {
99  SegmentInfo() : extremities(), name(), useLod(false), minLineLengthThresh(0.) {}
100 
101  std::vector<vpPoint> extremities;
102  std::string name;
103  bool useLod;
104  double minLineLengthThresh;
105  };
106 
111  struct PolygonFaceInfo {
112  PolygonFaceInfo(const double dist, const vpPolygon &poly, const std::vector<vpPoint> &corners)
113  : distanceToCamera(dist), polygon(poly), faceCorners(corners) {}
114 
115  bool operator<(const PolygonFaceInfo &pfi) const {
116  return distanceToCamera < pfi.distanceToCamera;
117  }
118 
119  double distanceToCamera;
120  vpPolygon polygon;
121  std::vector<vpPoint> faceCorners;
122  };
123 }
124 #endif // DOXYGEN_SHOULD_SKIP_THIS
125 
132 : cam(), cMo(), oJo(6,6), isoJoIdentity(true), modelFileName(), modelInitialised(false),
133  poseSavingFilename(), computeCovariance(false), covarianceMatrix(), computeProjError(false),
134  projectionError(90.0), displayFeatures(false), m_w(), m_error(), m_optimizationMethod(vpMbTracker::GAUSS_NEWTON_OPT),
135  faces(), angleAppears( vpMath::rad(89) ), angleDisappears( vpMath::rad(89) ), distNearClip(0.001),
136  distFarClip(100), clippingFlag(vpPolygon3D::NO_CLIPPING), useOgre(false), ogreShowConfigDialog(false), useScanLine(false),
137  nbPoints(0), nbLines(0), nbPolygonLines(0), nbPolygonPoints(0), nbCylinders(0), nbCircles(0),
138  useLodGeneral(false), applyLodSettingInConfig(false), minLineLengthThresholdGeneral(50.0),
139  minPolygonAreaThresholdGeneral(2500.0), mapOfParameterNames()
140 {
141  oJo.eye();
142  //Map used to parse additional information in CAO model files,
143  //like name of faces or LOD setting
144  mapOfParameterNames["name"] = "string";
145  mapOfParameterNames["minPolygonAreaThreshold"] = "number";
146  mapOfParameterNames["minLineLengthThreshold"] = "number";
147  mapOfParameterNames["useLod"] = "boolean";
148 }
149 
154 {
155 }
156 
157 #ifdef VISP_HAVE_MODULE_GUI
158 
180 void
181 vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::string& initFile, const bool displayHelp)
182 {
183  vpHomogeneousMatrix last_cMo;
184  vpPoseVector init_pos;
185  vpImagePoint ip;
187 
188  std::string ext = ".init";
189  std::string str_pose = "";
190  size_t pos = (unsigned int)initFile.rfind(ext);
191 
192  // Load the last poses from files
193  std::fstream finitpos ;
194  std::fstream finit ;
195  char s[FILENAME_MAX];
196  if(poseSavingFilename.empty()){
197  if( pos == initFile.size()-ext.size() && pos != 0)
198  str_pose = initFile.substr(0,pos) + ".0.pos";
199  else
200  str_pose = initFile + ".0.pos";
201 
202  finitpos.open(str_pose.c_str() ,std::ios::in) ;
203  sprintf(s, "%s", str_pose.c_str());
204  }else{
205  finitpos.open(poseSavingFilename.c_str() ,std::ios::in) ;
206  sprintf(s, "%s", poseSavingFilename.c_str());
207  }
208  if(finitpos.fail() ){
209  std::cout << "cannot read " << s << std::endl << "cMo set to identity" << std::endl;
210  last_cMo.eye();
211  }
212  else{
213  for (unsigned int i = 0; i < 6; i += 1){
214  finitpos >> init_pos[i];
215  }
216 
217  finitpos.close();
218  last_cMo.buildFrom(init_pos) ;
219 
220  std::cout <<"last_cMo : "<<std::endl << last_cMo <<std::endl;
221 
223  display(I, last_cMo, cam, vpColor::green, 1, true);
224  vpDisplay::displayFrame(I, last_cMo, cam, 0.05, vpColor::green);
225  vpDisplay::flush(I);
226 
227  std::cout << "No modification : left click " << std::endl;
228  std::cout << "Modify initial pose : right click " << std::endl ;
229 
230  vpDisplay::displayText(I, 15, 10,
231  "left click to validate, right click to modify initial pose",
232  vpColor::red);
233 
234  vpDisplay::flush(I) ;
235 
236  while (!vpDisplay::getClick(I, ip, button)) ;
237  }
238 
239 
240  if (!finitpos.fail() && button == vpMouseButton::button1){
241  cMo = last_cMo ;
242  }
243  else
244  {
245  vpDisplay *d_help = NULL;
246 
247  vpDisplay::display(I) ;
248  vpDisplay::flush(I) ;
249 
250  vpPose pose ;
251 
252  pose.clearPoint() ;
253 
254  // file parser
255  // number of points
256  // X Y Z
257  // X Y Z
258 
259  double X,Y,Z ;
260 
261  if( pos == initFile.size()-ext.size() && pos != 0)
262  sprintf(s,"%s", initFile.c_str());
263  else
264  sprintf(s,"%s.init", initFile.c_str());
265 
266  std::cout << "Load 3D points from: " << s << std::endl ;
267  finit.open(s,std::ios::in) ;
268  if (finit.fail()){
269  std::cout << "cannot read " << s << std::endl;
270  throw vpException(vpException::ioError, "cannot read init file");
271  }
272 
273 #ifdef VISP_HAVE_MODULE_IO
274  //Display window creation and initialisation
275  try{
276  if(displayHelp){
277  std::string dispF;
278  if( pos == initFile.size()-ext.size() && pos != 0)
279  dispF = initFile.substr(0,pos) + ".ppm";
280  else
281  dispF = initFile + ".ppm";
282 
283  if (vpIoTools::checkFilename(dispF)) {
284  std::cout << "Load image to help initialization: " << dispF << std::endl;
285 #if defined VISP_HAVE_X11
286  d_help = new vpDisplayX ;
287 #elif defined VISP_HAVE_GDI
288  d_help = new vpDisplayGDI;
289 #elif defined VISP_HAVE_OPENCV
290  d_help = new vpDisplayOpenCV;
291 #endif
292 
293  vpImage<vpRGBa> Iref ;
294  vpImageIo::read(Iref, dispF) ;
295 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
296  d_help->init(Iref, I.display->getWindowXPosition()+(int)I.getWidth()+80, I.display->getWindowYPosition(),
297  "Where to initialize...") ;
298  vpDisplay::display(Iref) ;
299  vpDisplay::flush(Iref);
300 #endif
301  }
302  }
303  }
304  catch(...) {
305  if(d_help != NULL) {
306  delete d_help;
307  d_help = NULL;
308  }
309  }
310 #else //#ifdef VISP_HAVE_MODULE_IO
311  (void)(displayHelp);
312 #endif //#ifdef VISP_HAVE_MODULE_IO
313  char c;
314  // skip lines starting with # as comment
315  finit.get(c);
316  while (!finit.fail() && (c == '#')) {
317  finit.ignore(256, '\n');
318  finit.get(c);
319  }
320  finit.unget();
321 
322  unsigned int n ;
323  finit >> n ;
324  finit.ignore(256, '\n'); // skip the rest of the line
325  std::cout << "Number of 3D points " << n << std::endl ;
326  if (n > 100000) {
328  "Exceed the max number of points.");
329  }
330 
331  vpPoint *P = new vpPoint [n] ;
332  for (unsigned int i=0 ; i < n ; i++){
333  // skip lines starting with # as comment
334  finit.get(c);
335  while (!finit.fail() && (c == '#')) {
336  finit.ignore(256, '\n');
337  finit.get(c);
338  }
339  finit.unget();
340 
341  finit >> X ;
342  finit >> Y ;
343  finit >> Z ;
344  finit.ignore(256, '\n'); // skip the rest of the line
345 
346  std::cout << "Point " << i+1 << " with 3D coordinates: " << X << " " << Y << " " << Z << std::endl;
347  P[i].setWorldCoordinates(X,Y,Z) ; // (X,Y,Z)
348  }
349 
350  finit.close();
351 
353  bool isWellInit = false;
354  while(!isWellInit)
355  {
357  std::vector<vpImagePoint> mem_ip;
358  for(unsigned int i=0 ; i< n ; i++)
359  {
360  std::ostringstream text;
361  text << "Click on point " << i+1;
363  vpDisplay::displayText(I, 15, 10, text.str(), vpColor::red);
364  for (unsigned int k=0; k<mem_ip.size(); k++) {
365  vpDisplay::displayCross(I, mem_ip[k], 10, vpColor::green, 2) ;
366  }
367  vpDisplay::flush(I) ;
368 
369  std::cout << "Click on point " << i+1 << " ";
370  double x=0,y=0;
371  vpDisplay::getClick(I, ip) ;
372  mem_ip.push_back(ip);
373  vpDisplay::flush(I) ;
375  P[i].set_x(x);
376  P[i].set_y(y);
377 
378  std::cout << "with 2D coordinates: " << ip << std::endl;
379 
380  pose.addPoint(P[i]) ; // and added to the pose computation point list
381  }
382  vpDisplay::flush(I) ;
383  vpDisplay::display(I) ;
384 
385  vpHomogeneousMatrix cMo1, cMo2;
386  pose.computePose(vpPose::LAGRANGE, cMo1) ;
387  double d1 = pose.computeResidual(cMo1);
388  pose.computePose(vpPose::DEMENTHON, cMo2) ;
389  double d2 = pose.computeResidual(cMo2);
390 
391  if(d1 < d2){
392  cMo = cMo1;
393  }
394  else{
395  cMo = cMo2;
396  }
398 
399  display(I, cMo, cam, vpColor::green, 1, true);
400  vpDisplay::displayText(I, 15, 10,
401  "left click to validate, right click to re initialize object",
402  vpColor::red);
403 
404  vpDisplay::flush(I) ;
405 
406  button = vpMouseButton::button1;
407  while (!vpDisplay::getClick(I, ip, button)) ;
408 
409 
410  if (button == vpMouseButton::button1)
411  {
412  isWellInit = true;
413  }
414  else
415  {
416  pose.clearPoint() ;
417  vpDisplay::display(I) ;
418  vpDisplay::flush(I) ;
419  }
420  }
423 
424  delete [] P;
425 
426  //save the pose into file
427  if(poseSavingFilename.empty())
428  savePose(str_pose);
429  else
431 
432  if(d_help != NULL) {
433  delete d_help;
434  d_help = NULL;
435  }
436  }
437 
438  std::cout <<"cMo : "<<std::endl << cMo <<std::endl;
439 
440  init(I);
441 }
442 
452 void vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::vector<vpPoint> &points3D_list,
453  const std::string &displayFile)
454 {
455  vpDisplay::display(I) ;
456  vpDisplay::flush(I) ;
457  vpDisplay *d_help = NULL;
458 
459  vpPose pose ;
460  std::vector<vpPoint> P;
461  for (unsigned int i=0 ; i < points3D_list.size() ; i++)
462  P.push_back( vpPoint(points3D_list[i].get_oX(), points3D_list[i].get_oY(), points3D_list[i].get_oZ()) );
463 
464 #ifdef VISP_HAVE_MODULE_IO
465  vpImage<vpRGBa> Iref ;
466  //Display window creation and initialisation
467  if(vpIoTools::checkFilename(displayFile)){
468  try{
469  std::cout << "Load image to help initialization: " << displayFile << std::endl;
470 #if defined VISP_HAVE_X11
471  d_help = new vpDisplayX ;
472 #elif defined VISP_HAVE_GDI
473  d_help = new vpDisplayGDI;
474 #elif defined VISP_HAVE_OPENCV
475  d_help = new vpDisplayOpenCV;
476 #endif
477 
478  vpImageIo::read(Iref, displayFile) ;
479 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
480  d_help->init(Iref, I.display->getWindowXPosition()+(int)I.getWidth()+80, I.display->getWindowYPosition(),
481  "Where to initialize...") ;
482  vpDisplay::display(Iref) ;
483  vpDisplay::flush(Iref);
484 #endif
485  }
486  catch(...) {
487  if(d_help != NULL) {
488  delete d_help;
489  d_help = NULL;
490  }
491  }
492  }
493 #else //#ifdef VISP_HAVE_MODULE_IO
494  (void)(displayFile);
495 #endif //#ifdef VISP_HAVE_MODULE_IO
496 
497  vpImagePoint ip;
498  bool isWellInit = false;
499  while(!isWellInit)
500  {
501  for(unsigned int i=0 ; i< points3D_list.size() ; i++)
502  {
503  std::cout << "Click on point " << i+1 << std::endl ;
504  double x=0,y=0;
505  vpDisplay::getClick(I, ip) ;
507  vpDisplay::flush(I) ;
509  P[i].set_x(x);
510  P[i].set_y(y);
511 
512  std::cout << "Click on point " << ip << std::endl;
513 
514  vpDisplay::displayPoint (I, ip, vpColor::green); //display target point
515  pose.addPoint(P[i]) ; // and added to the pose computation point list
516  }
517  vpDisplay::flush(I) ;
518 
519  vpHomogeneousMatrix cMo1, cMo2;
520  pose.computePose(vpPose::LAGRANGE, cMo1) ;
521  double d1 = pose.computeResidual(cMo1);
522  pose.computePose(vpPose::DEMENTHON, cMo2) ;
523  double d2 = pose.computeResidual(cMo2);
524 
525  if(d1 < d2){
526  cMo = cMo1;
527  }
528  else{
529  cMo = cMo2;
530  }
532 
533  display(I, cMo, cam, vpColor::green, 1, true);
534  vpDisplay::displayText(I, 15, 10,
535  "left click to validate, right click to re initialize object",
536  vpColor::red);
537 
538  vpDisplay::flush(I) ;
539 
541  while (!vpDisplay::getClick(I, ip, button)) ;
542 
543  if (button == vpMouseButton::button1)
544  {
545  isWellInit = true;
546  }
547  else
548  {
549  pose.clearPoint() ;
550  vpDisplay::display(I) ;
551  vpDisplay::flush(I) ;
552  }
553  }
554 
556 
557  if(d_help != NULL) {
558  delete d_help;
559  d_help = NULL;
560  }
561 
562  init(I);
563 }
564 #endif //#ifdef VISP_HAVE_MODULE_GUI
565 
583 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::string& initFile )
584 {
585  char s[FILENAME_MAX];
586  std::fstream finit ;
587 
588  std::string ext = ".init";
589  size_t pos = initFile.rfind(ext);
590 
591  if( pos == initFile.size()-ext.size() && pos != 0)
592  sprintf(s,"%s", initFile.c_str());
593  else
594  sprintf(s,"%s.init", initFile.c_str());
595 
596  std::cout << "filename " << s << std::endl ;
597  finit.open(s,std::ios::in) ;
598  if (finit.fail()){
599  std::cout << "cannot read " << s << std::endl;
600  throw vpException(vpException::ioError, "cannot read init file");
601  }
602 
603  unsigned int size;
604  double X, Y, Z;
605  finit >> size ;
606  std::cout << "number of points " << size << std::endl ;
607 
608  if (size > 100000) {
610  "Exceed the max number of points.");
611  }
612 
613  vpPoint *P = new vpPoint [size];
614  vpPose pose ;
615 
616  for(unsigned int i=0 ; i< size ; i++)
617  {
618  finit >> X ;
619  finit >> Y ;
620  finit >> Z ;
621  P[i].setWorldCoordinates(X,Y,Z) ;
622  }
623 
624  unsigned int size2;
625  double x, y;
626  vpImagePoint ip;
627  finit >> size2 ;
628  if(size != size2)
629  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
630 
631  for(unsigned int i=0 ; i< size ; i++)
632  {
633  finit >> x;
634  finit >> y;
635  ip = vpImagePoint(x,y);
637  P[i].set_x(x);
638  P[i].set_y(y);
639  pose.addPoint(P[i]);
640  }
641 
642  vpHomogeneousMatrix cMo1, cMo2;
643  pose.computePose(vpPose::LAGRANGE, cMo1) ;
644  double d1 = pose.computeResidual(cMo1);
645  pose.computePose(vpPose::DEMENTHON, cMo2) ;
646  double d2 = pose.computeResidual(cMo2);
647 
648  if(d1 < d2)
649  cMo = cMo1;
650  else
651  cMo = cMo2;
652 
654 
655  delete [] P;
656 
657  init(I);
658 }
659 
668 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::vector<vpImagePoint> &points2D_list,
669  const std::vector<vpPoint> &points3D_list )
670 {
671  if(points2D_list.size() != points3D_list.size())
672  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
673 
674  size_t size = points3D_list.size();
675  std::vector<vpPoint> P;
676  vpPose pose ;
677 
678  for(size_t i=0 ; i< size ; i++)
679  {
680  P.push_back( vpPoint(points3D_list[i].get_oX(), points3D_list[i].get_oY(), points3D_list[i].get_oZ()) );
681  double x=0,y=0;
682  vpPixelMeterConversion::convertPoint(cam, points2D_list[i], x, y);
683  P[i].set_x(x);
684  P[i].set_y(y);
685  pose.addPoint(P[i]);
686  }
687 
688  vpHomogeneousMatrix cMo1, cMo2;
689  pose.computePose(vpPose::LAGRANGE, cMo1) ;
690  double d1 = pose.computeResidual(cMo1);
691  pose.computePose(vpPose::DEMENTHON, cMo2) ;
692  double d2 = pose.computeResidual(cMo2);
693 
694  if(d1 < d2)
695  cMo = cMo1;
696  else
697  cMo = cMo2;
698 
700 
701  init(I);
702 }
703 
721 void vpMbTracker::initFromPose(const vpImage<unsigned char>& I, const std::string &initFile)
722 {
723  char s[FILENAME_MAX];
724  std::fstream finit ;
725  vpPoseVector init_pos;
726 
727  std::string ext = ".pos";
728  size_t pos = initFile.rfind(ext);
729 
730  if( pos == initFile.size()-ext.size() && pos != 0)
731  sprintf(s,"%s", initFile.c_str());
732  else
733  sprintf(s,"%s.pos", initFile.c_str());
734 
735  finit.open(s,std::ios::in) ;
736  if (finit.fail()){
737  std::cout << "cannot read " << s << std::endl;
738  throw vpException(vpException::ioError, "cannot read init file");
739  }
740 
741  for (unsigned int i = 0; i < 6; i += 1){
742  finit >> init_pos[i];
743  }
744 
745  cMo.buildFrom(init_pos);
746  init(I);
747 }
748 
756 {
757  this->cMo = cMo_;
758  init(I);
759 }
760 
768 {
769  vpHomogeneousMatrix _cMo(cPo);
770  initFromPose(I, _cMo);
771 }
772 
778 void vpMbTracker::savePose(const std::string &filename) const
779 {
780  vpPoseVector init_pos;
781  std::fstream finitpos ;
782  char s[FILENAME_MAX];
783 
784  sprintf(s,"%s", filename.c_str());
785  finitpos.open(s, std::ios::out) ;
786 
787  init_pos.buildFrom(cMo);
788  finitpos << init_pos;
789  finitpos.close();
790 }
791 
792 
793 void vpMbTracker::addPolygon(const std::vector<vpPoint>& corners, const int idFace, const std::string &polygonName,
794  const bool useLod, const double minPolygonAreaThreshold, const double minLineLengthThreshold)
795 {
796  std::vector<vpPoint> corners_without_duplicates;
797  corners_without_duplicates.push_back(corners[0]);
798  for (unsigned int i=0; i < corners.size()-1; i++) {
799  if (std::fabs(corners[i].get_oX() - corners[i+1].get_oX()) > std::fabs(corners[i].get_oX())*std::numeric_limits<double>::epsilon()
800  || std::fabs(corners[i].get_oY() - corners[i+1].get_oY()) > std::fabs(corners[i].get_oY())*std::numeric_limits<double>::epsilon()
801  || std::fabs(corners[i].get_oZ() - corners[i+1].get_oZ()) > std::fabs(corners[i].get_oZ())*std::numeric_limits<double>::epsilon()) {
802  corners_without_duplicates.push_back(corners[i+1]);
803  }
804  }
805 
806  vpMbtPolygon polygon;
807  polygon.setNbPoint((unsigned int)corners_without_duplicates.size());
808  polygon.setIndex((int)idFace);
809  polygon.setName(polygonName);
810  polygon.setLod(useLod);
811 
812 // //if(minPolygonAreaThreshold != -1.0) {
813 // if(std::fabs(minPolygonAreaThreshold + 1.0) > std::fabs(minPolygonAreaThreshold)*std::numeric_limits<double>::epsilon()) {
814 // polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
815 // }
816 //
817 // //if(minLineLengthThreshold != -1.0) {
818 // if(std::fabs(minLineLengthThreshold + 1.0) > std::fabs(minLineLengthThreshold)*std::numeric_limits<double>::epsilon()) {
819 // polygon.setMinLineLengthThresh(minLineLengthThreshold);
820 // }
821 
822  polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
823  polygon.setMinLineLengthThresh(minLineLengthThreshold);
824 
825  for(unsigned int j = 0; j < corners_without_duplicates.size(); j++) {
826  polygon.addPoint(j, corners_without_duplicates[j]);
827  }
828 
829  faces.addPolygon(&polygon);
830 
832  faces.getPolygon().back()->setClipping(clippingFlag);
833 
834  if((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
835  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
836 
837  if((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
838  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
839 }
840 
841 void vpMbTracker::addPolygon(const vpPoint& p1, const vpPoint &p2, const vpPoint &p3, const double radius,
842  const int idFace, const std::string &polygonName, const bool useLod, const double minPolygonAreaThreshold)
843 {
844  vpMbtPolygon polygon;
845  polygon.setNbPoint(4);
846  polygon.setName(polygonName);
847  polygon.setLod(useLod);
848 
849 // //if(minPolygonAreaThreshold != -1.0) {
850 // if(std::fabs(minPolygonAreaThreshold + 1.0) > std::fabs(minPolygonAreaThreshold)*std::numeric_limits<double>::epsilon()) {
851 // polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
852 // }
853  polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
854  //Non sense to set minLineLengthThreshold for circle
855  //but used to be coherent when applying LOD settings for all polygons
857 
858  {
859  // Create the 4 points of the circle bounding box
860  vpPlane plane(p1, p2, p3, vpPlane::object_frame);
861 
862  // Matrice de passage entre world et circle frame
863  double norm_X = sqrt(vpMath::sqr(p2.get_oX()-p1.get_oX())
864  + vpMath::sqr(p2.get_oY()-p1.get_oY())
865  + vpMath::sqr(p2.get_oZ()-p1.get_oZ()));
866  double norm_Y = sqrt(vpMath::sqr(plane.getA())
867  + vpMath::sqr(plane.getB())
868  + vpMath::sqr(plane.getC()));
869  vpRotationMatrix wRc;
870  vpColVector x(3),y(3),z(3);
871  // X axis is P2-P1
872  x[0] = (p2.get_oX()-p1.get_oX()) / norm_X;
873  x[1] = (p2.get_oY()-p1.get_oY()) / norm_X;
874  x[2] = (p2.get_oZ()-p1.get_oZ()) / norm_X;
875  // Y axis is the normal of the plane
876  y[0] = plane.getA() / norm_Y;
877  y[1] = plane.getB() / norm_Y;
878  y[2] = plane.getC() / norm_Y;
879  // Z axis = X ^ Y
880  z = vpColVector::crossProd(x, y);
881  for (unsigned int i=0; i< 3; i++) {
882  wRc[i][0] = x[i];
883  wRc[i][1] = y[i];
884  wRc[i][2] = z[i];
885  }
886 
887  vpTranslationVector wtc(p1.get_oX(), p1.get_oY(), p1.get_oZ());
888  vpHomogeneousMatrix wMc(wtc, wRc);
889 
890  vpColVector c_p(4); // A point in the circle frame that is on the bbox
891  c_p[0] = radius;
892  c_p[1] = 0;
893  c_p[2] = radius;
894  c_p[3] = 1;
895 
896  // Matrix to rotate a point by 90 deg around Y in the circle frame
897  for(unsigned int i=0; i<4; i++) {
898  vpColVector w_p(4); // A point in the word frame
900  w_p = wMc * cMc_90 * c_p;
901 
902  vpPoint w_P;
903  w_P.setWorldCoordinates(w_p[0], w_p[1], w_p[2]);
904 
905  polygon.addPoint(i,w_P);
906  }
907  }
908 
909  polygon.setIndex(idFace);
910  faces.addPolygon(&polygon);
911 
913  faces.getPolygon().back()->setClipping(clippingFlag);
914 
915  if((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
916  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
917 
918  if((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
919  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
920 }
921 
922 void vpMbTracker::addPolygon(const vpPoint& p1, const vpPoint &p2, const int idFace, const std::string &polygonName,
923  const bool useLod, const double minLineLengthThreshold)
924 {
925  // A polygon as a single line that corresponds to the revolution axis of the cylinder
926  vpMbtPolygon polygon;
927  polygon.setNbPoint(2);
928 
929  polygon.addPoint(0, p1);
930  polygon.addPoint(1, p2);
931 
932  polygon.setIndex(idFace) ;
933  polygon.setName(polygonName);
934  polygon.setLod(useLod);
935 
936 // //if(minLineLengthThreshold != -1.0) {
937 // if(std::fabs(minLineLengthThreshold + 1.0) > std::fabs(minLineLengthThreshold)*std::numeric_limits<double>::epsilon()) {
938 // polygon.setMinLineLengthThresh(minLineLengthThreshold);
939 // }
940  polygon.setMinLineLengthThresh(minLineLengthThreshold);
941  //Non sense to set minPolygonAreaThreshold for cylinder
942  //but used to be coherent when applying LOD settings for all polygons
944 
945  faces.addPolygon(&polygon) ;
946 
948  faces.getPolygon().back()->setClipping(clippingFlag);
949 
950  if((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
951  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
952 
953  if((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
954  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
955 }
956 
957 void vpMbTracker::addPolygon(const std::vector<std::vector<vpPoint> > &listFaces, const int idFace, const std::string &polygonName,
958  const bool useLod, const double minLineLengthThreshold)
959 {
960  int id = idFace;
961  for(unsigned int i = 0 ; i < listFaces.size() ; i++)
962  {
963  vpMbtPolygon polygon;
964  polygon.setNbPoint((unsigned int)listFaces[i].size());
965  for(unsigned int j = 0 ; j < listFaces[i].size() ; j++)
966  polygon.addPoint(j, listFaces[i][j]);
967 
968  polygon.setIndex(id) ;
969  polygon.setName(polygonName);
970  polygon.setIsPolygonOriented(false);
971  polygon.setLod(useLod);
972  polygon.setMinLineLengthThresh(minLineLengthThreshold);
974 
975  faces.addPolygon(&polygon) ;
976 
978  faces.getPolygon().back()->setClipping(clippingFlag);
979 
980  if((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
981  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
982 
983  if((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
984  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
985 
986  id++;
987  }
988 }
989 
1015 void
1016 vpMbTracker::loadModel(const char *modelFile, const bool verbose)
1017 {
1018  loadModel( std::string(modelFile), verbose );
1019 }
1020 
1046 void
1047 vpMbTracker::loadModel(const std::string& modelFile, const bool verbose)
1048 {
1049  std::string::const_iterator it;
1050 
1051  if(vpIoTools::checkFilename(modelFile)) {
1052  it = modelFile.end();
1053  if((*(it-1) == 'o' && *(it-2) == 'a' && *(it-3) == 'c' && *(it-4) == '.') ||
1054  (*(it-1) == 'O' && *(it-2) == 'A' && *(it-3) == 'C' && *(it-4) == '.') ){
1055  std::vector<std::string> vectorOfModelFilename;
1056  int startIdFace = (int)faces.size();
1057  nbPoints = 0;
1058  nbLines = 0;
1059  nbPolygonLines = 0;
1060  nbPolygonPoints = 0;
1061  nbCylinders = 0;
1062  nbCircles = 0;
1063  loadCAOModel(modelFile, vectorOfModelFilename, startIdFace, verbose, true);
1064  }
1065  else if((*(it-1) == 'l' && *(it-2) == 'r' && *(it-3) == 'w' && *(it-4) == '.') ||
1066  (*(it-1) == 'L' && *(it-2) == 'R' && *(it-3) == 'W' && *(it-4) == '.') ){
1067  loadVRMLModel(modelFile);
1068  }
1069  else{
1070  throw vpException(vpException::ioError, "Error: File %s doesn't contain a cao or wrl model", modelFile.c_str());
1071  }
1072  }
1073  else{
1074  throw vpException(vpException::ioError, "Error: File %s doesn't exist", modelFile.c_str());
1075  }
1076 
1077  this->modelInitialised = true;
1078  this->modelFileName = modelFile;
1079 }
1080 
1081 
1112 void
1113 vpMbTracker::loadVRMLModel(const std::string& modelFile)
1114 {
1115 #ifdef VISP_HAVE_COIN3D
1116  SoDB::init(); // Call SoDB::finish() before ending the program.
1117 
1118  SoInput in;
1119  SbBool ok = in.openFile(modelFile.c_str());
1120  SoVRMLGroup *sceneGraphVRML2;
1121 
1122  if (!ok) {
1123  vpERROR_TRACE("can't open file to load model");
1124  throw vpException(vpException::fatalError, "can't open file to load model");
1125  }
1126 
1127  if(!in.isFileVRML2())
1128  {
1129  SoSeparator *sceneGraph = SoDB::readAll(&in);
1130  if (sceneGraph == NULL) { /*return -1;*/ }
1131  sceneGraph->ref();
1132 
1133  SoToVRML2Action tovrml2;
1134  tovrml2.apply(sceneGraph);
1135 
1136  sceneGraphVRML2 =tovrml2.getVRML2SceneGraph();
1137  sceneGraphVRML2->ref();
1138  sceneGraph->unref();
1139  }
1140  else
1141  {
1142  sceneGraphVRML2 = SoDB::readAllVRML(&in);
1143  if (sceneGraphVRML2 == NULL) { /*return -1;*/ }
1144  sceneGraphVRML2->ref();
1145  }
1146 
1147  in.closeFile();
1148 
1149  vpHomogeneousMatrix transform;
1150  int indexFace = (int)faces.size();
1151  extractGroup(sceneGraphVRML2, transform, indexFace);
1152 
1153  sceneGraphVRML2->unref();
1154 #else
1155  vpERROR_TRACE("coin not detected with ViSP, cannot load model : %s", modelFile.c_str());
1156  throw vpException(vpException::fatalError, "coin not detected with ViSP, cannot load model");
1157 #endif
1158 }
1159 
1160 void vpMbTracker::removeComment(std::ifstream& fileId) {
1161  char c;
1162 
1163  fileId.get(c);
1164  while (!fileId.fail() && (c == '#')) {
1165  fileId.ignore(256, '\n');
1166  fileId.get(c);
1167  }
1168  if (fileId.fail())
1169  throw(vpException(vpException::ioError, "Reached end of file"));
1170  fileId.unget();
1171 }
1172 
1173 std::map<std::string, std::string> vpMbTracker::parseParameters(std::string& endLine) {
1174  std::map<std::string, std::string> mapOfParams;
1175 
1176  bool exit = false;
1177  while (!endLine.empty() && !exit) {
1178  exit = true;
1179 
1180  for (std::map<std::string, std::string>::const_iterator it =
1181  mapOfParameterNames.begin(); it != mapOfParameterNames.end();
1182  ++it) {
1183  endLine = trim(endLine);
1184  // std::cout << "endLine=" << endLine << std::endl;
1185  std::string param(it->first + "=");
1186 
1187  //Compare with a potential parameter
1188  if (endLine.compare(0, param.size(), param) == 0) {
1189  exit = false;
1190  endLine = endLine.substr(param.size());
1191 
1192  bool parseQuote = false;
1193  if (it->second == "string") {
1194  //Check if the string is between quotes
1195  if (endLine.size() > 2 && endLine[0] == '"') {
1196  parseQuote = true;
1197  endLine = endLine.substr(1);
1198  size_t pos = endLine.find_first_of('"');
1199 
1200  if (pos != std::string::npos) {
1201  mapOfParams[it->first] = endLine.substr(0, pos);
1202  endLine = endLine.substr(pos + 1);
1203  } else {
1204  parseQuote = false;
1205  }
1206  }
1207  }
1208 
1209  if (!parseQuote) {
1210  //Deal with space or tabulation after parameter value to substring
1211  // to the next sequence
1212  size_t pos1 = endLine.find_first_of(' ');
1213  size_t pos2 = endLine.find_first_of('\t');
1214  size_t pos = pos1 < pos2 ? pos1 : pos2;
1215 
1216  mapOfParams[it->first] = endLine.substr(0, pos);
1217  endLine = endLine.substr(pos + 1);
1218  }
1219  }
1220  }
1221  }
1222 
1223 // for(std::map<std::string, std::string>::const_iterator it = mapOfParams.begin(); it != mapOfParams.end(); ++it) {
1224 // std::cout << it->first << "=" << it->second << std::endl;
1225 // }
1226 
1227  return mapOfParams;
1228 }
1229 
1275 void
1276 vpMbTracker::loadCAOModel(const std::string& modelFile,
1277  std::vector<std::string>& vectorOfModelFilename, int& startIdFace,
1278  const bool verbose, const bool parent) {
1279  std::ifstream fileId;
1280  fileId.exceptions(std::ifstream::failbit | std::ifstream::eofbit);
1281  fileId.open(modelFile.c_str(), std::ifstream::in);
1282  if (fileId.fail()) {
1283  std::cout << "cannot read CAO model file: " << modelFile << std::endl;
1284  throw vpException(vpException::ioError, "cannot read CAO model file");
1285  }
1286 
1287  if(verbose) {
1288  std::cout << "Model file : " << modelFile << std::endl;
1289  }
1290  vectorOfModelFilename.push_back(modelFile);
1291 
1292  try {
1293  char c;
1294  // Extraction of the version (remove empty line and commented ones (comment
1295  // line begin with the #)).
1296  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
1297  removeComment(fileId);
1298 
1300  int caoVersion;
1301  fileId.get(c);
1302  if (c == 'V') {
1303  fileId >> caoVersion;
1304  fileId.ignore(256, '\n'); // skip the rest of the line
1305  } else {
1306  std::cout
1307  << "in vpMbTracker::loadCAOModel() -> Bad parameter header file : use V0, V1, ...";
1309  "in vpMbTracker::loadCAOModel() -> Bad parameter header file : use V0, V1, ...");
1310  }
1311 
1312  removeComment(fileId);
1313 
1314 
1316  std::string line;
1317  std::string prefix = "load";
1318 
1319  fileId.get(c);
1320  fileId.unget();
1321  bool header = false;
1322  while(c == 'l' || c == 'L') {
1323  header = true;
1324 
1325  getline(fileId, line);
1326  if(!line.compare(0, prefix.size(), prefix)) {
1327 
1328  //Get the loaded model pathname
1329  std::string headerPathRead = line.substr(6);
1330  size_t firstIndex = headerPathRead.find_first_of("\")");
1331  headerPathRead = headerPathRead.substr(0, firstIndex);
1332 
1333  std::string headerPath = headerPathRead;
1334  if(!vpIoTools::isAbsolutePathname(headerPathRead)) {
1335  std::string parentDirectory = vpIoTools::getParent(modelFile);
1336  headerPath = vpIoTools::createFilePath(parentDirectory, headerPathRead);
1337  }
1338 
1339  //Normalize path
1340  headerPath = vpIoTools::path(headerPath);
1341 
1342  //Get real path
1343  headerPath = vpIoTools::getAbsolutePathname(headerPath);
1344 
1345  bool cyclic = false;
1346  for (std::vector<std::string>::const_iterator it = vectorOfModelFilename.begin();
1347  it != vectorOfModelFilename.end() && !cyclic; ++it) {
1348  if (headerPath == *it) {
1349  cyclic = true;
1350  }
1351  }
1352 
1353  if (!cyclic) {
1354  if (vpIoTools::checkFilename(headerPath)) {
1355  loadCAOModel(headerPath, vectorOfModelFilename, startIdFace, verbose, false);
1356  } else {
1357  throw vpException(vpException::ioError, "file cannot be open");
1358  }
1359  } else {
1360  std::cout << "WARNING Cyclic dependency detected with file "
1361  << headerPath << " declared in " << modelFile << std::endl;
1362  }
1363  } else {
1364  header = false;
1365  }
1366 
1367  removeComment(fileId);
1368  fileId.get(c);
1369  fileId.unget();
1370  }
1371 
1372 
1374  unsigned int caoNbrPoint;
1375  fileId >> caoNbrPoint;
1376  fileId.ignore(256, '\n'); // skip the rest of the line
1377 
1378  nbPoints += caoNbrPoint;
1379  if(verbose || vectorOfModelFilename.size() == 1) {
1380  std::cout << "> " << caoNbrPoint << " points" << std::endl;
1381  }
1382 
1383  if (caoNbrPoint > 100000) {
1385  "Exceed the max number of points in the CAO model.");
1386  }
1387 
1388  if (caoNbrPoint == 0 && !header) {
1390  "in vpMbTracker::loadCAOModel() -> no points are defined");
1391  }
1392  vpPoint *caoPoints = new vpPoint[caoNbrPoint];
1393 
1394  double x; // 3D coordinates
1395  double y;
1396  double z;
1397 
1398  int i; // image coordinate (used for matching)
1399  int j;
1400 
1401  for (unsigned int k = 0; k < caoNbrPoint; k++) {
1402  removeComment(fileId);
1403 
1404  fileId >> x;
1405  fileId >> y;
1406  fileId >> z;
1407 
1408  if (caoVersion == 2) {
1409  fileId >> i;
1410  fileId >> j;
1411  }
1412 
1413  fileId.ignore(256, '\n'); // skip the rest of the line
1414 
1415  caoPoints[k].setWorldCoordinates(x, y, z);
1416  }
1417 
1418 
1419  removeComment(fileId);
1420 
1421 
1423  //Store in a map the potential segments to add
1424  std::map<std::pair<unsigned int, unsigned int>, SegmentInfo > segmentTemporaryMap;
1425  unsigned int caoNbrLine;
1426  fileId >> caoNbrLine;
1427  fileId.ignore(256, '\n'); // skip the rest of the line
1428 
1429  nbLines += caoNbrLine;
1430  unsigned int *caoLinePoints = NULL;
1431  if(verbose || vectorOfModelFilename.size() == 1) {
1432  std::cout << "> " << caoNbrLine << " lines" << std::endl;
1433  }
1434 
1435  if (caoNbrLine > 100000) {
1436  delete[] caoPoints;
1438  "Exceed the max number of lines in the CAO model.");
1439  }
1440 
1441  if (caoNbrLine > 0)
1442  caoLinePoints = new unsigned int[2 * caoNbrLine];
1443 
1444  unsigned int index1, index2;
1445  //Initialization of idFace with startIdFace for dealing with recursive load in header
1446  int idFace = startIdFace;
1447 
1448  for (unsigned int k = 0; k < caoNbrLine; k++) {
1449  removeComment(fileId);
1450 
1451  fileId >> index1;
1452  fileId >> index2;
1453 
1455  //Get the end of the line
1456  char buffer[256];
1457  fileId.getline(buffer, 256);
1458  std::string endLine(buffer);
1459  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1460 
1461  std::string segmentName = "";
1462  double minLineLengthThresh = !applyLodSettingInConfig ? minLineLengthThresholdGeneral : 50.0;
1463  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1464  if(mapOfParams.find("name") != mapOfParams.end()) {
1465  segmentName = mapOfParams["name"];
1466  }
1467  if(mapOfParams.find("minLineLengthThreshold") != mapOfParams.end()) {
1468  minLineLengthThresh = std::atof(mapOfParams["minLineLengthThreshold"].c_str());
1469  }
1470  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1471  useLod = parseBoolean(mapOfParams["useLod"]);
1472  }
1473 
1474  SegmentInfo segmentInfo;
1475  segmentInfo.name = segmentName;
1476  segmentInfo.useLod = useLod;
1477  segmentInfo.minLineLengthThresh = minLineLengthThresh;
1478 
1479  caoLinePoints[2 * k] = index1;
1480  caoLinePoints[2 * k + 1] = index2;
1481 
1482  if (index1 < caoNbrPoint && index2 < caoNbrPoint) {
1483  std::vector<vpPoint> extremities;
1484  extremities.push_back(caoPoints[index1]);
1485  extremities.push_back(caoPoints[index2]);
1486  segmentInfo.extremities = extremities;
1487 
1488  std::pair<unsigned int, unsigned int> key(index1, index2);
1489 
1490  segmentTemporaryMap[key] = segmentInfo;
1491  } else {
1492  vpTRACE(" line %d has wrong coordinates.", k);
1493  }
1494  }
1495 
1496  removeComment(fileId);
1497 
1498 
1500  /* Load polygon from the lines extracted earlier (the first point of the line is used)*/
1501  //Store in a vector the indexes of the segments added in the face segment case
1502  std::vector<std::pair<unsigned int, unsigned int> > faceSegmentKeyVector;
1503  unsigned int caoNbrPolygonLine;
1504  fileId >> caoNbrPolygonLine;
1505  fileId.ignore(256, '\n'); // skip the rest of the line
1506 
1507  nbPolygonLines += caoNbrPolygonLine;
1508  if(verbose || vectorOfModelFilename.size() == 1) {
1509  std::cout << "> " << caoNbrPolygonLine << " polygon lines" << std::endl;
1510  }
1511 
1512  if (caoNbrPolygonLine > 100000) {
1513  delete[] caoPoints;
1514  delete[] caoLinePoints;
1516  "Exceed the max number of polygon lines.");
1517  }
1518 
1519  unsigned int index;
1520  for (unsigned int k = 0; k < caoNbrPolygonLine; k++) {
1521  removeComment(fileId);
1522 
1523  unsigned int nbLinePol;
1524  fileId >> nbLinePol;
1525  std::vector<vpPoint> corners;
1526  if (nbLinePol > 100000) {
1527  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1528  }
1529 
1530  for (unsigned int n = 0; n < nbLinePol; n++) {
1531  fileId >> index;
1532 
1533  if(index >= caoNbrLine) {
1534  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1535  }
1536  corners.push_back(caoPoints[caoLinePoints[2 * index]]);
1537  corners.push_back(caoPoints[caoLinePoints[2 * index + 1]]);
1538 
1539  std::pair<unsigned int, unsigned int> key(caoLinePoints[2 * index], caoLinePoints[2 * index + 1]);
1540  faceSegmentKeyVector.push_back(key);
1541  }
1542 
1543 
1545  //Get the end of the line
1546  char buffer[256];
1547  fileId.getline(buffer, 256);
1548  std::string endLine(buffer);
1549  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1550 
1551  std::string polygonName = "";
1552  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1553  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1554  if(mapOfParams.find("name") != mapOfParams.end()) {
1555  polygonName = mapOfParams["name"];
1556  }
1557  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1558  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1559  }
1560  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1561  useLod = parseBoolean(mapOfParams["useLod"]);
1562  }
1563 
1564  addPolygon(corners, idFace++, polygonName, useLod, minPolygonAreaThreshold, minLineLengthThresholdGeneral);
1565  initFaceFromLines(*(faces.getPolygon().back())); // Init from the last polygon that was added
1566  }
1567 
1568  //Add the segments which were not already added in the face segment case
1569  for(std::map<std::pair<unsigned int, unsigned int>, SegmentInfo >::const_iterator it =
1570  segmentTemporaryMap.begin(); it != segmentTemporaryMap.end(); ++it) {
1571  if(std::find(faceSegmentKeyVector.begin(), faceSegmentKeyVector.end(), it->first) == faceSegmentKeyVector.end()) {
1572  addPolygon(it->second.extremities, idFace++, it->second.name, it->second.useLod, minPolygonAreaThresholdGeneral,
1573  it->second.minLineLengthThresh);
1574  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1575  }
1576  }
1577 
1578  removeComment(fileId);
1579 
1580 
1582  /* Extract the polygon using the point coordinates (top of the file) */
1583  unsigned int caoNbrPolygonPoint;
1584  fileId >> caoNbrPolygonPoint;
1585  fileId.ignore(256, '\n'); // skip the rest of the line
1586 
1587  nbPolygonPoints += caoNbrPolygonPoint;
1588  if(verbose || vectorOfModelFilename.size() == 1) {
1589  std::cout << "> " << caoNbrPolygonPoint << " polygon points"
1590  << std::endl;
1591  }
1592 
1593  if (caoNbrPolygonPoint > 100000) {
1595  "Exceed the max number of polygon point.");
1596  }
1597 
1598  for (unsigned int k = 0; k < caoNbrPolygonPoint; k++) {
1599  removeComment(fileId);
1600 
1601  unsigned int nbPointPol;
1602  fileId >> nbPointPol;
1603  if (nbPointPol > 100000) {
1605  "Exceed the max number of points.");
1606  }
1607  std::vector<vpPoint> corners;
1608  for (unsigned int n = 0; n < nbPointPol; n++) {
1609  fileId >> index;
1610  if (index > caoNbrPoint - 1) {
1612  "Exceed the max number of points.");
1613  }
1614  corners.push_back(caoPoints[index]);
1615  }
1616 
1617 
1619  //Get the end of the line
1620  char buffer[256];
1621  fileId.getline(buffer, 256);
1622  std::string endLine(buffer);
1623  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1624 
1625  std::string polygonName = "";
1626  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1627  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1628  if(mapOfParams.find("name") != mapOfParams.end()) {
1629  polygonName = mapOfParams["name"];
1630  }
1631  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1632  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1633  }
1634  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1635  useLod = parseBoolean(mapOfParams["useLod"]);
1636  }
1637 
1638 
1639  addPolygon(corners, idFace++, polygonName, useLod, minPolygonAreaThreshold, minLineLengthThresholdGeneral);
1640  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1641  }
1642 
1644  unsigned int caoNbCylinder;
1645  try {
1646  removeComment(fileId);
1647 
1648  if (fileId.eof()) { // check if not at the end of the file (for old style files)
1649  delete[] caoPoints;
1650  delete[] caoLinePoints;
1651  return;
1652  }
1653 
1654  /* Extract the cylinders */
1655  fileId >> caoNbCylinder;
1656  fileId.ignore(256, '\n'); // skip the rest of the line
1657 
1658  nbCylinders += caoNbCylinder;
1659  if(verbose || vectorOfModelFilename.size() == 1) {
1660  std::cout << "> " << caoNbCylinder << " cylinders" << std::endl;
1661  }
1662 
1663  if (caoNbCylinder > 100000) {
1665  "Exceed the max number of cylinders.");
1666  }
1667 
1668  for (unsigned int k = 0; k < caoNbCylinder; ++k) {
1669  removeComment(fileId);
1670 
1671  double radius;
1672  unsigned int indexP1, indexP2;
1673  fileId >> indexP1;
1674  fileId >> indexP2;
1675  fileId >> radius;
1676 
1678  //Get the end of the line
1679  char buffer[256];
1680  fileId.getline(buffer, 256);
1681  std::string endLine(buffer);
1682  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1683 
1684  std::string polygonName = "";
1685  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1686  double minLineLengthThreshold = !applyLodSettingInConfig ? minLineLengthThresholdGeneral : 50.0;
1687  if(mapOfParams.find("name") != mapOfParams.end()) {
1688  polygonName = mapOfParams["name"];
1689  }
1690  if(mapOfParams.find("minLineLengthThreshold") != mapOfParams.end()) {
1691  minLineLengthThreshold = std::atof(mapOfParams["minLineLengthThreshold"].c_str());
1692  }
1693  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1694  useLod = parseBoolean(mapOfParams["useLod"]);
1695  }
1696 
1697  int idRevolutionAxis = idFace;
1698  addPolygon(caoPoints[indexP1], caoPoints[indexP2], idFace++, polygonName, useLod, minLineLengthThreshold);
1699 
1700  std::vector<std::vector<vpPoint> > listFaces;
1701  createCylinderBBox(caoPoints[indexP1], caoPoints[indexP2], radius,listFaces);
1702  addPolygon(listFaces, idFace, polygonName, useLod, minLineLengthThreshold);
1703  idFace+=4;
1704 
1705  initCylinder(caoPoints[indexP1], caoPoints[indexP2], radius, idRevolutionAxis, polygonName);
1706  }
1707 
1708  } catch (...) {
1709  std::cerr << "Cannot get the number of cylinders. Defaulting to zero."
1710  << std::endl;
1711  caoNbCylinder = 0;
1712  }
1713 
1714 
1716  unsigned int caoNbCircle;
1717  try {
1718  removeComment(fileId);
1719 
1720  if (fileId.eof()) { // check if not at the end of the file (for old style files)
1721  delete[] caoPoints;
1722  delete[] caoLinePoints;
1723  return;
1724  }
1725 
1726  /* Extract the circles */
1727  fileId >> caoNbCircle;
1728  fileId.ignore(256, '\n'); // skip the rest of the line
1729 
1730  nbCircles += caoNbCircle;
1731  if(verbose || vectorOfModelFilename.size() == 1) {
1732  std::cout << "> " << caoNbCircle << " circles" << std::endl;
1733  }
1734 
1735  if (caoNbCircle > 100000) {
1737  "Exceed the max number of cicles.");
1738  }
1739 
1740  for (unsigned int k = 0; k < caoNbCircle; ++k) {
1741  removeComment(fileId);
1742 
1743  double radius;
1744  unsigned int indexP1, indexP2, indexP3;
1745  fileId >> radius;
1746  fileId >> indexP1;
1747  fileId >> indexP2;
1748  fileId >> indexP3;
1749 
1751  //Get the end of the line
1752  char buffer[256];
1753  fileId.getline(buffer, 256);
1754  std::string endLine(buffer);
1755  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1756 
1757  std::string polygonName = "";
1758  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1759  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1760  if(mapOfParams.find("name") != mapOfParams.end()) {
1761  polygonName = mapOfParams["name"];
1762  }
1763  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1764  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1765  }
1766  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1767  useLod = parseBoolean(mapOfParams["useLod"]);
1768  }
1769 
1770  addPolygon(caoPoints[indexP1], caoPoints[indexP2],
1771  caoPoints[indexP3], radius, idFace, polygonName, useLod, minPolygonAreaThreshold);
1772 
1773  initCircle(caoPoints[indexP1], caoPoints[indexP2],
1774  caoPoints[indexP3], radius, idFace++, polygonName);
1775  }
1776 
1777  } catch (...) {
1778  std::cerr << "Cannot get the number of circles. Defaulting to zero."
1779  << std::endl;
1780  caoNbCircle = 0;
1781  }
1782 
1783  startIdFace = idFace;
1784 
1785  delete[] caoPoints;
1786  delete[] caoLinePoints;
1787 
1788  if(vectorOfModelFilename.size() > 1 && parent) {
1789  if(verbose) {
1790  std::cout << "Global information for " << vpIoTools::getName(modelFile) << " :" << std::endl;
1791  std::cout << "Total nb of points : " << nbPoints << std::endl;
1792  std::cout << "Total nb of lines : " << nbLines << std::endl;
1793  std::cout << "Total nb of polygon lines : " << nbPolygonLines << std::endl;
1794  std::cout << "Total nb of polygon points : " << nbPolygonPoints << std::endl;
1795  std::cout << "Total nb of cylinders : " << nbCylinders << std::endl;
1796  std::cout << "Total nb of circles : " << nbCircles << std::endl;
1797  } else {
1798  std::cout << "> " << nbPoints << " points" << std::endl;
1799  std::cout << "> " << nbLines << " lines" << std::endl;
1800  std::cout << "> " << nbPolygonLines << " polygon lines" << std::endl;
1801  std::cout << "> " << nbPolygonPoints << " polygon points" << std::endl;
1802  std::cout << "> " << nbCylinders << " cylinders" << std::endl;
1803  std::cout << "> " << nbCircles << " circles" << std::endl;
1804  }
1805  }
1806  } catch (...) {
1807  std::cerr << "Cannot read line!" << std::endl;
1808  throw vpException(vpException::ioError, "cannot read line");
1809  }
1810 }
1811 
1812 #ifdef VISP_HAVE_COIN3D
1813 
1820 void
1821 vpMbTracker::extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, int &idFace)
1822 {
1823  vpHomogeneousMatrix transformCur;
1824  SoVRMLTransform *sceneGraphVRML2Trasnform = dynamic_cast<SoVRMLTransform *>(sceneGraphVRML2);
1825  if(sceneGraphVRML2Trasnform){
1826  float rx, ry, rz, rw;
1827  sceneGraphVRML2Trasnform->rotation.getValue().getValue(rx,ry,rz,rw);
1828  vpRotationMatrix rotMat(vpQuaternionVector(rx,ry,rz,rw));
1829 // std::cout << "Rotation: " << rx << " " << ry << " " << rz << " " << rw << std::endl;
1830 
1831  float tx, ty, tz;
1832  tx = sceneGraphVRML2Trasnform->translation.getValue()[0];
1833  ty = sceneGraphVRML2Trasnform->translation.getValue()[1];
1834  tz = sceneGraphVRML2Trasnform->translation.getValue()[2];
1835  vpTranslationVector transVec(tx,ty,tz);
1836 // std::cout << "Translation: " << tx << " " << ty << " " << tz << std::endl;
1837 
1838  float sx, sy, sz;
1839  sx = sceneGraphVRML2Trasnform->scale.getValue()[0];
1840  sy = sceneGraphVRML2Trasnform->scale.getValue()[1];
1841  sz = sceneGraphVRML2Trasnform->scale.getValue()[2];
1842 // std::cout << "Scale: " << sx << " " << sy << " " << sz << std::endl;
1843 
1844  for(unsigned int i = 0 ; i < 3 ; i++)
1845  rotMat[0][i] *= sx;
1846  for(unsigned int i = 0 ; i < 3 ; i++)
1847  rotMat[1][i] *= sy;
1848  for(unsigned int i = 0 ; i < 3 ; i++)
1849  rotMat[2][i] *= sz;
1850 
1851  transformCur = vpHomogeneousMatrix(transVec,rotMat);
1852  transform = transform * transformCur;
1853  }
1854 
1855  int nbShapes = sceneGraphVRML2->getNumChildren();
1856 // std::cout << sceneGraphVRML2->getTypeId().getName().getString() << std::endl;
1857 // std::cout << "Nb object in VRML : " << nbShapes << std::endl;
1858 
1859  SoNode * child;
1860 
1861  for (int i = 0; i < nbShapes; i++)
1862  {
1863  vpHomogeneousMatrix transform_recursive(transform);
1864  child = sceneGraphVRML2->getChild(i);
1865 
1866  if (child->getTypeId() == SoVRMLGroup::getClassTypeId()){
1867  extractGroup((SoVRMLGroup*)child, transform_recursive, idFace);
1868  }
1869 
1870  if (child->getTypeId() == SoVRMLTransform::getClassTypeId()){
1871  extractGroup((SoVRMLTransform*)child, transform_recursive, idFace);
1872  }
1873 
1874  if (child->getTypeId() == SoVRMLShape::getClassTypeId()){
1875  SoChildList * child2list = child->getChildren();
1876  std::string name = child->getName().getString();
1877 
1878  for (int j = 0; j < child2list->getLength(); j++)
1879  {
1880  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedFaceSet::getClassTypeId())
1881  {
1882  SoVRMLIndexedFaceSet * face_set;
1883  face_set = (SoVRMLIndexedFaceSet*)child2list->get(j);
1884  if(!strncmp(face_set->getName().getString(),"cyl",3)){
1885  extractCylinders(face_set, transform, idFace, name);
1886  }else{
1887  extractFaces(face_set, transform, idFace, name);
1888  }
1889  }
1890  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedLineSet::getClassTypeId())
1891  {
1892  SoVRMLIndexedLineSet * line_set;
1893  line_set = (SoVRMLIndexedLineSet*)child2list->get(j);
1894  extractLines(line_set, idFace, name);
1895  }
1896  }
1897  }
1898  }
1899 }
1900 
1910 void
1911 vpMbTracker::extractFaces(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName)
1912 {
1913  std::vector<vpPoint> corners;
1914  corners.resize(0);
1915 
1916 // SoMFInt32 indexList = _face_set->coordIndex;
1917 // int indexListSize = indexList.getNum();
1918  int indexListSize = face_set->coordIndex.getNum();
1919 
1920  vpColVector pointTransformed(4);
1921  vpPoint pt;
1922  SoVRMLCoordinate *coord;
1923 
1924  for (int i = 0; i < indexListSize; i++)
1925  {
1926  if (face_set->coordIndex[i] == -1)
1927  {
1928  if(corners.size() > 1)
1929  {
1930  addPolygon(corners, idFace++, polygonName);
1931  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1932  corners.resize(0);
1933  }
1934  }
1935  else
1936  {
1937  coord = (SoVRMLCoordinate *)(face_set->coord.getValue());
1938  int index = face_set->coordIndex[i];
1939  pointTransformed[0]=coord->point[index].getValue()[0];
1940  pointTransformed[1]=coord->point[index].getValue()[1];
1941  pointTransformed[2]=coord->point[index].getValue()[2];
1942  pointTransformed[3] = 1.0;
1943 
1944  pointTransformed = transform * pointTransformed;
1945 
1946  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1947  corners.push_back(pt);
1948  }
1949  }
1950 }
1951 
1966 void
1967 vpMbTracker::extractCylinders(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName)
1968 {
1969  std::vector<vpPoint> corners_c1, corners_c2;//points belonging to the first circle and to the second one.
1970  SoVRMLCoordinate* coords = (SoVRMLCoordinate *)face_set->coord.getValue();
1971 
1972  unsigned int indexListSize = (unsigned int)coords->point.getNum();
1973 
1974  if(indexListSize % 2 == 1){
1975  std::cout << "Not an even number of points when extracting a cylinder." << std::endl;
1976  throw vpException(vpException::dimensionError, "Not an even number of points when extracting a cylinder.");
1977  }
1978  corners_c1.resize(indexListSize / 2);
1979  corners_c2.resize(indexListSize / 2);
1980  vpColVector pointTransformed(4);
1981  vpPoint pt;
1982 
1983 
1984  // extract all points and fill the two sets.
1985 
1986  for(int i=0; i<coords->point.getNum(); ++i){
1987  pointTransformed[0]=coords->point[i].getValue()[0];
1988  pointTransformed[1]=coords->point[i].getValue()[1];
1989  pointTransformed[2]=coords->point[i].getValue()[2];
1990  pointTransformed[3] = 1.0;
1991 
1992  pointTransformed = transform * pointTransformed;
1993 
1994  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1995 
1996  if(i < (int)corners_c1.size()){
1997  corners_c1[(unsigned int)i] = pt;
1998  }else{
1999  corners_c2[(unsigned int)i-corners_c1.size()] = pt;
2000  }
2001  }
2002 
2003  vpPoint p1 = getGravityCenter(corners_c1);
2004  vpPoint p2 = getGravityCenter(corners_c2);
2005 
2006  vpColVector dist(3);
2007  dist[0] = p1.get_oX() - corners_c1[0].get_oX();
2008  dist[1] = p1.get_oY() - corners_c1[0].get_oY();
2009  dist[2] = p1.get_oZ() - corners_c1[0].get_oZ();
2010  double radius_c1 = sqrt(dist.sumSquare());
2011  dist[0] = p2.get_oX() - corners_c2[0].get_oX();
2012  dist[1] = p2.get_oY() - corners_c2[0].get_oY();
2013  dist[2] = p2.get_oZ() - corners_c2[0].get_oZ();
2014  double radius_c2 = sqrt(dist.sumSquare());
2015 
2016  if(std::fabs(radius_c1 - radius_c2) > (std::numeric_limits<double>::epsilon() * vpMath::maximum(radius_c1, radius_c2))){
2017  std::cout << "Radius from the two circles of the cylinders are different." << std::endl;
2018  throw vpException(vpException::badValue, "Radius from the two circles of the cylinders are different.");
2019  }
2020 
2021  //addPolygon(p1, p2, idFace, polygonName);
2022  //initCylinder(p1, p2, radius_c1, idFace++);
2023 
2024  int idRevolutionAxis = idFace;
2025  addPolygon(p1, p2, idFace++, polygonName);
2026 
2027  std::vector<std::vector<vpPoint> > listFaces;
2028  createCylinderBBox(p1, p2, radius_c1, listFaces);
2029  addPolygon(listFaces, idFace, polygonName);
2030  idFace+=4;
2031 
2032  initCylinder(p1, p2, radius_c1, idRevolutionAxis, polygonName);
2033 }
2034 
2043 void
2044 vpMbTracker::extractLines(SoVRMLIndexedLineSet* line_set, int &idFace, const std::string &polygonName)
2045 {
2046  std::vector<vpPoint> corners;
2047  corners.resize(0);
2048 
2049  int indexListSize = line_set->coordIndex.getNum();
2050 
2051  SbVec3f point(0,0,0);
2052  vpPoint pt;
2053  SoVRMLCoordinate *coord;
2054 
2055  for (int i = 0; i < indexListSize; i++)
2056  {
2057  if (line_set->coordIndex[i] == -1)
2058  {
2059  if(corners.size() > 1)
2060  {
2061  addPolygon(corners, idFace++, polygonName);
2062  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
2063  corners.resize(0);
2064  }
2065  }
2066  else
2067  {
2068  coord = (SoVRMLCoordinate *)(line_set->coord.getValue());
2069  int index = line_set->coordIndex[i];
2070  point[0]=coord->point[index].getValue()[0];
2071  point[1]=coord->point[index].getValue()[1];
2072  point[2]=coord->point[index].getValue()[2];
2073 
2074  pt.setWorldCoordinates(point[0],point[1],point[2]);
2075  corners.push_back(pt);
2076  }
2077  }
2078 }
2079 
2080 #endif // VISP_HAVE_COIN3D
2081 
2091 vpPoint
2092 vpMbTracker::getGravityCenter(const std::vector<vpPoint>& pts) const
2093 {
2094  if(pts.empty()){
2095  std::cout << "Cannot extract center of gravity of empty set." << std::endl;
2096  throw vpException(vpException::dimensionError, "Cannot extract center of gravity of empty set.");
2097  }
2098  double oX = 0;
2099  double oY = 0;
2100  double oZ = 0;
2101  vpPoint G;
2102 
2103  for(unsigned int i=0; i<pts.size(); ++i){
2104  oX += pts[i].get_oX();
2105  oY += pts[i].get_oY();
2106  oZ += pts[i].get_oZ();
2107  }
2108 
2109  G.setWorldCoordinates(oX/pts.size(), oY/pts.size(), oZ/pts.size());
2110  return G;
2111 }
2112 
2123 std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > >
2124 vpMbTracker::getPolygonFaces(const bool orderPolygons, const bool useVisibility, const bool clipPolygon)
2125 {
2126  //Temporary variable to permit to order polygons by distance
2127  std::vector<vpPolygon> polygonsTmp;
2128  std::vector<std::vector<vpPoint> > roisPtTmp;
2129 
2130  //Pair containing the list of vpPolygon and the list of face corners
2131  std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > > pairOfPolygonFaces;
2132 
2133  for (unsigned int i = 0; i < faces.getPolygon().size(); i++) {
2134  //A face has at least 3 points
2135  if (faces.getPolygon()[i]->nbpt > 2) {
2136  if ( (useVisibility && faces.getPolygon()[i]->isvisible) || !useVisibility ) {
2137  std::vector<vpImagePoint> roiPts;
2138 
2139  if (clipPolygon) {
2140  faces.getPolygon()[i]->getRoiClipped(cam, roiPts, cMo);
2141  } else {
2142  roiPts = faces.getPolygon()[i]->getRoi(cam, cMo);
2143  }
2144 
2145  if (roiPts.size() <= 2) {
2146  continue;
2147  }
2148 
2149  polygonsTmp.push_back(vpPolygon(roiPts));
2150 
2151  std::vector<vpPoint> polyPts;
2152  if (clipPolygon) {
2153  faces.getPolygon()[i]->getPolygonClipped(polyPts);
2154  } else {
2155  for (unsigned int j = 0; j < faces.getPolygon()[i]->nbpt; j++) {
2156  polyPts.push_back(faces.getPolygon()[i]->p[j]);
2157  }
2158  }
2159  roisPtTmp.push_back(polyPts);
2160  }
2161  }
2162  }
2163 
2164  if(orderPolygons) {
2165  //Order polygons by distance (near to far)
2166  std::vector<PolygonFaceInfo> listOfPolygonFaces;
2167  for(unsigned int i = 0; i < polygonsTmp.size(); i++) {
2168  double x_centroid = 0.0, y_centroid = 0.0, z_centroid = 0.0;
2169  for(unsigned int j = 0; j < roisPtTmp[i].size(); j++) {
2170  x_centroid += roisPtTmp[i][j].get_X();
2171  y_centroid += roisPtTmp[i][j].get_Y();
2172  z_centroid += roisPtTmp[i][j].get_Z();
2173  }
2174 
2175  x_centroid /= roisPtTmp[i].size();
2176  y_centroid /= roisPtTmp[i].size();
2177  z_centroid /= roisPtTmp[i].size();
2178 
2179  double squared_dist = x_centroid*x_centroid + y_centroid*y_centroid + z_centroid*z_centroid;
2180  listOfPolygonFaces.push_back(PolygonFaceInfo(squared_dist, polygonsTmp[i], roisPtTmp[i]));
2181  }
2182 
2183  //Sort the list of polygon faces
2184  std::sort(listOfPolygonFaces.begin(), listOfPolygonFaces.end());
2185 
2186  polygonsTmp.resize(listOfPolygonFaces.size());
2187  roisPtTmp.resize(listOfPolygonFaces.size());
2188 
2189  size_t cpt = 0;
2190  for(std::vector<PolygonFaceInfo>::const_iterator it = listOfPolygonFaces.begin(); it != listOfPolygonFaces.end();
2191  ++it, cpt++) {
2192  polygonsTmp[cpt] = it->polygon;
2193  roisPtTmp[cpt] = it->faceCorners;
2194  }
2195 
2196  pairOfPolygonFaces.first = polygonsTmp;
2197  pairOfPolygonFaces.second = roisPtTmp;
2198  } else {
2199  pairOfPolygonFaces.first = polygonsTmp;
2200  pairOfPolygonFaces.second = roisPtTmp;
2201  }
2202 
2203  return pairOfPolygonFaces;
2204 }
2205 
2213 void
2215 {
2216  useOgre = v;
2217  if(useOgre){
2218 #ifndef VISP_HAVE_OGRE
2219  useOgre = false;
2220  std::cout << "WARNING: ViSP doesn't have Ogre3D, basic visibility test will be used. setOgreVisibilityTest() set to false." << std::endl;
2221 #endif
2222  }
2223 }
2224 
2230 void
2232 {
2233  if( (clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING && dist <= distNearClip)
2234  vpTRACE("Far clipping value cannot be inferior than near clipping value. Far clipping won't be considered.");
2235  else if ( dist < 0 )
2236  vpTRACE("Far clipping value cannot be inferior than 0. Far clipping won't be considered.");
2237  else{
2239  distFarClip = dist;
2240  for (unsigned int i = 0; i < faces.size(); i ++){
2241  faces[i]->setFarClippingDistance(distFarClip);
2242  }
2243 #ifdef VISP_HAVE_OGRE
2245 #endif
2246  }
2247 }
2248 
2258 void
2259 vpMbTracker::setLod(const bool useLod, const std::string &name)
2260 {
2261  for (unsigned int i = 0; i < faces.size(); i++)
2262  {
2263  if(name.empty() || faces[i]->name == name) {
2264  faces[i]->setLod(useLod);
2265  }
2266  }
2267 }
2268 
2277 void
2278 vpMbTracker::setMinLineLengthThresh(const double minLineLengthThresh, const std::string &name)
2279 {
2280  for (unsigned int i = 0; i < faces.size(); i++)
2281  {
2282  if(name.empty() || faces[i]->name == name) {
2283  faces[i]->setMinLineLengthThresh(minLineLengthThresh);
2284  }
2285  }
2286 }
2287 
2296 void
2297 vpMbTracker::setMinPolygonAreaThresh(const double minPolygonAreaThresh, const std::string &name)
2298 {
2299  for (unsigned int i = 0; i < faces.size(); i++)
2300  {
2301  if(name.empty() || faces[i]->name == name) {
2302  faces[i]->setMinPolygonAreaThresh(minPolygonAreaThresh);
2303  }
2304  }
2305 }
2306 
2312 void
2314 {
2315  if( (clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING && dist >= distFarClip)
2316  vpTRACE("Near clipping value cannot be superior than far clipping value. Near clipping won't be considered.");
2317  else if ( dist < 0 )
2318  vpTRACE("Near clipping value cannot be inferior than 0. Near clipping won't be considered.");
2319  else{
2321  distNearClip = dist;
2322  for (unsigned int i = 0; i < faces.size(); i ++){
2323  faces[i]->setNearClippingDistance(distNearClip);
2324  }
2325 #ifdef VISP_HAVE_OGRE
2327 #endif
2328  }
2329 }
2330 
2338 void
2339 vpMbTracker::setClipping(const unsigned int &flags)
2340 {
2341  clippingFlag = flags;
2342  for (unsigned int i = 0; i < faces.size(); i ++)
2344 }
2345 
2360 void
2361 vpMbTracker::computeJTR(const vpMatrix& interaction, const vpColVector& error, vpColVector& JTR) const
2362 {
2363  if(interaction.getRows() != error.getRows() || interaction.getCols() != 6 ){
2365  "Incorrect matrices size in computeJTR.");
2366  }
2367 
2368  JTR.resize(6);
2369  const unsigned int N = interaction.getRows();
2370 
2371  for (unsigned int i = 0; i < 6; i += 1){
2372  double ssum = 0;
2373  for (unsigned int j = 0; j < N; j += 1){
2374  ssum += interaction[j][i] * error[j];
2375  }
2376  JTR[i] = ssum;
2377  }
2378 }
2379 
2393 {
2394  vpColVector v(6);
2395  for(unsigned int i = 0 ; i < 6 ; i++)
2396  v[i] = oJo[i][i];
2397  return v;
2398 }
2399 
2413 void
2415 {
2416  if(v.getRows() == 6)
2417  {
2418  isoJoIdentity = true;
2419  for(unsigned int i = 0 ; i < 6 ; i++){
2420  // if(v[i] != 0){
2421  if(std::fabs(v[i]) > std::numeric_limits<double>::epsilon()){
2422  oJo[i][i] = 1.0;
2423  }
2424  else{
2425  oJo[i][i] = 0.0;
2426  isoJoIdentity = false;
2427  }
2428  }
2429  }
2430 }
2431 
2432 
2433 void
2434 vpMbTracker::createCylinderBBox(const vpPoint& p1, const vpPoint &p2, const double &radius, std::vector<std::vector<vpPoint> > &listFaces)
2435 {
2436  listFaces.clear();
2437 
2438 // std::vector<vpPoint> revolutionAxis;
2439 // revolutionAxis.push_back(p1);
2440 // revolutionAxis.push_back(p2);
2441 // listFaces.push_back(revolutionAxis);
2442 
2443  vpColVector axis(3);
2444  axis[0] = p1.get_oX() - p2.get_oX();
2445  axis[1] = p1.get_oY() - p2.get_oY();
2446  axis[2] = p1.get_oZ() - p2.get_oZ();
2447 
2448  vpColVector randomVec(3);
2449  randomVec = 0;
2450 
2451  vpColVector axisOrtho(3);
2452 
2453  randomVec[0] = 1.0;
2454  axisOrtho = vpColVector::crossProd(axis, randomVec);
2455 
2456  if(axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon())
2457  {
2458  randomVec = 0;
2459  randomVec[1] = 1.0;
2460  axisOrtho = vpColVector::crossProd(axis, randomVec);
2461  if(axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon())
2462  {
2463  randomVec = 0;
2464  randomVec[2] = 1.0;
2465  axisOrtho = vpColVector::crossProd(axis, randomVec);
2466  if(axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon())
2467  throw vpMatrixException(vpMatrixException::badValue, "Problem in the cylinder definition");
2468  }
2469  }
2470 
2471  axisOrtho.normalize();
2472 
2473  vpColVector axisOrthoBis(3);
2474  axisOrthoBis = vpColVector::crossProd(axis, axisOrtho);
2475  axisOrthoBis.normalize();
2476 
2477  //First circle
2478  vpColVector p1Vec(3);
2479  p1Vec[0] = p1.get_oX();
2480  p1Vec[1] = p1.get_oY();
2481  p1Vec[2] = p1.get_oZ();
2482  vpColVector fc1 = p1Vec + axisOrtho*radius;
2483  vpColVector fc2 = p1Vec + axisOrthoBis*radius;
2484  vpColVector fc3 = p1Vec - axisOrtho*radius;
2485  vpColVector fc4 = p1Vec - axisOrthoBis*radius;
2486 
2487  vpColVector p2Vec(3);
2488  p2Vec[0] = p2.get_oX();
2489  p2Vec[1] = p2.get_oY();
2490  p2Vec[2] = p2.get_oZ();
2491  vpColVector sc1 = p2Vec + axisOrtho*radius;
2492  vpColVector sc2 = p2Vec + axisOrthoBis*radius;
2493  vpColVector sc3 = p2Vec - axisOrtho*radius;
2494  vpColVector sc4 = p2Vec - axisOrthoBis*radius;
2495 
2496  std::vector<vpPoint> pointsFace;
2497  pointsFace.push_back( vpPoint(fc1[0], fc1[1], fc1[2]) );
2498  pointsFace.push_back( vpPoint(sc1[0], sc1[1], sc1[2]) );
2499  pointsFace.push_back( vpPoint(sc2[0], sc2[1], sc2[2]) );
2500  pointsFace.push_back( vpPoint(fc2[0], fc2[1], fc2[2]) );
2501  listFaces.push_back(pointsFace);
2502 
2503  pointsFace.clear();
2504  pointsFace.push_back( vpPoint(fc2[0], fc2[1], fc2[2]) );
2505  pointsFace.push_back( vpPoint(sc2[0], sc2[1], sc2[2]) );
2506  pointsFace.push_back( vpPoint(sc3[0], sc3[1], sc3[2]) );
2507  pointsFace.push_back( vpPoint(fc3[0], fc3[1], fc3[2]) );
2508  listFaces.push_back(pointsFace);
2509 
2510  pointsFace.clear();
2511  pointsFace.push_back( vpPoint(fc3[0], fc3[1], fc3[2]) );
2512  pointsFace.push_back( vpPoint(sc3[0], sc3[1], sc3[2]) );
2513  pointsFace.push_back( vpPoint(sc4[0], sc4[1], sc4[2]) );
2514  pointsFace.push_back( vpPoint(fc4[0], fc4[1], fc4[2]) );
2515  listFaces.push_back(pointsFace);
2516 
2517  pointsFace.clear();
2518  pointsFace.push_back( vpPoint(fc4[0], fc4[1], fc4[2]) );
2519  pointsFace.push_back( vpPoint(sc4[0], sc4[1], sc4[2]) );
2520  pointsFace.push_back( vpPoint(sc1[0], sc1[1], sc1[2]) );
2521  pointsFace.push_back( vpPoint(fc1[0], fc1[1], fc1[2]) );
2522  listFaces.push_back(pointsFace);
2523 }
2524 
virtual vpColVector getEstimatedDoF() const
vpDisplay * display
Definition: vpImage.h:135
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:97
virtual ~vpMbTracker()
bool parseBoolean(std::string &input)
Definition: vpMbTracker.h:643
Implements a 3D polygon with render functionnalities like clipping.
Definition: vpPolygon3D.h:59
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:169
virtual void setNbPoint(const unsigned int nb)
unsigned int nbLines
Number of lines in CAO model.
Definition: vpMbTracker.h:163
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
virtual void extractCylinders(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName="")
unsigned int getWidth() const
Definition: vpImage.h:226
vpPoint getGravityCenter(const std::vector< vpPoint > &_pts) const
std::map< std::string, std::string > parseParameters(std::string &endLine)
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1412
unsigned int nbCircles
Number of circles in CAO model.
Definition: vpMbTracker.h:171
vpMbHiddenFaces< vpMbtPolygon > faces
Set of faces describing the object.
Definition: vpMbTracker.h:144
void setNearClippingDistance(const double &dist)
Definition: vpAROgre.h:207
Implementation of an homogeneous matrix and operations on such kind of matrices.
virtual void extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, int &idFace)
std::map< std::string, std::string > mapOfParameterNames
Map with [map.first]=parameter_names and [map.second]=type (string, number or boolean) ...
Definition: vpMbTracker.h:181
double euclideanNorm() const
unsigned int nbCylinders
Number of cylinders in CAO model.
Definition: vpMbTracker.h:169
#define vpERROR_TRACE
Definition: vpDebug.h:391
unsigned int nbPoints
Number of points in CAO model.
Definition: vpMbTracker.h:161
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
vpHomogeneousMatrix cMo
The current pose.
Definition: vpMbTracker.h:115
virtual void initCircle(const vpPoint &p1, const vpPoint &p2, const vpPoint &p3, const double radius, const int idFace=0, const std::string &name="")=0
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:153
bool modelInitialised
Flag used to ensure that the CAD model is loaded before the initialisation.
Definition: vpMbTracker.h:123
double get_oY() const
Get the point Y coordinate in the object frame.
Definition: vpPoint.cpp:449
void setMinPolygonAreaThresh(const double min_polygon_area)
Definition: vpMbtPolygon.h:143
error that can be emited by ViSP classes.
Definition: vpException.h:73
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:770
void set_x(const double x)
Set the point x coordinate in the image plane.
Definition: vpPoint.cpp:496
virtual void loadCAOModel(const std::string &modelFile, std::vector< std::string > &vectorOfModelFilename, int &startIdFace, const bool verbose=false, const bool parent=true)
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Point coordinates conversion from pixel coordinates to normalized coordinates in meter...
void setName(const std::string &face_name)
Definition: vpMbtPolygon.h:152
Provides simple mathematics computation tools that are not available in the C mathematics library (ma...
Definition: vpMath.h:87
bool useOgre
Use Ogre3d for visibility tests.
Definition: vpMbTracker.h:156
unsigned int getCols() const
Return the number of columns of the 2D array.
Definition: vpArray2D.h:154
std::string modelFileName
The name of the file containing the model (it is used to create a file name.0.pos used to store the c...
Definition: vpMbTracker.h:121
virtual void setEstimatedDoF(const vpColVector &v)
virtual void initFromPose(const vpImage< unsigned char > &I, const std::string &initFile)
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1306
static const vpColor green
Definition: vpColor.h:166
static void flush(const vpImage< unsigned char > &I)
void setFarClippingDistance(const double &dist)
Definition: vpAROgre.h:197
virtual void extractLines(SoVRMLIndexedLineSet *line_set, int &idFace, const std::string &polygonName="")
static const vpColor red
Definition: vpColor.h:163
Class that defines what is a point.
Definition: vpPoint.h:59
vpCameraParameters cam
The camera parameters.
Definition: vpMbTracker.h:113
static Type maximum(const Type &a, const Type &b)
Definition: vpMath.h:140
Implementation of a rotation matrix and operations on such kind of matrices.
virtual void init(const vpImage< unsigned char > &I)=0
double distFarClip
Distance for near clipping.
Definition: vpMbTracker.h:152
void computeJTR(const vpMatrix &J, const vpColVector &R, vpColVector &JTR) const
static bool checkFilename(const char *filename)
Definition: vpIoTools.cpp:508
vpAROgre * getOgreContext()
Defines a generic 2D polygon.
Definition: vpPolygon.h:99
virtual void setMinPolygonAreaThresh(const double minPolygonAreaThresh, const std::string &name="")
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &col, const unsigned int thickness=1, const bool displayFullModel=false)=0
vpColVector & normalize()
vpMatrix oJo
The Degrees of Freedom to estimate.
Definition: vpMbTracker.h:117
Implementation of a polygon of the model used by the model-based tracker.
Definition: vpMbtPolygon.h:64
void savePose(const std::string &filename) const
#define vpTRACE
Definition: vpDebug.h:414
static double sqr(double x)
Definition: vpMath.h:110
double minLineLengthThresholdGeneral
Minimum line length threshold for LOD mode (general setting)
Definition: vpMbTracker.h:177
static std::string createFilePath(const std::string &parent, const std::string child)
Definition: vpIoTools.cpp:1366
static void display(const vpImage< unsigned char > &I)
void clear()
Definition: vpColVector.h:106
void createCylinderBBox(const vpPoint &p1, const vpPoint &p2, const double &radius, std::vector< std::vector< vpPoint > > &listFaces)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void addPoint(const unsigned int n, const vpPoint &P)
Class used for pose computation from N points (pose from point only). Some of the algorithms implemen...
Definition: vpPose.h:76
virtual void initFaceFromCorners(vpMbtPolygon &polygon)=0
double get_oZ() const
Get the point Z coordinate in the object frame.
Definition: vpPoint.cpp:451
void set_y(const double y)
Set the point y coordinate in the image plane.
Definition: vpPoint.cpp:498
Main methods for a model-based tracker.
Definition: vpMbTracker.h:103
bool computePose(vpPoseMethodType method, vpHomogeneousMatrix &cMo, bool(*func)(vpHomogeneousMatrix *)=NULL)
Definition: vpPose.cpp:372
std::string & trim(std::string &s) const
Definition: vpMbTracker.h:665
virtual void loadVRMLModel(const std::string &modelFile)
Implementation of a rotation vector as quaternion angle minimal representation.
void setIsPolygonOriented(const bool &oriented)
Definition: vpMbtPolygon.h:161
unsigned int nbPolygonLines
Number of polygon lines in CAO model.
Definition: vpMbTracker.h:165
unsigned int getRows() const
Return the number of rows of the 2D array.
Definition: vpArray2D.h:152
void addPolygon(PolygonType *p)
virtual void initClick(const vpImage< unsigned char > &I, const std::string &initFile, const bool displayHelp=false)
void buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
static std::string getName(const std::string &pathname)
Definition: vpIoTools.cpp:1271
static double rad(double deg)
Definition: vpMath.h:104
virtual void setMinLineLengthThresh(const double minLineLengthThresh, const std::string &name="")
std::string poseSavingFilename
Filename used to save the initial pose computed using the initClick() method. It is also used to read...
Definition: vpMbTracker.h:125
unsigned int size() const
double sumSquare() const
double get_oX() const
Get the point X coordinate in the object frame.
Definition: vpPoint.cpp:447
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color=vpColor::none, unsigned int thickness=1, vpImagePoint offset=vpImagePoint(0, 0))
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
unsigned int nbPolygonPoints
Number of polygon points in CAO model.
Definition: vpMbTracker.h:167
double minPolygonAreaThresholdGeneral
Minimum polygon area threshold for LOD mode (general setting)
Definition: vpMbTracker.h:179
virtual void setOgreVisibilityTest(const bool &v)
void setWorldCoordinates(const double oX, const double oY, const double oZ)
Definition: vpPoint.cpp:111
virtual void loadModel(const char *modelFile, const bool verbose=false)
int getWindowYPosition() const
Definition: vpDisplay.h:235
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:205
bool applyLodSettingInConfig
True if the CAO model is loaded before the call to loadConfigFile, (deduced by the number of polygons...
Definition: vpMbTracker.h:175
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
void setLod(const bool use_lod)
virtual void initFaceFromLines(vpMbtPolygon &polygon)=0
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:93
double getB() const
Definition: vpPlane.h:108
error that can be emited by the vpMatrix class and its derivates
double getA() const
Definition: vpPlane.h:106
static std::string getAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1328
vpPoseVector buildFrom(const double tx, const double ty, const double tz, const double tux, const double tuy, const double tuz)
virtual void setClipping(const unsigned int &flags)
double getC() const
Definition: vpPlane.h:110
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
void addPolygon(const std::vector< vpPoint > &corners, const int idFace=-1, const std::string &polygonName="", const bool useLod=false, const double minPolygonAreaThreshold=2500.0, const double minLineLengthThreshold=50.0)
static vpColVector crossProd(const vpColVector &a, const vpColVector &b)
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:58
unsigned int clippingFlag
Flags specifying which clipping to used.
Definition: vpMbTracker.h:154
virtual void initFromPoints(const vpImage< unsigned char > &I, const std::string &initFile)
virtual void setFarClippingDistance(const double &dist)
void addPoint(const vpPoint &P)
Definition: vpPose.cpp:145
double distNearClip
Distance for near clipping.
Definition: vpMbTracker.h:150
bool useLodGeneral
True if LOD mode is enabled.
Definition: vpMbTracker.h:173
virtual void extractFaces(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName="")
Class that consider the case of a translation vector.
void eye()
Definition: vpMatrix.cpp:194
bool isoJoIdentity
Boolean to know if oJo is identity (for fast computation)
Definition: vpMbTracker.h:119
virtual std::pair< std::vector< vpPolygon >, std::vector< std::vector< vpPoint > > > getPolygonFaces(const bool orderPolygons=true, const bool useVisibility=true, const bool clipPolygon=false)
void removeComment(std::ifstream &fileId)
double computeResidual(const vpHomogeneousMatrix &cMo) const
Compute and return the residual expressed in meter for the pose matrix 'cMo'.
Definition: vpPose.cpp:337
virtual void initCylinder(const vpPoint &p1, const vpPoint &p2, const double radius, const int idFace=0, const std::string &name="")=0
void setMinLineLengthThresh(const double min_line_length)
Definition: vpMbtPolygon.h:130
int getWindowXPosition() const
Definition: vpDisplay.h:230
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:225
std::vector< PolygonType * > & getPolygon()
virtual void setIndex(const int i)
Definition: vpMbtPolygon.h:116
void clearPoint()
Definition: vpPose.cpp:130
virtual void setLod(const bool useLod, const std::string &name="")
virtual void setNearClippingDistance(const double &dist)