Visual Servoing Platform  version 3.0.0
vpMbTracker.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 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 
97 struct SegmentInfo {
98  SegmentInfo() : extremities(), name(), useLod(false), minLineLengthThresh(0.) {}
99 
100  std::vector<vpPoint> extremities;
101  std::string name;
102  bool useLod;
103  double minLineLengthThresh;
104 };
105 
110 struct PolygonFaceInfo {
111  PolygonFaceInfo(const double dist, const vpPolygon &poly, const std::vector<vpPoint> &corners)
112 : distanceToCamera(dist), polygon(poly), faceCorners(corners) {}
113 
114  bool operator<(const PolygonFaceInfo &pfi) const {
115  return distanceToCamera < pfi.distanceToCamera;
116  }
117 
118  double distanceToCamera;
119  vpPolygon polygon;
120  std::vector<vpPoint> faceCorners;
121 };
122 #endif // DOXYGEN_SHOULD_SKIP_THIS
123 
130 : cam(), cMo(), oJo(6,6), isoJoIdentity(true), modelFileName(), modelInitialised(false),
131  poseSavingFilename(), computeCovariance(false), covarianceMatrix(), computeProjError(false),
132  projectionError(90.0), displayFeatures(false), m_w(), m_error(), m_optimizationMethod(vpMbTracker::GAUSS_NEWTON_OPT),
133  faces(), angleAppears( vpMath::rad(89) ), angleDisappears( vpMath::rad(89) ), distNearClip(0.001),
134  distFarClip(100), clippingFlag(vpPolygon3D::NO_CLIPPING), useOgre(false), ogreShowConfigDialog(false), useScanLine(false),
135  nbPoints(0), nbLines(0), nbPolygonLines(0), nbPolygonPoints(0), nbCylinders(0), nbCircles(0),
136  useLodGeneral(false), applyLodSettingInConfig(false), minLineLengthThresholdGeneral(50.0),
137  minPolygonAreaThresholdGeneral(2500.0), mapOfParameterNames()
138 {
139  oJo.eye();
140  //Map used to parse additional information in CAO model files,
141  //like name of faces or LOD setting
142  mapOfParameterNames["name"] = "string";
143  mapOfParameterNames["minPolygonAreaThreshold"] = "number";
144  mapOfParameterNames["minLineLengthThreshold"] = "number";
145  mapOfParameterNames["useLod"] = "boolean";
146 }
147 
152 {
153 }
154 
155 #ifdef VISP_HAVE_MODULE_GUI
156 
178 void
179 vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::string& initFile, const bool displayHelp)
180 {
181  vpHomogeneousMatrix last_cMo;
182  vpPoseVector init_pos;
183  vpImagePoint ip;
185 
186  std::string ext = ".init";
187  std::string str_pose = "";
188  size_t pos = (unsigned int)initFile.rfind(ext);
189 
190  // Load the last poses from files
191  std::fstream finitpos ;
192  std::fstream finit ;
193  char s[FILENAME_MAX];
194  if(poseSavingFilename.empty()){
195  if( pos == initFile.size()-ext.size() && pos != 0)
196  str_pose = initFile.substr(0,pos) + ".0.pos";
197  else
198  str_pose = initFile + ".0.pos";
199 
200  finitpos.open(str_pose.c_str() ,std::ios::in) ;
201  sprintf(s, "%s", str_pose.c_str());
202  }else{
203  finitpos.open(poseSavingFilename.c_str() ,std::ios::in) ;
204  sprintf(s, "%s", poseSavingFilename.c_str());
205  }
206  if(finitpos.fail() ){
207  std::cout << "cannot read " << s << std::endl << "cMo set to identity" << std::endl;
208  last_cMo.eye();
209  }
210  else{
211  for (unsigned int i = 0; i < 6; i += 1){
212  finitpos >> init_pos[i];
213  }
214 
215  finitpos.close();
216  last_cMo.buildFrom(init_pos) ;
217 
218  std::cout <<"last_cMo : "<<std::endl << last_cMo <<std::endl;
219 
221  display(I, last_cMo, cam, vpColor::green, 1, true);
222  vpDisplay::displayFrame(I, last_cMo, cam, 0.05, vpColor::green);
223  vpDisplay::flush(I);
224 
225  std::cout << "No modification : left click " << std::endl;
226  std::cout << "Modify initial pose : right click " << std::endl ;
227 
228  vpDisplay::displayText(I, 15, 10,
229  "left click to validate, right click to modify initial pose",
230  vpColor::red);
231 
232  vpDisplay::flush(I) ;
233 
234  while (!vpDisplay::getClick(I, ip, button)) ;
235  }
236 
237 
238  if (!finitpos.fail() && button == vpMouseButton::button1){
239  cMo = last_cMo ;
240  }
241  else
242  {
243  vpDisplay *d_help = NULL;
244 
245  vpDisplay::display(I) ;
246  vpDisplay::flush(I) ;
247 
248  vpPose pose ;
249 
250  pose.clearPoint() ;
251 
252  // file parser
253  // number of points
254  // X Y Z
255  // X Y Z
256 
257  double X,Y,Z ;
258 
259  if( pos == initFile.size()-ext.size() && pos != 0)
260  sprintf(s,"%s", initFile.c_str());
261  else
262  sprintf(s,"%s.init", initFile.c_str());
263 
264  std::cout << "Load 3D points from: " << s << std::endl ;
265  finit.open(s,std::ios::in) ;
266  if (finit.fail()){
267  std::cout << "cannot read " << s << std::endl;
268  throw vpException(vpException::ioError, "cannot read init file");
269  }
270 
271 #ifdef VISP_HAVE_MODULE_IO
272  //Display window creation and initialisation
273  try{
274  if(displayHelp){
275  std::string dispF;
276  if( pos == initFile.size()-ext.size() && pos != 0)
277  dispF = initFile.substr(0,pos) + ".ppm";
278  else
279  dispF = initFile + ".ppm";
280 
281  if (vpIoTools::checkFilename(dispF)) {
282  std::cout << "Load image to help initialization: " << dispF << std::endl;
283 #if defined VISP_HAVE_X11
284  d_help = new vpDisplayX ;
285 #elif defined VISP_HAVE_GDI
286  d_help = new vpDisplayGDI;
287 #elif defined VISP_HAVE_OPENCV
288  d_help = new vpDisplayOpenCV;
289 #endif
290 
291  vpImage<vpRGBa> Iref ;
292  vpImageIo::read(Iref, dispF) ;
293 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
294  d_help->init(Iref, I.display->getWindowXPosition()+(int)I.getWidth()+80, I.display->getWindowYPosition(),
295  "Where to initialize...") ;
296  vpDisplay::display(Iref) ;
297  vpDisplay::flush(Iref);
298 #endif
299  }
300  }
301  }
302  catch(...) {
303  if(d_help != NULL) {
304  delete d_help;
305  d_help = NULL;
306  }
307  }
308 #else //#ifdef VISP_HAVE_MODULE_IO
309  (void)(displayHelp);
310 #endif //#ifdef VISP_HAVE_MODULE_IO
311  char c;
312  // skip lines starting with # as comment
313  finit.get(c);
314  while (!finit.fail() && (c == '#')) {
315  finit.ignore(256, '\n');
316  finit.get(c);
317  }
318  finit.unget();
319 
320  unsigned int n ;
321  finit >> n ;
322  finit.ignore(256, '\n'); // skip the rest of the line
323  std::cout << "Number of 3D points " << n << std::endl ;
324  if (n > 100000) {
326  "Exceed the max number of points.");
327  }
328 
329  vpPoint *P = new vpPoint [n] ;
330  for (unsigned int i=0 ; i < n ; i++){
331  // skip lines starting with # as comment
332  finit.get(c);
333  while (!finit.fail() && (c == '#')) {
334  finit.ignore(256, '\n');
335  finit.get(c);
336  }
337  finit.unget();
338 
339  finit >> X ;
340  finit >> Y ;
341  finit >> Z ;
342  finit.ignore(256, '\n'); // skip the rest of the line
343 
344  std::cout << "Point " << i+1 << " with 3D coordinates: " << X << " " << Y << " " << Z << std::endl;
345  P[i].setWorldCoordinates(X,Y,Z) ; // (X,Y,Z)
346  }
347 
348  finit.close();
349 
351  bool isWellInit = false;
352  while(!isWellInit)
353  {
355  std::vector<vpImagePoint> mem_ip;
356  for(unsigned int i=0 ; i< n ; i++)
357  {
358  std::ostringstream text;
359  text << "Click on point " << i+1;
361  vpDisplay::displayText(I, 15, 10, text.str(), vpColor::red);
362  for (unsigned int k=0; k<mem_ip.size(); k++) {
363  vpDisplay::displayCross(I, mem_ip[k], 10, vpColor::green, 2) ;
364  }
365  vpDisplay::flush(I) ;
366 
367  std::cout << "Click on point " << i+1 << " ";
368  double x=0,y=0;
369  vpDisplay::getClick(I, ip) ;
370  mem_ip.push_back(ip);
371  vpDisplay::flush(I) ;
373  P[i].set_x(x);
374  P[i].set_y(y);
375 
376  std::cout << "with 2D coordinates: " << ip << std::endl;
377 
378  pose.addPoint(P[i]) ; // and added to the pose computation point list
379  }
380  vpDisplay::flush(I) ;
381  vpDisplay::display(I) ;
382 
383  vpHomogeneousMatrix cMo1, cMo2;
384  pose.computePose(vpPose::LAGRANGE, cMo1) ;
385  double d1 = pose.computeResidual(cMo1);
386  pose.computePose(vpPose::DEMENTHON, cMo2) ;
387  double d2 = pose.computeResidual(cMo2);
388 
389  if(d1 < d2){
390  cMo = cMo1;
391  }
392  else{
393  cMo = cMo2;
394  }
396 
397  display(I, cMo, cam, vpColor::green, 1, true);
398  vpDisplay::displayText(I, 15, 10,
399  "left click to validate, right click to re initialize object",
400  vpColor::red);
401 
402  vpDisplay::flush(I) ;
403 
404  button = vpMouseButton::button1;
405  while (!vpDisplay::getClick(I, ip, button)) ;
406 
407 
408  if (button == vpMouseButton::button1)
409  {
410  isWellInit = true;
411  }
412  else
413  {
414  pose.clearPoint() ;
415  vpDisplay::display(I) ;
416  vpDisplay::flush(I) ;
417  }
418  }
421 
422  delete [] P;
423 
424  //save the pose into file
425  if(poseSavingFilename.empty())
426  savePose(str_pose);
427  else
429 
430  if(d_help != NULL) {
431  delete d_help;
432  d_help = NULL;
433  }
434  }
435 
436  std::cout <<"cMo : "<<std::endl << cMo <<std::endl;
437 
438  init(I);
439 }
440 
450 void vpMbTracker::initClick(const vpImage<unsigned char>& I, const std::vector<vpPoint> &points3D_list,
451  const std::string &displayFile)
452 {
453  vpDisplay::display(I) ;
454  vpDisplay::flush(I) ;
455  vpDisplay *d_help = NULL;
456 
457  vpPose pose ;
458  std::vector<vpPoint> P;
459  for (unsigned int i=0 ; i < points3D_list.size() ; i++)
460  P.push_back( vpPoint(points3D_list[i].get_oX(), points3D_list[i].get_oY(), points3D_list[i].get_oZ()) );
461 
462 #ifdef VISP_HAVE_MODULE_IO
463  vpImage<vpRGBa> Iref ;
464  //Display window creation and initialisation
465  if(vpIoTools::checkFilename(displayFile)){
466  try{
467  std::cout << "Load image to help initialization: " << displayFile << std::endl;
468 #if defined VISP_HAVE_X11
469  d_help = new vpDisplayX ;
470 #elif defined VISP_HAVE_GDI
471  d_help = new vpDisplayGDI;
472 #elif defined VISP_HAVE_OPENCV
473  d_help = new vpDisplayOpenCV;
474 #endif
475 
476  vpImageIo::read(Iref, displayFile) ;
477 #if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV)
478  d_help->init(Iref, I.display->getWindowXPosition()+(int)I.getWidth()+80, I.display->getWindowYPosition(),
479  "Where to initialize...") ;
480  vpDisplay::display(Iref) ;
481  vpDisplay::flush(Iref);
482 #endif
483  }
484  catch(...) {
485  if(d_help != NULL) {
486  delete d_help;
487  d_help = NULL;
488  }
489  }
490  }
491 #else //#ifdef VISP_HAVE_MODULE_IO
492  (void)(displayFile);
493 #endif //#ifdef VISP_HAVE_MODULE_IO
494 
495  vpImagePoint ip;
496  bool isWellInit = false;
497  while(!isWellInit)
498  {
499  for(unsigned int i=0 ; i< points3D_list.size() ; i++)
500  {
501  std::cout << "Click on point " << i+1 << std::endl ;
502  double x=0,y=0;
503  vpDisplay::getClick(I, ip) ;
505  vpDisplay::flush(I) ;
507  P[i].set_x(x);
508  P[i].set_y(y);
509 
510  std::cout << "Click on point " << ip << std::endl;
511 
512  vpDisplay::displayPoint (I, ip, vpColor::green); //display target point
513  pose.addPoint(P[i]) ; // and added to the pose computation point list
514  }
515  vpDisplay::flush(I) ;
516 
517  vpHomogeneousMatrix cMo1, cMo2;
518  pose.computePose(vpPose::LAGRANGE, cMo1) ;
519  double d1 = pose.computeResidual(cMo1);
520  pose.computePose(vpPose::DEMENTHON, cMo2) ;
521  double d2 = pose.computeResidual(cMo2);
522 
523  if(d1 < d2){
524  cMo = cMo1;
525  }
526  else{
527  cMo = cMo2;
528  }
530 
531  display(I, cMo, cam, vpColor::green, 1, true);
532  vpDisplay::displayText(I, 15, 10,
533  "left click to validate, right click to re initialize object",
534  vpColor::red);
535 
536  vpDisplay::flush(I) ;
537 
539  while (!vpDisplay::getClick(I, ip, button)) ;
540 
541  if (button == vpMouseButton::button1)
542  {
543  isWellInit = true;
544  }
545  else
546  {
547  pose.clearPoint() ;
548  vpDisplay::display(I) ;
549  vpDisplay::flush(I) ;
550  }
551  }
552 
554 
555  if(d_help != NULL) {
556  delete d_help;
557  d_help = NULL;
558  }
559 
560  init(I);
561 }
562 #endif //#ifdef VISP_HAVE_MODULE_GUI
563 
581 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::string& initFile )
582 {
583  char s[FILENAME_MAX];
584  std::fstream finit ;
585 
586  std::string ext = ".init";
587  size_t pos = initFile.rfind(ext);
588 
589  if( pos == initFile.size()-ext.size() && pos != 0)
590  sprintf(s,"%s", initFile.c_str());
591  else
592  sprintf(s,"%s.init", initFile.c_str());
593 
594  std::cout << "filename " << s << std::endl ;
595  finit.open(s,std::ios::in) ;
596  if (finit.fail()){
597  std::cout << "cannot read " << s << std::endl;
598  throw vpException(vpException::ioError, "cannot read init file");
599  }
600 
601  unsigned int size;
602  double X, Y, Z;
603  finit >> size ;
604  std::cout << "number of points " << size << std::endl ;
605 
606  if (size > 100000) {
608  "Exceed the max number of points.");
609  }
610 
611  vpPoint *P = new vpPoint [size];
612  vpPose pose ;
613 
614  for(unsigned int i=0 ; i< size ; i++)
615  {
616  finit >> X ;
617  finit >> Y ;
618  finit >> Z ;
619  P[i].setWorldCoordinates(X,Y,Z) ;
620  }
621 
622  unsigned int size2;
623  double x, y;
624  vpImagePoint ip;
625  finit >> size2 ;
626  if(size != size2)
627  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
628 
629  for(unsigned int i=0 ; i< size ; i++)
630  {
631  finit >> x;
632  finit >> y;
633  ip = vpImagePoint(x,y);
635  P[i].set_x(x);
636  P[i].set_y(y);
637  pose.addPoint(P[i]);
638  }
639 
640  vpHomogeneousMatrix cMo1, cMo2;
641  pose.computePose(vpPose::LAGRANGE, cMo1) ;
642  double d1 = pose.computeResidual(cMo1);
643  pose.computePose(vpPose::DEMENTHON, cMo2) ;
644  double d2 = pose.computeResidual(cMo2);
645 
646  if(d1 < d2)
647  cMo = cMo1;
648  else
649  cMo = cMo2;
650 
652 
653  delete [] P;
654 
655  init(I);
656 }
657 
666 void vpMbTracker::initFromPoints( const vpImage<unsigned char>& I, const std::vector<vpImagePoint> &points2D_list,
667  const std::vector<vpPoint> &points3D_list )
668 {
669  if(points2D_list.size() != points3D_list.size())
670  vpERROR_TRACE( "vpMbTracker::initFromPoints(), Number of 2D points different to the number of 3D points." );
671 
672  size_t size = points3D_list.size();
673  std::vector<vpPoint> P;
674  vpPose pose ;
675 
676  for(size_t i=0 ; i< size ; i++)
677  {
678  P.push_back( vpPoint(points3D_list[i].get_oX(), points3D_list[i].get_oY(), points3D_list[i].get_oZ()) );
679  double x=0,y=0;
680  vpPixelMeterConversion::convertPoint(cam, points2D_list[i], x, y);
681  P[i].set_x(x);
682  P[i].set_y(y);
683  pose.addPoint(P[i]);
684  }
685 
686  vpHomogeneousMatrix cMo1, cMo2;
687  pose.computePose(vpPose::LAGRANGE, cMo1) ;
688  double d1 = pose.computeResidual(cMo1);
689  pose.computePose(vpPose::DEMENTHON, cMo2) ;
690  double d2 = pose.computeResidual(cMo2);
691 
692  if(d1 < d2)
693  cMo = cMo1;
694  else
695  cMo = cMo2;
696 
698 
699  init(I);
700 }
701 
719 void vpMbTracker::initFromPose(const vpImage<unsigned char>& I, const std::string &initFile)
720 {
721  char s[FILENAME_MAX];
722  std::fstream finit ;
723  vpPoseVector init_pos;
724 
725  std::string ext = ".pos";
726  size_t pos = initFile.rfind(ext);
727 
728  if( pos == initFile.size()-ext.size() && pos != 0)
729  sprintf(s,"%s", initFile.c_str());
730  else
731  sprintf(s,"%s.pos", initFile.c_str());
732 
733  finit.open(s,std::ios::in) ;
734  if (finit.fail()){
735  std::cout << "cannot read " << s << std::endl;
736  throw vpException(vpException::ioError, "cannot read init file");
737  }
738 
739  for (unsigned int i = 0; i < 6; i += 1){
740  finit >> init_pos[i];
741  }
742 
743  cMo.buildFrom(init_pos);
744  init(I);
745 }
746 
754 {
755  this->cMo = cMo_;
756  init(I);
757 }
758 
766 {
767  vpHomogeneousMatrix _cMo(cPo);
768  initFromPose(I, _cMo);
769 }
770 
776 void vpMbTracker::savePose(const std::string &filename)
777 {
778  vpPoseVector init_pos;
779  std::fstream finitpos ;
780  char s[FILENAME_MAX];
781 
782  sprintf(s,"%s", filename.c_str());
783  finitpos.open(s, std::ios::out) ;
784 
785  init_pos.buildFrom(cMo);
786  finitpos << init_pos;
787  finitpos.close();
788 }
789 
790 
791 void vpMbTracker::addPolygon(const std::vector<vpPoint>& corners, const int idFace, const std::string &polygonName,
792  const bool useLod, const double minPolygonAreaThreshold, const double minLineLengthThreshold)
793 {
794  std::vector<vpPoint> corners_without_duplicates;
795  corners_without_duplicates.push_back(corners[0]);
796  for (unsigned int i=0; i < corners.size()-1; i++) {
797  if (std::fabs(corners[i].get_oX() - corners[i+1].get_oX()) > std::fabs(corners[i].get_oX())*std::numeric_limits<double>::epsilon()
798  || std::fabs(corners[i].get_oY() - corners[i+1].get_oY()) > std::fabs(corners[i].get_oY())*std::numeric_limits<double>::epsilon()
799  || std::fabs(corners[i].get_oZ() - corners[i+1].get_oZ()) > std::fabs(corners[i].get_oZ())*std::numeric_limits<double>::epsilon()) {
800  corners_without_duplicates.push_back(corners[i+1]);
801  }
802  }
803 
804  vpMbtPolygon polygon;
805  polygon.setNbPoint((unsigned int)corners_without_duplicates.size());
806  polygon.setIndex((int)idFace);
807  polygon.setName(polygonName);
808  polygon.setLod(useLod);
809 
810 // //if(minPolygonAreaThreshold != -1.0) {
811 // if(std::fabs(minPolygonAreaThreshold + 1.0) > std::fabs(minPolygonAreaThreshold)*std::numeric_limits<double>::epsilon()) {
812 // polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
813 // }
814 //
815 // //if(minLineLengthThreshold != -1.0) {
816 // if(std::fabs(minLineLengthThreshold + 1.0) > std::fabs(minLineLengthThreshold)*std::numeric_limits<double>::epsilon()) {
817 // polygon.setMinLineLengthThresh(minLineLengthThreshold);
818 // }
819 
820  polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
821  polygon.setMinLineLengthThresh(minLineLengthThreshold);
822 
823  for(unsigned int j = 0; j < corners_without_duplicates.size(); j++) {
824  polygon.addPoint(j, corners_without_duplicates[j]);
825  }
826 
827  faces.addPolygon(&polygon);
828 
830  faces.getPolygon().back()->setClipping(clippingFlag);
831 
832  if((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
833  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
834 
835  if((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
836  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
837 }
838 
839 void vpMbTracker::addPolygon(const vpPoint& p1, const vpPoint &p2, const vpPoint &p3, const double radius,
840  const int idFace, const std::string &polygonName, const bool useLod, const double minPolygonAreaThreshold)
841 {
842  vpMbtPolygon polygon;
843  polygon.setNbPoint(4);
844  polygon.setName(polygonName);
845  polygon.setLod(useLod);
846 
847 // //if(minPolygonAreaThreshold != -1.0) {
848 // if(std::fabs(minPolygonAreaThreshold + 1.0) > std::fabs(minPolygonAreaThreshold)*std::numeric_limits<double>::epsilon()) {
849 // polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
850 // }
851  polygon.setMinPolygonAreaThresh(minPolygonAreaThreshold);
852  //Non sense to set minLineLengthThreshold for circle
853  //but used to be coherent when applying LOD settings for all polygons
855 
856  {
857  // Create the 4 points of the circle bounding box
858  vpPlane plane(p1, p2, p3, vpPlane::object_frame);
859 
860  // Matrice de passage entre world et circle frame
861  double norm_X = sqrt(vpMath::sqr(p2.get_oX()-p1.get_oX())
862  + vpMath::sqr(p2.get_oY()-p1.get_oY())
863  + vpMath::sqr(p2.get_oZ()-p1.get_oZ()));
864  double norm_Y = sqrt(vpMath::sqr(plane.getA())
865  + vpMath::sqr(plane.getB())
866  + vpMath::sqr(plane.getC()));
867  vpRotationMatrix wRc;
868  vpColVector x(3),y(3),z(3);
869  // X axis is P2-P1
870  x[0] = (p2.get_oX()-p1.get_oX()) / norm_X;
871  x[1] = (p2.get_oY()-p1.get_oY()) / norm_X;
872  x[2] = (p2.get_oZ()-p1.get_oZ()) / norm_X;
873  // Y axis is the normal of the plane
874  y[0] = plane.getA() / norm_Y;
875  y[1] = plane.getB() / norm_Y;
876  y[2] = plane.getC() / norm_Y;
877  // Z axis = X ^ Y
878  z = vpColVector::crossProd(x, y);
879  for (unsigned int i=0; i< 3; i++) {
880  wRc[i][0] = x[i];
881  wRc[i][1] = y[i];
882  wRc[i][2] = z[i];
883  }
884 
885  vpTranslationVector wtc(p1.get_oX(), p1.get_oY(), p1.get_oZ());
886  vpHomogeneousMatrix wMc(wtc, wRc);
887 
888  vpColVector c_p(4); // A point in the circle frame that is on the bbox
889  c_p[0] = radius;
890  c_p[1] = 0;
891  c_p[2] = radius;
892  c_p[3] = 1;
893 
894  // Matrix to rotate a point by 90 deg around Y in the circle frame
895  for(unsigned int i=0; i<4; i++) {
896  vpColVector w_p(4); // A point in the word frame
898  w_p = wMc * cMc_90 * c_p;
899 
900  vpPoint w_P;
901  w_P.setWorldCoordinates(w_p[0], w_p[1], w_p[2]);
902 
903  polygon.addPoint(i,w_P);
904  }
905  }
906 
907  polygon.setIndex(idFace);
908  faces.addPolygon(&polygon);
909 
911  faces.getPolygon().back()->setClipping(clippingFlag);
912 
913  if((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
914  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
915 
916  if((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
917  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
918 }
919 
920 void vpMbTracker::addPolygon(const vpPoint& p1, const vpPoint &p2, const int idFace, const std::string &polygonName,
921  const bool useLod, const double minLineLengthThreshold)
922 {
923  // A polygon as a single line that corresponds to the revolution axis of the cylinder
924  vpMbtPolygon polygon;
925  polygon.setNbPoint(2);
926 
927  polygon.addPoint(0, p1);
928  polygon.addPoint(1, p2);
929 
930  polygon.setIndex(idFace) ;
931  polygon.setName(polygonName);
932  polygon.setLod(useLod);
933 
934 // //if(minLineLengthThreshold != -1.0) {
935 // if(std::fabs(minLineLengthThreshold + 1.0) > std::fabs(minLineLengthThreshold)*std::numeric_limits<double>::epsilon()) {
936 // polygon.setMinLineLengthThresh(minLineLengthThreshold);
937 // }
938  polygon.setMinLineLengthThresh(minLineLengthThreshold);
939  //Non sense to set minPolygonAreaThreshold for cylinder
940  //but used to be coherent when applying LOD settings for all polygons
942 
943  faces.addPolygon(&polygon) ;
944 
946  faces.getPolygon().back()->setClipping(clippingFlag);
947 
948  if((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
949  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
950 
951  if((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
952  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
953 }
954 
955 void vpMbTracker::addPolygon(const std::vector<std::vector<vpPoint> > &listFaces, const int idFace, const std::string &polygonName,
956  const bool useLod, const double minLineLengthThreshold)
957 {
958  int id = idFace;
959  for(unsigned int i = 0 ; i < listFaces.size() ; i++)
960  {
961  vpMbtPolygon polygon;
962  polygon.setNbPoint((unsigned int)listFaces[i].size());
963  for(unsigned int j = 0 ; j < listFaces[i].size() ; j++)
964  polygon.addPoint(j, listFaces[i][j]);
965 
966  polygon.setIndex(id) ;
967  polygon.setName(polygonName);
968  polygon.setIsPolygonOriented(false);
969  polygon.setLod(useLod);
970  polygon.setMinLineLengthThresh(minLineLengthThreshold);
972 
973  faces.addPolygon(&polygon) ;
974 
976  faces.getPolygon().back()->setClipping(clippingFlag);
977 
978  if((clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
979  faces.getPolygon().back()->setNearClippingDistance(distNearClip);
980 
981  if((clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
982  faces.getPolygon().back()->setFarClippingDistance(distFarClip);
983 
984  id++;
985  }
986 }
987 
1013 void
1014 vpMbTracker::loadModel(const char *modelFile, const bool verbose)
1015 {
1016  loadModel( std::string(modelFile), verbose );
1017 }
1018 
1044 void
1045 vpMbTracker::loadModel(const std::string& modelFile, const bool verbose)
1046 {
1047  std::string::const_iterator it;
1048 
1049  if(vpIoTools::checkFilename(modelFile)) {
1050  it = modelFile.end();
1051  if((*(it-1) == 'o' && *(it-2) == 'a' && *(it-3) == 'c' && *(it-4) == '.') ||
1052  (*(it-1) == 'O' && *(it-2) == 'A' && *(it-3) == 'C' && *(it-4) == '.') ){
1053  std::vector<std::string> vectorOfModelFilename;
1054  int startIdFace = faces.size();
1055  nbPoints = 0;
1056  nbLines = 0;
1057  nbPolygonLines = 0;
1058  nbPolygonPoints = 0;
1059  nbCylinders = 0;
1060  nbCircles = 0;
1061  loadCAOModel(modelFile, vectorOfModelFilename, startIdFace, verbose, true);
1062  }
1063  else if((*(it-1) == 'l' && *(it-2) == 'r' && *(it-3) == 'w' && *(it-4) == '.') ||
1064  (*(it-1) == 'L' && *(it-2) == 'R' && *(it-3) == 'W' && *(it-4) == '.') ){
1065  loadVRMLModel(modelFile);
1066  }
1067  else{
1068  throw vpException(vpException::ioError, "Error: File %s doesn't contain a cao or wrl model", modelFile.c_str());
1069  }
1070  }
1071  else{
1072  throw vpException(vpException::ioError, "Error: File %s doesn't exist", modelFile.c_str());
1073  }
1074 
1075  this->modelInitialised = true;
1076  this->modelFileName = modelFile;
1077 }
1078 
1079 
1110 void
1111 vpMbTracker::loadVRMLModel(const std::string& modelFile)
1112 {
1113 #ifdef VISP_HAVE_COIN3D
1114  SoDB::init(); // Call SoDB::finish() before ending the program.
1115 
1116  SoInput in;
1117  SbBool ok = in.openFile(modelFile.c_str());
1118  SoSeparator *sceneGraph;
1119  SoVRMLGroup *sceneGraphVRML2;
1120 
1121  if (!ok) {
1122  vpERROR_TRACE("can't open file to load model");
1123  throw vpException(vpException::fatalError, "can't open file to load model");
1124  }
1125 
1126  if(!in.isFileVRML2())
1127  {
1128  sceneGraph = SoDB::readAll(&in);
1129  if (sceneGraph == NULL) { /*return -1;*/ }
1130  sceneGraph->ref();
1131 
1132  SoToVRML2Action tovrml2;
1133  tovrml2.apply(sceneGraph);
1134 
1135  sceneGraphVRML2 =tovrml2.getVRML2SceneGraph();
1136  sceneGraphVRML2->ref();
1137  sceneGraph->unref();
1138  }
1139  else
1140  {
1141  sceneGraphVRML2 = SoDB::readAllVRML(&in);
1142  if (sceneGraphVRML2 == NULL) { /*return -1;*/ }
1143  sceneGraphVRML2->ref();
1144  }
1145 
1146  in.closeFile();
1147 
1148  vpHomogeneousMatrix transform;
1149  int indexFace = faces.size();
1150  extractGroup(sceneGraphVRML2, transform, indexFace);
1151 
1152  sceneGraphVRML2->unref();
1153 #else
1154  vpERROR_TRACE("coin not detected with ViSP, cannot load model : %s", modelFile.c_str());
1155  throw vpException(vpException::fatalError, "coin not detected with ViSP, cannot load model");
1156 #endif
1157 }
1158 
1159 void vpMbTracker::removeComment(std::ifstream& fileId) {
1160  char c;
1161 
1162  fileId.get(c);
1163  while (!fileId.fail() && (c == '#')) {
1164  fileId.ignore(256, '\n');
1165  fileId.get(c);
1166  }
1167  if (fileId.fail())
1168  throw(vpException(vpException::ioError, "Reached end of file"));
1169  fileId.unget();
1170 }
1171 
1172 std::map<std::string, std::string> vpMbTracker::parseParameters(std::string& endLine) {
1173  std::map<std::string, std::string> mapOfParams;
1174 
1175  bool exit = false;
1176  while (!endLine.empty() && !exit) {
1177  exit = true;
1178 
1179  for (std::map<std::string, std::string>::const_iterator it =
1180  mapOfParameterNames.begin(); it != mapOfParameterNames.end();
1181  ++it) {
1182  endLine = trim(endLine);
1183  // std::cout << "endLine=" << endLine << std::endl;
1184  std::string param(it->first + "=");
1185 
1186  //Compare with a potential parameter
1187  if (endLine.compare(0, param.size(), param) == 0) {
1188  exit = false;
1189  endLine = endLine.substr(param.size());
1190 
1191  bool parseQuote = false;
1192  if (it->second == "string") {
1193  //Check if the string is between quotes
1194  if (endLine.size() > 2 && endLine[0] == '"') {
1195  parseQuote = true;
1196  endLine = endLine.substr(1);
1197  size_t pos = endLine.find_first_of('"');
1198 
1199  if (pos != std::string::npos) {
1200  mapOfParams[it->first] = endLine.substr(0, pos);
1201  endLine = endLine.substr(pos + 1);
1202  } else {
1203  parseQuote = false;
1204  }
1205  }
1206  }
1207 
1208  if (!parseQuote) {
1209  //Deal with space or tabulation after parameter value to substring
1210  // to the next sequence
1211  size_t pos1 = endLine.find_first_of(' ');
1212  size_t pos2 = endLine.find_first_of('\t');
1213  size_t pos = pos1 < pos2 ? pos1 : pos2;
1214 
1215  mapOfParams[it->first] = endLine.substr(0, pos);
1216  endLine = endLine.substr(pos + 1);
1217  }
1218  }
1219  }
1220  }
1221 
1222 // for(std::map<std::string, std::string>::const_iterator it = mapOfParams.begin(); it != mapOfParams.end(); ++it) {
1223 // std::cout << it->first << "=" << it->second << std::endl;
1224 // }
1225 
1226  return mapOfParams;
1227 }
1228 
1274 void
1275 vpMbTracker::loadCAOModel(const std::string& modelFile,
1276  std::vector<std::string>& vectorOfModelFilename, int& startIdFace,
1277  const bool verbose, const bool parent) {
1278  std::ifstream fileId;
1279  fileId.exceptions(std::ifstream::failbit | std::ifstream::eofbit);
1280  fileId.open(modelFile.c_str(), std::ifstream::in);
1281  if (fileId.fail()) {
1282  std::cout << "cannot read CAO model file: " << modelFile << std::endl;
1283  throw vpException(vpException::ioError, "cannot read CAO model file");
1284  }
1285 
1286  if(verbose) {
1287  std::cout << "Model file : " << modelFile << std::endl;
1288  }
1289  vectorOfModelFilename.push_back(modelFile);
1290 
1291  try {
1292  char c;
1293  // Extraction of the version (remove empty line and commented ones (comment
1294  // line begin with the #)).
1295  //while ((fileId.get(c) != NULL) && (c == '#')) fileId.ignore(256, '\n');
1296  removeComment(fileId);
1297 
1299  int caoVersion;
1300  fileId.get(c);
1301  if (c == 'V') {
1302  fileId >> caoVersion;
1303  fileId.ignore(256, '\n'); // skip the rest of the line
1304  } else {
1305  std::cout
1306  << "in vpMbTracker::loadCAOModel() -> Bad parameter header file : use V0, V1, ...";
1308  "in vpMbTracker::loadCAOModel() -> Bad parameter header file : use V0, V1, ...");
1309  }
1310 
1311  removeComment(fileId);
1312 
1313 
1315  std::string line;
1316  std::string prefix = "load";
1317 
1318  fileId.get(c);
1319  fileId.unget();
1320  bool header = false;
1321  while(c == 'l' || c == 'L') {
1322  header = true;
1323 
1324  getline(fileId, line);
1325  if(!line.compare(0, prefix.size(), prefix)) {
1326 
1327  //Get the loaded model pathname
1328  std::string headerPathname = line.substr(6);
1329  size_t firstIndex = headerPathname.find_first_of("\")");
1330  headerPathname = headerPathname.substr(0, firstIndex);
1331 
1332  std::string headerPath = headerPathname;
1333  if(!vpIoTools::isAbsolutePathname(headerPathname)) {
1334  std::string parentDirectory = vpIoTools::getParent(modelFile);
1335  headerPath = vpIoTools::createFilePath(parentDirectory, headerPathname);
1336  }
1337 
1338  bool cyclic = false;
1339  std::string headerModelFilename = vpIoTools::getName(headerPath);
1340  if (!headerModelFilename.compare(vpIoTools::getName(modelFile))) {
1341  cyclic = true;
1342  }
1343 
1344  for (std::vector<std::string>::const_iterator it =
1345  vectorOfModelFilename.begin();
1346  it != vectorOfModelFilename.end() - 1 && !cyclic;
1347  ++it) {
1348  std::string loadedModelFilename = vpIoTools::getName(*it);
1349  if (!headerModelFilename.compare(loadedModelFilename)) {
1350  cyclic = true;
1351  }
1352  }
1353 
1354  if (!cyclic) {
1355  if (vpIoTools::checkFilename(modelFile)) {
1356  loadCAOModel(headerPath, vectorOfModelFilename, startIdFace, verbose, false);
1357  } else {
1359  "file cannot be open");
1360  }
1361  } else {
1362  std::cout << "WARNING Cyclic dependency detected with file "
1363  << headerPath << " declared in " << modelFile << std::endl;
1364  }
1365  } else {
1366  header = false;
1367  }
1368 
1369  removeComment(fileId);
1370  fileId.get(c);
1371  fileId.unget();
1372  }
1373 
1374 
1376  unsigned int caoNbrPoint;
1377  fileId >> caoNbrPoint;
1378  fileId.ignore(256, '\n'); // skip the rest of the line
1379 
1380  nbPoints += caoNbrPoint;
1381  if(verbose || vectorOfModelFilename.size() == 1) {
1382  std::cout << "> " << caoNbrPoint << " points" << std::endl;
1383  }
1384 
1385  if (caoNbrPoint > 100000) {
1387  "Exceed the max number of points in the CAO model.");
1388  }
1389 
1390  if (caoNbrPoint == 0 && !header) {
1392  "in vpMbTracker::loadCAOModel() -> no points are defined");
1393  }
1394  vpPoint *caoPoints = new vpPoint[caoNbrPoint];
1395 
1396  double x; // 3D coordinates
1397  double y;
1398  double z;
1399 
1400  int i; // image coordinate (used for matching)
1401  int j;
1402 
1403  for (unsigned int k = 0; k < caoNbrPoint; k++) {
1404  removeComment(fileId);
1405 
1406  fileId >> x;
1407  fileId >> y;
1408  fileId >> z;
1409 
1410  if (caoVersion == 2) {
1411  fileId >> i;
1412  fileId >> j;
1413  }
1414 
1415  fileId.ignore(256, '\n'); // skip the rest of the line
1416 
1417  caoPoints[k].setWorldCoordinates(x, y, z);
1418  }
1419 
1420 
1421  removeComment(fileId);
1422 
1423 
1425  //Store in a map the potential segments to add
1426  std::map<std::pair<unsigned int, unsigned int>, SegmentInfo > segmentTemporaryMap;
1427  unsigned int caoNbrLine;
1428  fileId >> caoNbrLine;
1429  fileId.ignore(256, '\n'); // skip the rest of the line
1430 
1431  nbLines += caoNbrLine;
1432  unsigned int *caoLinePoints = NULL;
1433  if(verbose || vectorOfModelFilename.size() == 1) {
1434  std::cout << "> " << caoNbrLine << " lines" << std::endl;
1435  }
1436 
1437  if (caoNbrLine > 100000) {
1438  delete[] caoPoints;
1440  "Exceed the max number of lines in the CAO model.");
1441  }
1442 
1443  if (caoNbrLine > 0)
1444  caoLinePoints = new unsigned int[2 * caoNbrLine];
1445 
1446  unsigned int index1, index2;
1447  //Initialization of idFace with startIdFace for dealing with recursive load in header
1448  int idFace = startIdFace;
1449 
1450  for (unsigned int k = 0; k < caoNbrLine; k++) {
1451  removeComment(fileId);
1452 
1453  fileId >> index1;
1454  fileId >> index2;
1455 
1457  //Get the end of the line
1458  char buffer[256];
1459  fileId.getline(buffer, 256);
1460  std::string endLine(buffer);
1461  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1462 
1463 // fileId.ignore(256, '\n'); // skip the rest of the line
1464 
1465  std::string segmentName = "";
1466  double minLineLengthThresh = !applyLodSettingInConfig ? minLineLengthThresholdGeneral : 50.0;
1467  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1468  if(mapOfParams.find("name") != mapOfParams.end()) {
1469  segmentName = mapOfParams["name"];
1470  }
1471  if(mapOfParams.find("minLineLengthThreshold") != mapOfParams.end()) {
1472  minLineLengthThresh = std::atof(mapOfParams["minLineLengthThreshold"].c_str());
1473  }
1474  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1475  useLod = parseBoolean(mapOfParams["useLod"]);
1476  }
1477 
1478  SegmentInfo segmentInfo;
1479  segmentInfo.name = segmentName;
1480  segmentInfo.useLod = useLod;
1481  segmentInfo.minLineLengthThresh = minLineLengthThresh;
1482 
1483  caoLinePoints[2 * k] = index1;
1484  caoLinePoints[2 * k + 1] = index2;
1485 
1486  if (index1 < caoNbrPoint && index2 < caoNbrPoint) {
1487  std::vector<vpPoint> extremities;
1488  extremities.push_back(caoPoints[index1]);
1489  extremities.push_back(caoPoints[index2]);
1490  segmentInfo.extremities = extremities;
1491 
1492  std::pair<unsigned int, unsigned int> key(index1, index2);
1493 
1494  segmentTemporaryMap[key] = segmentInfo;
1495 // addPolygon(extremities, idFace++);
1496 // initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1497  } else {
1498  vpTRACE(" line %d has wrong coordinates.", k);
1499  }
1500  }
1501 
1502  removeComment(fileId);
1503 
1504 
1506  /* Load polygon from the lines extracted earlier (the first point of the line is used)*/
1507  //Store in a vector the indexes of the segments added in the face segment case
1508  std::vector<std::pair<unsigned int, unsigned int> > faceSegmentKeyVector;
1509  unsigned int caoNbrPolygonLine;
1510  fileId >> caoNbrPolygonLine;
1511  fileId.ignore(256, '\n'); // skip the rest of the line
1512 
1513  nbPolygonLines += caoNbrPolygonLine;
1514  if(verbose || vectorOfModelFilename.size() == 1) {
1515  std::cout << "> " << caoNbrPolygonLine << " polygon lines" << std::endl;
1516  }
1517 
1518  if (caoNbrPolygonLine > 100000) {
1519  delete[] caoPoints;
1520  delete[] caoLinePoints;
1522  "Exceed the max number of polygon lines.");
1523  }
1524 
1525  unsigned int index;
1526  for (unsigned int k = 0; k < caoNbrPolygonLine; k++) {
1527  removeComment(fileId);
1528 
1529  unsigned int nbLinePol;
1530  fileId >> nbLinePol;
1531  std::vector<vpPoint> corners;
1532  if (nbLinePol > 100000) {
1533  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1534  }
1535 
1536  for (unsigned int n = 0; n < nbLinePol; n++) {
1537  fileId >> index;
1538 // if (2 * index > 2 * caoNbrLine - 1) {
1539  if(index >= caoNbrLine) {
1540  throw vpException(vpException::badValue, "Exceed the max number of lines.");
1541  }
1542  corners.push_back(caoPoints[caoLinePoints[2 * index]]);
1543  corners.push_back(caoPoints[caoLinePoints[2 * index + 1]]);
1544 
1545  std::pair<unsigned int, unsigned int> key(caoLinePoints[2 * index], caoLinePoints[2 * index + 1]);
1546  faceSegmentKeyVector.push_back(key);
1547  }
1548 
1549 
1551  //Get the end of the line
1552  char buffer[256];
1553  fileId.getline(buffer, 256);
1554  std::string endLine(buffer);
1555  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1556 
1557 // fileId.ignore(256, '\n'); // skip the rest of the line
1558 
1559  std::string polygonName = "";
1560  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1561  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1562  if(mapOfParams.find("name") != mapOfParams.end()) {
1563  polygonName = mapOfParams["name"];
1564  }
1565  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1566  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1567  }
1568  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1569  useLod = parseBoolean(mapOfParams["useLod"]);
1570  }
1571 
1572  addPolygon(corners, idFace++, polygonName, useLod, minPolygonAreaThreshold, minLineLengthThresholdGeneral);
1573  // initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1574  initFaceFromLines(*(faces.getPolygon().back())); // Init from the last polygon that was added
1575  }
1576 
1577  //Add the segments which were not already added in the face segment case
1578  for(std::map<std::pair<unsigned int, unsigned int>, SegmentInfo >::const_iterator it =
1579  segmentTemporaryMap.begin(); it != segmentTemporaryMap.end(); ++it) {
1580  if(std::find(faceSegmentKeyVector.begin(), faceSegmentKeyVector.end(), it->first) == faceSegmentKeyVector.end()) {
1581  addPolygon(it->second.extremities, idFace++, it->second.name, it->second.useLod, minPolygonAreaThresholdGeneral,
1582  it->second.minLineLengthThresh);
1583  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1584  }
1585  }
1586 
1587  removeComment(fileId);
1588 
1589 
1591  /* Extract the polygon using the point coordinates (top of the file) */
1592  unsigned int caoNbrPolygonPoint;
1593  fileId >> caoNbrPolygonPoint;
1594  fileId.ignore(256, '\n'); // skip the rest of the line
1595 
1596  nbPolygonPoints += caoNbrPolygonPoint;
1597  if(verbose || vectorOfModelFilename.size() == 1) {
1598  std::cout << "> " << caoNbrPolygonPoint << " polygon points"
1599  << std::endl;
1600  }
1601 
1602  if (caoNbrPolygonPoint > 100000) {
1604  "Exceed the max number of polygon point.");
1605  }
1606 
1607  for (unsigned int k = 0; k < caoNbrPolygonPoint; k++) {
1608  removeComment(fileId);
1609 
1610  unsigned int nbPointPol;
1611  fileId >> nbPointPol;
1612  if (nbPointPol > 100000) {
1614  "Exceed the max number of points.");
1615  }
1616  std::vector<vpPoint> corners;
1617  for (unsigned int n = 0; n < nbPointPol; n++) {
1618  fileId >> index;
1619  if (index > caoNbrPoint - 1) {
1621  "Exceed the max number of points.");
1622  }
1623  corners.push_back(caoPoints[index]);
1624  }
1625 
1626 
1628  //Get the end of the line
1629  char buffer[256];
1630  fileId.getline(buffer, 256);
1631  std::string endLine(buffer);
1632  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1633 
1634 // fileId.ignore(256, '\n'); // skip the rest of the line
1635 
1636  std::string polygonName = "";
1637  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1638  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1639  if(mapOfParams.find("name") != mapOfParams.end()) {
1640  polygonName = mapOfParams["name"];
1641  }
1642  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1643  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1644  }
1645  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1646  useLod = parseBoolean(mapOfParams["useLod"]);
1647  }
1648 
1649 
1650  addPolygon(corners, idFace++, polygonName, useLod, minPolygonAreaThreshold, minLineLengthThresholdGeneral);
1651  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1652  }
1653 
1655  unsigned int caoNbCylinder;
1656  try {
1657  removeComment(fileId);
1658 
1659  if (fileId.eof()) { // check if not at the end of the file (for old style files)
1660  delete[] caoPoints;
1661  delete[] caoLinePoints;
1662  return;
1663  }
1664 
1665  /* Extract the cylinders */
1666  fileId >> caoNbCylinder;
1667  fileId.ignore(256, '\n'); // skip the rest of the line
1668 
1669  nbCylinders += caoNbCylinder;
1670  if(verbose || vectorOfModelFilename.size() == 1) {
1671  std::cout << "> " << caoNbCylinder << " cylinders" << std::endl;
1672  }
1673 
1674  if (caoNbCylinder > 100000) {
1676  "Exceed the max number of cylinders.");
1677  }
1678 
1679  for (unsigned int k = 0; k < caoNbCylinder; ++k) {
1680  removeComment(fileId);
1681 
1682  double radius;
1683  unsigned int indexP1, indexP2;
1684  fileId >> indexP1;
1685  fileId >> indexP2;
1686  fileId >> radius;
1687 
1689  //Get the end of the line
1690  char buffer[256];
1691  fileId.getline(buffer, 256);
1692  std::string endLine(buffer);
1693  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1694 
1695 // fileId.ignore(256, '\n'); // skip the rest of the line
1696 
1697  std::string polygonName = "";
1698  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1699  double minLineLengthThreshold = !applyLodSettingInConfig ? minLineLengthThresholdGeneral : 50.0;
1700  if(mapOfParams.find("name") != mapOfParams.end()) {
1701  polygonName = mapOfParams["name"];
1702  }
1703  if(mapOfParams.find("minLineLengthThreshold") != mapOfParams.end()) {
1704  minLineLengthThreshold = std::atof(mapOfParams["minLineLengthThreshold"].c_str());
1705  }
1706  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1707  useLod = parseBoolean(mapOfParams["useLod"]);
1708  }
1709 
1710  int idRevolutionAxis = idFace;
1711  addPolygon(caoPoints[indexP1], caoPoints[indexP2], idFace++, polygonName, useLod, minLineLengthThreshold);
1712 
1713  std::vector<std::vector<vpPoint> > listFaces;
1714  createCylinderBBox(caoPoints[indexP1], caoPoints[indexP2], radius,listFaces);
1715  addPolygon(listFaces, idFace, polygonName, useLod, minLineLengthThreshold);
1716  idFace+=4;
1717 
1718  initCylinder(caoPoints[indexP1], caoPoints[indexP2], radius, idRevolutionAxis, polygonName);
1719  }
1720 
1721  } catch (...) {
1722  std::cerr
1723  << "Cannot get the number of cylinders. Defaulting to zero."
1724  << std::endl;
1725  caoNbCylinder = 0;
1726  }
1727 
1728 
1730  unsigned int caoNbCircle;
1731  try {
1732  removeComment(fileId);
1733 
1734  if (fileId.eof()) { // check if not at the end of the file (for old style files)
1735  delete[] caoPoints;
1736  delete[] caoLinePoints;
1737  return;
1738  }
1739 
1740  /* Extract the circles */
1741  fileId >> caoNbCircle;
1742  fileId.ignore(256, '\n'); // skip the rest of the line
1743 
1744  nbCircles += caoNbCircle;
1745  if(verbose || vectorOfModelFilename.size() == 1) {
1746  std::cout << "> " << caoNbCircle << " circles" << std::endl;
1747  }
1748 
1749  if (caoNbCircle > 100000) {
1751  "Exceed the max number of cicles.");
1752  }
1753 
1754  for (unsigned int k = 0; k < caoNbCircle; ++k) {
1755  removeComment(fileId);
1756 
1757  double radius;
1758  unsigned int indexP1, indexP2, indexP3;
1759  fileId >> radius;
1760  fileId >> indexP1;
1761  fileId >> indexP2;
1762  fileId >> indexP3;
1763 
1765  //Get the end of the line
1766  char buffer[256];
1767  fileId.getline(buffer, 256);
1768  std::string endLine(buffer);
1769  std::map<std::string, std::string> mapOfParams = parseParameters(endLine);
1770 
1771 // fileId.ignore(256, '\n'); // skip the rest of the line
1772 
1773  std::string polygonName = "";
1774  bool useLod = !applyLodSettingInConfig ? useLodGeneral : false;
1775  double minPolygonAreaThreshold = !applyLodSettingInConfig ? minPolygonAreaThresholdGeneral : 2500.0;
1776  if(mapOfParams.find("name") != mapOfParams.end()) {
1777  polygonName = mapOfParams["name"];
1778  }
1779  if(mapOfParams.find("minPolygonAreaThreshold") != mapOfParams.end()) {
1780  minPolygonAreaThreshold = std::atof(mapOfParams["minPolygonAreaThreshold"].c_str());
1781  }
1782  if(mapOfParams.find("useLod") != mapOfParams.end()) {
1783  useLod = parseBoolean(mapOfParams["useLod"]);
1784  }
1785 
1786  addPolygon(caoPoints[indexP1], caoPoints[indexP2],
1787  caoPoints[indexP3], radius, idFace, polygonName, useLod, minPolygonAreaThreshold);
1788 
1789  initCircle(caoPoints[indexP1], caoPoints[indexP2],
1790  caoPoints[indexP3], radius, idFace++, polygonName);
1791  }
1792 
1793  } catch (...) {
1794  std::cerr << "Cannot get the number of circles. Defaulting to zero."
1795  << std::endl;
1796  caoNbCircle = 0;
1797  }
1798 
1799  startIdFace = idFace;
1800 
1801  delete[] caoPoints;
1802  delete[] caoLinePoints;
1803 
1804  if(vectorOfModelFilename.size() > 1 && parent) {
1805  if(verbose) {
1806  std::cout << "Global information for " << vpIoTools::getName(modelFile) << " :" << std::endl;
1807  std::cout << "Total nb of points : " << nbPoints << std::endl;
1808  std::cout << "Total nb of lines : " << nbLines << std::endl;
1809  std::cout << "Total nb of polygon lines : " << nbPolygonLines << std::endl;
1810  std::cout << "Total nb of polygon points : " << nbPolygonPoints << std::endl;
1811  std::cout << "Total nb of cylinders : " << nbCylinders << std::endl;
1812  std::cout << "Total nb of circles : " << nbCircles << std::endl;
1813  } else {
1814  std::cout << "> " << nbPoints << " points" << std::endl;
1815  std::cout << "> " << nbLines << " lines" << std::endl;
1816  std::cout << "> " << nbPolygonLines << " polygon lines" << std::endl;
1817  std::cout << "> " << nbPolygonPoints << " polygon points" << std::endl;
1818  std::cout << "> " << nbCylinders << " cylinders" << std::endl;
1819  std::cout << "> " << nbCircles << " circles" << std::endl;
1820  }
1821  }
1822  } catch (...) {
1823  std::cerr << "Cannot read line!" << std::endl;
1824  throw vpException(vpException::ioError, "cannot read line");
1825  }
1826 }
1827 
1828 #ifdef VISP_HAVE_COIN3D
1829 
1836 void
1837 vpMbTracker::extractGroup(SoVRMLGroup *sceneGraphVRML2, vpHomogeneousMatrix &transform, int &idFace)
1838 {
1839  vpHomogeneousMatrix transformCur;
1840  SoVRMLTransform *sceneGraphVRML2Trasnform = dynamic_cast<SoVRMLTransform *>(sceneGraphVRML2);
1841  if(sceneGraphVRML2Trasnform){
1842  float rx, ry, rz, rw;
1843  sceneGraphVRML2Trasnform->rotation.getValue().getValue(rx,ry,rz,rw);
1844  vpRotationMatrix rotMat(vpQuaternionVector(rx,ry,rz,rw));
1845 // std::cout << "Rotation: " << rx << " " << ry << " " << rz << " " << rw << std::endl;
1846 
1847  float tx, ty, tz;
1848  tx = sceneGraphVRML2Trasnform->translation.getValue()[0];
1849  ty = sceneGraphVRML2Trasnform->translation.getValue()[1];
1850  tz = sceneGraphVRML2Trasnform->translation.getValue()[2];
1851  vpTranslationVector transVec(tx,ty,tz);
1852 // std::cout << "Translation: " << tx << " " << ty << " " << tz << std::endl;
1853 
1854  float sx, sy, sz;
1855  sx = sceneGraphVRML2Trasnform->scale.getValue()[0];
1856  sy = sceneGraphVRML2Trasnform->scale.getValue()[1];
1857  sz = sceneGraphVRML2Trasnform->scale.getValue()[2];
1858 // std::cout << "Scale: " << sx << " " << sy << " " << sz << std::endl;
1859 
1860  for(unsigned int i = 0 ; i < 3 ; i++)
1861  rotMat[0][i] *= sx;
1862  for(unsigned int i = 0 ; i < 3 ; i++)
1863  rotMat[1][i] *= sy;
1864  for(unsigned int i = 0 ; i < 3 ; i++)
1865  rotMat[2][i] *= sz;
1866 
1867  transformCur = vpHomogeneousMatrix(transVec,rotMat);
1868  transform = transform * transformCur;
1869  }
1870 
1871  int nbShapes = sceneGraphVRML2->getNumChildren();
1872 // std::cout << sceneGraphVRML2->getTypeId().getName().getString() << std::endl;
1873 // std::cout << "Nb object in VRML : " << nbShapes << std::endl;
1874 
1875  SoNode * child;
1876 
1877  for (int i = 0; i < nbShapes; i++)
1878  {
1879  vpHomogeneousMatrix transform_recursive(transform);
1880  child = sceneGraphVRML2->getChild(i);
1881 
1882  if (child->getTypeId() == SoVRMLGroup::getClassTypeId()){
1883  extractGroup((SoVRMLGroup*)child, transform_recursive, idFace);
1884  }
1885 
1886  if (child->getTypeId() == SoVRMLTransform::getClassTypeId()){
1887  extractGroup((SoVRMLTransform*)child, transform_recursive, idFace);
1888  }
1889 
1890  if (child->getTypeId() == SoVRMLShape::getClassTypeId()){
1891  SoChildList * child2list = child->getChildren();
1892  std::string name = child->getName().getString();
1893 
1894  for (int j = 0; j < child2list->getLength(); j++)
1895  {
1896  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedFaceSet::getClassTypeId())
1897  {
1898  SoVRMLIndexedFaceSet * face_set;
1899  face_set = (SoVRMLIndexedFaceSet*)child2list->get(j);
1900  if(!strncmp(face_set->getName().getString(),"cyl",3)){
1901  extractCylinders(face_set, transform, idFace, name);
1902  }else{
1903  extractFaces(face_set, transform, idFace, name);
1904  }
1905  }
1906  if (((SoNode*)child2list->get(j))->getTypeId() == SoVRMLIndexedLineSet::getClassTypeId())
1907  {
1908  SoVRMLIndexedLineSet * line_set;
1909  line_set = (SoVRMLIndexedLineSet*)child2list->get(j);
1910  extractLines(line_set, idFace, name);
1911  }
1912  }
1913  }
1914  }
1915 }
1916 
1926 void
1927 vpMbTracker::extractFaces(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName)
1928 {
1929  std::vector<vpPoint> corners;
1930  corners.resize(0);
1931 
1932 // SoMFInt32 indexList = _face_set->coordIndex;
1933 // int indexListSize = indexList.getNum();
1934  int indexListSize = face_set->coordIndex.getNum();
1935 
1936  vpColVector pointTransformed(4);
1937  vpPoint pt;
1938  SoVRMLCoordinate *coord;
1939 
1940  for (int i = 0; i < indexListSize; i++)
1941  {
1942  if (face_set->coordIndex[i] == -1)
1943  {
1944  if(corners.size() > 1)
1945  {
1946  addPolygon(corners, idFace++, polygonName);
1947  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
1948  corners.resize(0);
1949  }
1950  }
1951  else
1952  {
1953  coord = (SoVRMLCoordinate *)(face_set->coord.getValue());
1954  int index = face_set->coordIndex[i];
1955  pointTransformed[0]=coord->point[index].getValue()[0];
1956  pointTransformed[1]=coord->point[index].getValue()[1];
1957  pointTransformed[2]=coord->point[index].getValue()[2];
1958  pointTransformed[3] = 1.0;
1959 
1960  pointTransformed = transform * pointTransformed;
1961 
1962  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
1963  corners.push_back(pt);
1964  }
1965  }
1966 }
1967 
1982 void
1983 vpMbTracker::extractCylinders(SoVRMLIndexedFaceSet* face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName)
1984 {
1985  std::vector<vpPoint> corners_c1, corners_c2;//points belonging to the first circle and to the second one.
1986  SoVRMLCoordinate* coords = (SoVRMLCoordinate *)face_set->coord.getValue();
1987 
1988  unsigned int indexListSize = (unsigned int)coords->point.getNum();
1989 
1990  if(indexListSize % 2 == 1){
1991  std::cout << "Not an even number of points when extracting a cylinder." << std::endl;
1992  throw vpException(vpException::dimensionError, "Not an even number of points when extracting a cylinder.");
1993  }
1994  corners_c1.resize(indexListSize / 2);
1995  corners_c2.resize(indexListSize / 2);
1996  vpColVector pointTransformed(4);
1997  vpPoint pt;
1998 
1999 
2000  // extract all points and fill the two sets.
2001 
2002  for(int i=0; i<coords->point.getNum(); ++i){
2003  pointTransformed[0]=coords->point[i].getValue()[0];
2004  pointTransformed[1]=coords->point[i].getValue()[1];
2005  pointTransformed[2]=coords->point[i].getValue()[2];
2006  pointTransformed[3] = 1.0;
2007 
2008  pointTransformed = transform * pointTransformed;
2009 
2010  pt.setWorldCoordinates(pointTransformed[0],pointTransformed[1],pointTransformed[2]);
2011 
2012  if(i < (int)corners_c1.size()){
2013  corners_c1[(unsigned int)i] = pt;
2014  }else{
2015  corners_c2[(unsigned int)i-corners_c1.size()] = pt;
2016  }
2017  }
2018 
2019  vpPoint p1 = getGravityCenter(corners_c1);
2020  vpPoint p2 = getGravityCenter(corners_c2);
2021 
2022  vpColVector dist(3);
2023  dist[0] = p1.get_oX() - corners_c1[0].get_oX();
2024  dist[1] = p1.get_oY() - corners_c1[0].get_oY();
2025  dist[2] = p1.get_oZ() - corners_c1[0].get_oZ();
2026  double radius_c1 = sqrt(dist.sumSquare());
2027  dist[0] = p2.get_oX() - corners_c2[0].get_oX();
2028  dist[1] = p2.get_oY() - corners_c2[0].get_oY();
2029  dist[2] = p2.get_oZ() - corners_c2[0].get_oZ();
2030  double radius_c2 = sqrt(dist.sumSquare());
2031 
2032  if(std::fabs(radius_c1 - radius_c2) > (std::numeric_limits<double>::epsilon() * vpMath::maximum(radius_c1, radius_c2))){
2033  std::cout << "Radius from the two circles of the cylinders are different." << std::endl;
2034  throw vpException(vpException::badValue, "Radius from the two circles of the cylinders are different.");
2035  }
2036 
2037  //addPolygon(p1, p2, idFace, polygonName);
2038  //initCylinder(p1, p2, radius_c1, idFace++);
2039 
2040  int idRevolutionAxis = idFace;
2041  addPolygon(p1, p2, idFace++, polygonName);
2042 
2043  std::vector<std::vector<vpPoint> > listFaces;
2044  createCylinderBBox(p1, p2, radius_c1, listFaces);
2045  addPolygon(listFaces, idFace, polygonName);
2046  idFace+=4;
2047 
2048  initCylinder(p1, p2, radius_c1, idRevolutionAxis, polygonName);
2049 }
2050 
2059 void
2060 vpMbTracker::extractLines(SoVRMLIndexedLineSet* line_set, int &idFace, const std::string &polygonName)
2061 {
2062  std::vector<vpPoint> corners;
2063  corners.resize(0);
2064 
2065  int indexListSize = line_set->coordIndex.getNum();
2066 
2067  SbVec3f point(0,0,0);
2068  vpPoint pt;
2069  SoVRMLCoordinate *coord;
2070 
2071  for (int i = 0; i < indexListSize; i++)
2072  {
2073  if (line_set->coordIndex[i] == -1)
2074  {
2075  if(corners.size() > 1)
2076  {
2077  addPolygon(corners, idFace++, polygonName);
2078  initFaceFromCorners(*(faces.getPolygon().back())); // Init from the last polygon that was added
2079  corners.resize(0);
2080  }
2081  }
2082  else
2083  {
2084  coord = (SoVRMLCoordinate *)(line_set->coord.getValue());
2085  int index = line_set->coordIndex[i];
2086  point[0]=coord->point[index].getValue()[0];
2087  point[1]=coord->point[index].getValue()[1];
2088  point[2]=coord->point[index].getValue()[2];
2089 
2090  pt.setWorldCoordinates(point[0],point[1],point[2]);
2091  corners.push_back(pt);
2092  }
2093  }
2094 }
2095 
2096 #endif // VISP_HAVE_COIN3D
2097 
2107 vpPoint
2108 vpMbTracker::getGravityCenter(const std::vector<vpPoint>& pts)
2109 {
2110  if(pts.empty()){
2111  std::cout << "Cannot extract center of gravity of empty set." << std::endl;
2112  throw vpException(vpException::dimensionError, "Cannot extract center of gravity of empty set.");
2113  }
2114  double oX = 0;
2115  double oY = 0;
2116  double oZ = 0;
2117  vpPoint G;
2118 
2119  for(unsigned int i=0; i<pts.size(); ++i){
2120  oX += pts[i].get_oX();
2121  oY += pts[i].get_oY();
2122  oZ += pts[i].get_oZ();
2123  }
2124 
2125  G.setWorldCoordinates(oX/pts.size(), oY/pts.size(), oZ/pts.size());
2126  return G;
2127 }
2128 
2138 std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > >
2139 vpMbTracker::getPolygonFaces(const bool orderPolygons, const bool useVisibility)
2140 {
2141  //Temporary variable to permit to order polygons by distance
2142  std::vector<vpPolygon> polygonsTmp;
2143  std::vector<std::vector<vpPoint> > roisPtTmp;
2144 
2145  //Pair containing the list of vpPolygon and the list of face corners
2146  std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > > pairOfPolygonFaces;
2147 
2148  for (unsigned int i = 0; i < getNbPolygon(); i++) {
2149  std::vector<vpImagePoint> roi;
2150  std::vector<vpPoint> roiPt;
2151  //A face has at least three points
2152  if (getPolygon(i)->nbpt >= 3) {
2153  if((useVisibility && getPolygon(i)->isvisible) || !useVisibility) {
2154  for (unsigned int j = 0; j < getPolygon(i)->nbpt; j++) {
2155  vpPoint pt(getPolygon(i)->p[j]);
2156  pt.project(cMo);
2157  double u = 0, v = 0;
2159  roi.push_back(vpImagePoint(v, u));
2160  roiPt.push_back(pt);
2161  }
2162 
2163  polygonsTmp.push_back(vpPolygon(roi));
2164  roisPtTmp.push_back(roiPt);
2165  }
2166  }
2167  }
2168 
2169  if(orderPolygons) {
2170  //Order polygons by distance (near to far)
2171  std::vector<PolygonFaceInfo> listOfPolygonFaces;
2172  for(unsigned int i = 0; i < polygonsTmp.size(); i++) {
2173  double x_centroid = 0.0, y_centroid = 0.0, z_centroid = 0.0;
2174  for(unsigned int j = 0; j < roisPtTmp[i].size(); j++) {
2175  x_centroid += roisPtTmp[i][j].get_X();
2176  y_centroid += roisPtTmp[i][j].get_Y();
2177  z_centroid += roisPtTmp[i][j].get_Z();
2178  }
2179 
2180  x_centroid /= roisPtTmp[i].size();
2181  y_centroid /= roisPtTmp[i].size();
2182  z_centroid /= roisPtTmp[i].size();
2183 
2184  double squared_dist = x_centroid*x_centroid + y_centroid*y_centroid + z_centroid*z_centroid;
2185  listOfPolygonFaces.push_back(PolygonFaceInfo(squared_dist, polygonsTmp[i], roisPtTmp[i]));
2186  }
2187 
2188  //Sort the list of polygon faces
2189  std::sort(listOfPolygonFaces.begin(), listOfPolygonFaces.end());
2190 
2191  polygonsTmp.resize(listOfPolygonFaces.size());
2192  roisPtTmp.resize(listOfPolygonFaces.size());
2193 
2194  size_t cpt = 0;
2195  for(std::vector<PolygonFaceInfo>::const_iterator it = listOfPolygonFaces.begin(); it != listOfPolygonFaces.end();
2196  ++it, cpt++) {
2197  polygonsTmp[cpt] = it->polygon;
2198  roisPtTmp[cpt] = it->faceCorners;
2199  }
2200 
2201  pairOfPolygonFaces.first = polygonsTmp;
2202  pairOfPolygonFaces.second = roisPtTmp;
2203  } else {
2204  pairOfPolygonFaces.first = polygonsTmp;
2205  pairOfPolygonFaces.second = roisPtTmp;
2206  }
2207 
2208  return pairOfPolygonFaces;
2209 }
2210 
2218 void
2220 {
2221  useOgre = v;
2222  if(useOgre){
2223 #ifndef VISP_HAVE_OGRE
2224  useOgre = false;
2225  std::cout << "WARNING: ViSP doesn't have Ogre3D, basic visibility test will be used. setOgreVisibilityTest() set to false." << std::endl;
2226 #endif
2227  }
2228 }
2229 
2235 void
2237 {
2238  if( (clippingFlag & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING && dist <= distNearClip)
2239  vpTRACE("Far clipping value cannot be inferior than near clipping value. Far clipping won't be considered.");
2240  else if ( dist < 0 )
2241  vpTRACE("Far clipping value cannot be inferior than 0. Far clipping won't be considered.");
2242  else{
2244  distFarClip = dist;
2245  for (unsigned int i = 0; i < faces.size(); i ++){
2246  faces[i]->setFarClippingDistance(distFarClip);
2247  }
2248 #ifdef VISP_HAVE_OGRE
2250 #endif
2251  }
2252 }
2253 
2263 void
2264 vpMbTracker::setLod(const bool useLod, const std::string &name)
2265 {
2266  for (unsigned int i = 0; i < faces.size(); i++)
2267  {
2268  if(name.empty() || faces[i]->name == name) {
2269  faces[i]->setLod(useLod);
2270  }
2271  }
2272 }
2273 
2282 void
2283 vpMbTracker::setMinLineLengthThresh(const double minLineLengthThresh, const std::string &name)
2284 {
2285  for (unsigned int i = 0; i < faces.size(); i++)
2286  {
2287  if(name.empty() || faces[i]->name == name) {
2288  faces[i]->setMinLineLengthThresh(minLineLengthThresh);
2289  }
2290  }
2291 }
2292 
2301 void
2302 vpMbTracker::setMinPolygonAreaThresh(const double minPolygonAreaThresh, const std::string &name)
2303 {
2304  for (unsigned int i = 0; i < faces.size(); i++)
2305  {
2306  if(name.empty() || faces[i]->name == name) {
2307  faces[i]->setMinPolygonAreaThresh(minPolygonAreaThresh);
2308  }
2309  }
2310 }
2311 
2317 void
2319 {
2320  if( (clippingFlag & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING && dist >= distFarClip)
2321  vpTRACE("Near clipping value cannot be superior than far clipping value. Near clipping won't be considered.");
2322  else if ( dist < 0 )
2323  vpTRACE("Near clipping value cannot be inferior than 0. Near clipping won't be considered.");
2324  else{
2326  distNearClip = dist;
2327  for (unsigned int i = 0; i < faces.size(); i ++){
2328  faces[i]->setNearClippingDistance(distNearClip);
2329  }
2330 #ifdef VISP_HAVE_OGRE
2332 #endif
2333  }
2334 }
2335 
2343 void
2344 vpMbTracker::setClipping(const unsigned int &flags)
2345 {
2346  clippingFlag = flags;
2347  for (unsigned int i = 0; i < faces.size(); i ++)
2349 }
2350 
2365 void
2366 vpMbTracker::computeJTR(const vpMatrix& interaction, const vpColVector& error, vpColVector& JTR)
2367 {
2368  if(interaction.getRows() != error.getRows() || interaction.getCols() != 6 ){
2370  "Incorrect matrices size in computeJTR.");
2371  }
2372 
2373  JTR.resize(6);
2374  const unsigned int N = interaction.getRows();
2375 
2376  for (unsigned int i = 0; i < 6; i += 1){
2377  double ssum = 0;
2378  for (unsigned int j = 0; j < N; j += 1){
2379  ssum += interaction[j][i] * error[j];
2380  }
2381  JTR[i] = ssum;
2382  }
2383 }
2384 
2398 {
2399  vpColVector v(6);
2400  for(unsigned int i = 0 ; i < 6 ; i++)
2401  v[i] = oJo[i][i];
2402  return v;
2403 }
2404 
2415 void
2417 {
2418  if(v.getRows() == 6)
2419  {
2420  isoJoIdentity = true;
2421  for(unsigned int i = 0 ; i < 6 ; i++){
2422  // if(v[i] != 0){
2423  if(std::fabs(v[i]) > std::numeric_limits<double>::epsilon()){
2424  oJo[i][i] = 1.0;
2425  }
2426  else{
2427  oJo[i][i] = 0.0;
2428  isoJoIdentity = false;
2429  }
2430  }
2431  }
2432 }
2433 
2434 
2435 void
2436 vpMbTracker::createCylinderBBox(const vpPoint& p1, const vpPoint &p2, const double &radius, std::vector<std::vector<vpPoint> > &listFaces)
2437 {
2438  listFaces.clear();
2439 
2440 // std::vector<vpPoint> revolutionAxis;
2441 // revolutionAxis.push_back(p1);
2442 // revolutionAxis.push_back(p2);
2443 // listFaces.push_back(revolutionAxis);
2444 
2445  vpColVector axis(3);
2446  axis[0] = p1.get_oX() - p2.get_oX();
2447  axis[1] = p1.get_oY() - p2.get_oY();
2448  axis[2] = p1.get_oZ() - p2.get_oZ();
2449 
2450  vpColVector randomVec(3);
2451  randomVec = 0;
2452 
2453  vpColVector axisOrtho(3);
2454 
2455  randomVec[0] = 1.0;
2456  axisOrtho = vpColVector::crossProd(axis, randomVec);
2457 
2458  if(axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon())
2459  {
2460  randomVec = 0;
2461  randomVec[1] = 1.0;
2462  axisOrtho = vpColVector::crossProd(axis, randomVec);
2463  if(axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon())
2464  {
2465  randomVec = 0;
2466  randomVec[2] = 1.0;
2467  axisOrtho = vpColVector::crossProd(axis, randomVec);
2468  if(axisOrtho.euclideanNorm() < std::numeric_limits<double>::epsilon())
2469  throw vpMatrixException(vpMatrixException::badValue, "Problem in the cylinder definition");
2470  }
2471  }
2472 
2473  axisOrtho.normalize();
2474 
2475  vpColVector axisOrthoBis(3);
2476  axisOrthoBis = vpColVector::crossProd(axis, axisOrtho);
2477  axisOrthoBis.normalize();
2478 
2479  //First circle
2480  vpColVector p1Vec(3);
2481  p1Vec[0] = p1.get_oX();
2482  p1Vec[1] = p1.get_oY();
2483  p1Vec[2] = p1.get_oZ();
2484  vpColVector fc1 = p1Vec + axisOrtho*radius;
2485  vpColVector fc2 = p1Vec + axisOrthoBis*radius;
2486  vpColVector fc3 = p1Vec - axisOrtho*radius;
2487  vpColVector fc4 = p1Vec - axisOrthoBis*radius;
2488 
2489  vpColVector p2Vec(3);
2490  p2Vec[0] = p2.get_oX();
2491  p2Vec[1] = p2.get_oY();
2492  p2Vec[2] = p2.get_oZ();
2493  vpColVector sc1 = p2Vec + axisOrtho*radius;
2494  vpColVector sc2 = p2Vec + axisOrthoBis*radius;
2495  vpColVector sc3 = p2Vec - axisOrtho*radius;
2496  vpColVector sc4 = p2Vec - axisOrthoBis*radius;
2497 
2498  std::vector<vpPoint> pointsFace;
2499  pointsFace.push_back( vpPoint(fc1[0], fc1[1], fc1[2]) );
2500  pointsFace.push_back( vpPoint(sc1[0], sc1[1], sc1[2]) );
2501  pointsFace.push_back( vpPoint(sc2[0], sc2[1], sc2[2]) );
2502  pointsFace.push_back( vpPoint(fc2[0], fc2[1], fc2[2]) );
2503  listFaces.push_back(pointsFace);
2504 
2505  pointsFace.clear();
2506  pointsFace.push_back( vpPoint(fc2[0], fc2[1], fc2[2]) );
2507  pointsFace.push_back( vpPoint(sc2[0], sc2[1], sc2[2]) );
2508  pointsFace.push_back( vpPoint(sc3[0], sc3[1], sc3[2]) );
2509  pointsFace.push_back( vpPoint(fc3[0], fc3[1], fc3[2]) );
2510  listFaces.push_back(pointsFace);
2511 
2512  pointsFace.clear();
2513  pointsFace.push_back( vpPoint(fc3[0], fc3[1], fc3[2]) );
2514  pointsFace.push_back( vpPoint(sc3[0], sc3[1], sc3[2]) );
2515  pointsFace.push_back( vpPoint(sc4[0], sc4[1], sc4[2]) );
2516  pointsFace.push_back( vpPoint(fc4[0], fc4[1], fc4[2]) );
2517  listFaces.push_back(pointsFace);
2518 
2519  pointsFace.clear();
2520  pointsFace.push_back( vpPoint(fc4[0], fc4[1], fc4[2]) );
2521  pointsFace.push_back( vpPoint(sc4[0], sc4[1], sc4[2]) );
2522  pointsFace.push_back( vpPoint(sc1[0], sc1[1], sc1[2]) );
2523  pointsFace.push_back( vpPoint(fc1[0], fc1[1], fc1[2]) );
2524  listFaces.push_back(pointsFace);
2525 }
2526 
vpDisplay * display
Definition: vpImage.h:117
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:92
virtual ~vpMbTracker()
bool parseBoolean(std::string &input)
Definition: vpMbTracker.h:632
std::string & trim(std::string &s)
Definition: vpMbTracker.h:654
Implements a 3D polygon with render functionnalities like clipping.
Definition: vpPolygon3D.h:59
virtual void init(vpImage< unsigned char > &I, int x=-1, int y=-1, const char *title=NULL)=0
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:170
virtual void setNbPoint(const unsigned int nb)
unsigned int nbLines
Number of lines in CAO model.
Definition: vpMbTracker.h:163
virtual void extractCylinders(SoVRMLIndexedFaceSet *face_set, vpHomogeneousMatrix &transform, int &idFace, const std::string &polygonName="")
unsigned int getWidth() const
Definition: vpImage.h:161
std::map< std::string, std::string > parseParameters(std::string &endLine)
static bool isAbsolutePathname(const std::string &pathname)
Definition: vpIoTools.cpp:1311
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:204
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
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
Point coordinates conversion from normalized coordinates in meter to pixel coordinates ...
#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
vpPoint getGravityCenter(const std::vector< vpPoint > &_pts)
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)
Definition: vpDisplay.cpp:888
Define the X11 console to display images.
Definition: vpDisplayX.h:148
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
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 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
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.cpp:458
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:1240
static const vpColor green
Definition: vpColor.h:166
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2233
void setFarClippingDistance(const double &dist)
Definition: vpAROgre.h:194
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:141
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
static bool checkFilename(const char *filename)
Definition: vpIoTools.cpp:485
vpAROgre * getOgreContext()
Defines a generic 2D polygon.
Definition: vpPolygon.h:98
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
#define vpTRACE
Definition: vpDebug.h:414
static double sqr(double x)
Definition: vpMath.h:110
void savePose(const std::string &filename)
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:1265
bool computePose(vpPoseMethodType methode, vpHomogeneousMatrix &cMo, bool(*func)(vpHomogeneousMatrix *)=NULL)
compute the pose for a given method
Definition: vpPose.cpp:382
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
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.
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
void addPoint(const unsigned int n, const vpPoint &P)
Class used for pose computation from N points (pose from point only).
Definition: vpPose.h:74
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
virtual void loadVRMLModel(const std::string &modelFile)
Implementation of a rotation vector as quaternion angle minimal representation.
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.cpp:456
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:1205
static double rad(double deg)
Definition: vpMath.h:104
virtual void setMinLineLengthThresh(const double minLineLengthThresh, const std::string &name="")
virtual vpColVector getEstimatedDoF()
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
void computeJTR(const vpMatrix &J, const vpColVector &R, vpColVector &JTR)
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))
Definition: vpDisplay.cpp:373
unsigned int nbPolygonPoints
Number of polygon points in CAO model.
Definition: vpMbTracker.h:167
unsigned int nbpt
Number of points used to define the polygon.
Definition: vpPolygon3D.h:77
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:361
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
virtual vpMbtPolygon * getPolygon(const unsigned int index)
Definition: vpMbTracker.h:338
error that can be emited by the vpMatrix class and its derivates
virtual unsigned int getNbPolygon() const
Definition: vpMbTracker.h:309
double getA() const
Definition: vpPlane.h:106
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
virtual bool getClick(bool blocking=true)=0
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)
static void read(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:274
virtual void setFarClippingDistance(const double &dist)
virtual std::pair< std::vector< vpPolygon >, std::vector< std::vector< vpPoint > > > getPolygonFaces(const bool orderPolygons=true, const bool useVisibility=true)
void addPoint(const vpPoint &P)
Add a new point in this array.
Definition: vpPose.cpp:151
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
virtual void displayPoint(const vpImagePoint &ip, const vpColor &color)=0
bool isoJoIdentity
Boolean to know if oJo is identity (for fast computation)
Definition: vpMbTracker.h:119
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:340
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:356
void resize(const unsigned int i, const bool flagNullify=true)
Definition: vpColVector.h:217
std::vector< PolygonType * > & getPolygon()
virtual void setIndex(const int i)
Definition: vpMbtPolygon.h:116
void clearPoint()
suppress all the point in the array of point
Definition: vpPose.cpp:129
virtual void setLod(const bool useLod, const std::string &name="")
virtual void setNearClippingDistance(const double &dist)