ViSP  2.8.0
vpMbtPolygon.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbtPolygon.cpp 4319 2013-07-17 10:04:09Z ayol $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Make the complete tracking of an object by using its CAD model
36  *
37  * Authors:
38  * Nicolas Melchior
39  * Romain Tallonneau
40  * Eric Marchand
41  * Aurelien Yol
42  *
43  *****************************************************************************/
44 
45 #include <limits.h>
46 
47 #include <visp/vpConfig.h>
53 #include <visp/vpMbtPolygon.h>
54 
59 {
60  nbpt = 0 ;
61  p = NULL ;
62  isappearing = false;
63  isvisible = false;
65 
66  distNearClip = 0.001;
67  distFarClip = 100.0;
68 
70 }
71 
76 {
77  if (p !=NULL)
78  {
79  delete[] p;
80  p = NULL;
81  }
82 }
83 
91 vpPoint &
92 vpMbtPolygon::getPoint(const unsigned int _index)
93 {
94  if(_index >= nbpt){
95  throw vpException(vpException::dimensionError, "index out of range");
96  }
97  return p[_index];
98 }
99 
105 void
106 vpMbtPolygon::setNbPoint(const unsigned int nb)
107 {
108  nbpt = nb ;
109  if (p != NULL)
110  delete[] p;
111  p = new vpPoint[nb] ;
112 }
113 
120 void
121 vpMbtPolygon::addPoint(const unsigned int n, const vpPoint &P)
122 {
123  //if( p!NULL && n < nbpt )
124  p[n] = P ;
125 }
126 
132 void
134 {
135  for (unsigned int i = 0 ; i < nbpt ; i++)
136  {
137  p[i].changeFrame(cMo) ;
138  p[i].projection() ;
139  }
140 }
141 
155 bool
156 vpMbtPolygon::isVisible(const vpHomogeneousMatrix &cMo, const double alpha, const bool &modulo)
157 {
158  // std::cout << "Computing angle from MBT Face (cMo, alpha)" << std::endl;
159  if(nbpt <= 2){
160  /* a line is allways visible */
161  isvisible = true;
162  isappearing = false;
163  return true ;
164  }
165 
166  changeFrame(cMo);
167 
168  vpColVector e1(3) ;
169  vpColVector e2(3) ;
170  vpColVector facenormal(3) ;
171 
172  e1[0] = p[1].get_X() - p[0].get_X() ;
173  e1[1] = p[1].get_Y() - p[0].get_Y() ;
174  e1[2] = p[1].get_Z() - p[0].get_Z() ;
175 
176  e2[0] = p[2].get_X() - p[1].get_X() ;
177  e2[1] = p[2].get_Y() - p[1].get_Y() ;
178  e2[2] = p[2].get_Z() - p[1].get_Z() ;
179 
180  e1.normalize();
181  e2.normalize();
182 
183  facenormal = vpColVector::crossProd(e1,e2) ;
184  facenormal.normalize();
185 
186  vpColVector e4(3) ;
187  vpPoint pt;
188  for (unsigned int i = 0; i < nbpt; i += 1){
189  pt.set_X(pt.get_X() + p[i].get_X());
190  pt.set_Y(pt.get_Y() + p[i].get_Y());
191  pt.set_Z(pt.get_Z() + p[i].get_Z());
192  }
193  e4[0] = -pt.get_X()/(double)nbpt; e4[1] = -pt.get_Y()/(double)nbpt; e4[2] = -pt.get_Z()/(double)nbpt;
194  e4.normalize();
195 
196  double cos_angle = vpColVector::dotProd (e4, facenormal);
197  double angle = acos(cos_angle);
198 
199 // std::cout << cos_angle << "/" << vpMath::deg(angle) << std::endl;
200 
201  if( angle < alpha ){
202  isvisible = true;
203  isappearing = false;
204  return true;
205  }
206 
207  if(modulo && (M_PI - angle) < alpha){
208  isvisible = true;
209  isappearing = false;
210  return true;
211  }
212 
213  if (angle < alpha+vpMath::rad(1) ){
214  isappearing = true;
215  }
216  else if (modulo && (M_PI - angle) < alpha+vpMath::rad(1) ){
217  isappearing = true;
218  }
219  else {
220  isappearing = false;
221  }
222  isvisible = false ;
223  return false ;
224 }
225 
231 void
233 {
234  roiPointsClip = std::vector<std::pair<vpPoint,unsigned int> >();
235  std::vector<vpColVector> fovNormals;
236 
237  if(cam.isFovComputed() && clippingFlag > 3)
238  fovNormals = cam.getFovNormals();
239 
240  for (unsigned int i = 0; i < nbpt; i ++){
241  vpPoint p1Clipped, p2Clipped;
242  unsigned int p1ClippedInfo, p2ClippedInfo;
243  vpImagePoint ip;
244  if(vpMbtPolygon::getClippedPoints(p[i], p[(i+1)%nbpt], p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo, cam, fovNormals)){
245  p1Clipped.projection();
246  roiPointsClip.push_back(std::make_pair(p1Clipped, p1ClippedInfo));
247 
248  if(p2ClippedInfo != vpMbtPolygon::NO_CLIPPING){
249  p2Clipped.projection();
250  roiPointsClip.push_back(std::make_pair(p2Clipped, p2ClippedInfo));
251  }
252 
253  if(nbpt == 2){ //Case of a line.
254  if(p2ClippedInfo == vpMbtPolygon::NO_CLIPPING){
255  p2Clipped.projection();
256  roiPointsClip.push_back(std::make_pair(p2Clipped, p2ClippedInfo));
257  }
258  break;
259  }
260  }
261  }
262 }
263 
282 bool
283 vpMbtPolygon::getClippedPointsFov(const vpPoint &p1, const vpPoint &p2,
284  vpPoint &p1Clipped, vpPoint &p2Clipped,
285  unsigned int &p1ClippedInfo, unsigned int &p2ClippedInfo,
286  const vpColVector &normal, const unsigned int &flag)
287 {
288  vpRowVector p1Vec(3);
289  p1Vec[0] = p1.get_X(); p1Vec[1] = p1.get_Y(); p1Vec[2] = p1.get_Z();
290  p1Vec = p1Vec.normalize();
291 
292  vpRowVector p2Vec(3);
293  p2Vec[0] = p2.get_X(); p2Vec[1] = p2.get_Y(); p2Vec[2] = p2.get_Z();
294  p2Vec = p2Vec.normalize();
295 
296  if((clippingFlag & flag) == flag){
297  double beta1 = acos( p1Vec * normal );
298  double beta2 = acos( p2Vec * normal );
299 
300  if(beta1 < M_PI / 2.0 && beta2 < M_PI / 2.0)
301  return false;
302  else if (beta1 < M_PI / 2.0 || beta2 < M_PI / 2.0){
303  vpPoint pClipped;
304  double t = -(normal[0] * p1.get_X() + normal[1] * p1.get_Y() + normal[2] * p1.get_Z());
305  t = t / ( normal[0] * (p2.get_X() - p1.get_X()) + normal[1] * (p2.get_Y() - p1.get_Y()) + normal[2] * (p2.get_Z() - p1.get_Z()) );
306 
307  pClipped.set_X((p2.get_X() - p1.get_X())*t + p1.get_X());
308  pClipped.set_Y((p2.get_Y() - p1.get_Y())*t + p1.get_Y());
309  pClipped.set_Z((p2.get_Z() - p1.get_Z())*t + p1.get_Z());
310 
311  if(beta1 < M_PI / 2.0){
312  p1ClippedInfo = p1ClippedInfo | flag;
313  p1Clipped = pClipped;
314  }
315  else{
316  p2ClippedInfo = p2ClippedInfo | flag;
317  p2Clipped = pClipped;
318  }
319  }
320  }
321 
322  return true;
323 }
324 
338 bool
339 vpMbtPolygon::getClippedPoints(const vpPoint &p1, const vpPoint &p2,
340  vpPoint &p1Clipped, vpPoint &p2Clipped,
341  unsigned int &p1ClippedInfo, unsigned int &p2ClippedInfo,
342  const vpCameraParameters &cam, const std::vector<vpColVector> &fovNormals)
343 {
344  p1Clipped = p1;
345  p2Clipped = p2;
346  p1ClippedInfo = vpMbtPolygon::NO_CLIPPING;
347  p2ClippedInfo = vpMbtPolygon::NO_CLIPPING;
348 
350  // Near Clipping
351  if( (clippingFlag & vpMbtPolygon::NEAR_CLIPPING) == vpMbtPolygon::NEAR_CLIPPING ||
352  ((clippingFlag & vpMbtPolygon::LEFT_CLIPPING) == vpMbtPolygon::LEFT_CLIPPING && (clippingFlag & vpMbtPolygon::RIGHT_CLIPPING) == vpMbtPolygon::RIGHT_CLIPPING) ||
353  ((clippingFlag & vpMbtPolygon::UP_CLIPPING) == vpMbtPolygon::UP_CLIPPING && (clippingFlag & vpMbtPolygon::DOWN_CLIPPING) == vpMbtPolygon::DOWN_CLIPPING)){
354  if(p1Clipped.get_Z() < distNearClip && p2Clipped.get_Z() < distNearClip) //Not using getClippedPointsFov for efficiency
355  return false;
356  else if(p1Clipped.get_Z() < distNearClip || p2Clipped.get_Z() < distNearClip){
357  vpPoint pClippedNear;
358  double t = (p2Clipped.get_Z() - p1Clipped.get_Z());
359  t = (distNearClip - p1Clipped.get_Z()) / t;
360 
361  pClippedNear.set_X((p2Clipped.get_X() - p1Clipped.get_X())*t + p1Clipped.get_X());
362  pClippedNear.set_Y((p2Clipped.get_Y() - p1Clipped.get_Y())*t + p1Clipped.get_Y());
363  pClippedNear.set_Z(distNearClip);
364 
365  if(p1Clipped.get_Z() < distNearClip){
366  p1Clipped = pClippedNear;
367  p1ClippedInfo = p1ClippedInfo | vpMbtPolygon::NEAR_CLIPPING;
368  }
369  else{
370  p2Clipped = pClippedNear;
371  p2ClippedInfo = p2ClippedInfo | vpMbtPolygon::NEAR_CLIPPING;
372  }
373  }
374  }
375 
376  // Left Clipping
377  if((clippingFlag & vpMbtPolygon::LEFT_CLIPPING) == vpMbtPolygon::LEFT_CLIPPING){
378  if(!cam.isFovComputed())
379  vpTRACE("Field of view not computed, left clipping skipped.");
380  else if(!getClippedPointsFov(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
381  fovNormals[0], vpMbtPolygon::LEFT_CLIPPING))
382  return false;
383  }
384 
385  // Right Clipping
386  if((clippingFlag & vpMbtPolygon::RIGHT_CLIPPING) == vpMbtPolygon::RIGHT_CLIPPING ){
387  if(!cam.isFovComputed())
388  vpTRACE("Field of view not computed, right clipping skipped.");
389  else if(!getClippedPointsFov(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
390  fovNormals[1], vpMbtPolygon::RIGHT_CLIPPING))
391  return false;
392  }
393 
394  // Up Clipping
395  if((clippingFlag & vpMbtPolygon::UP_CLIPPING) == vpMbtPolygon::UP_CLIPPING){
396  if(!cam.isFovComputed())
397  vpTRACE("Field of view not computed, up clipping skipped.");
398  else if(!getClippedPointsFov(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
399  fovNormals[2], vpMbtPolygon::UP_CLIPPING))
400  return false;
401  }
402 
403  // Down Clipping
404  if((clippingFlag & vpMbtPolygon::DOWN_CLIPPING) == vpMbtPolygon::DOWN_CLIPPING ){
405  if(!cam.isFovComputed())
406  vpTRACE("Field of view not computed, down clipping skipped.");
407  else if(!getClippedPointsFov(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
408  fovNormals[3], vpMbtPolygon::DOWN_CLIPPING))
409  return false;
410  }
411 
412  // Far Clipping
414  if(p1Clipped.get_Z() > distFarClip && p2Clipped.get_Z() > distFarClip) //Not using getClippedPointsFov for efficiency
415  return false;
416  else if(p1Clipped.get_Z() > distFarClip || p2Clipped.get_Z() > distFarClip){
417  vpPoint pClippedFar;
418  double t = (p2Clipped.get_Z() - p1Clipped.get_Z());
419  t = (distFarClip - p1Clipped.get_Z()) / t;
420 
421  pClippedFar.set_X((p2Clipped.get_X() - p1Clipped.get_X())*t + p1Clipped.get_X());
422  pClippedFar.set_Y((p2Clipped.get_Y() - p1Clipped.get_Y())*t + p1Clipped.get_Y());
423  pClippedFar.set_Z(distFarClip);
424 
425  if(p1Clipped.get_Z() > distFarClip){
426  p1Clipped = pClippedFar;
427  p1ClippedInfo = p1ClippedInfo | vpMbtPolygon::FAR_CLIPPING;
428  }
429  else{
430  p2Clipped = pClippedFar;
431  p2ClippedInfo = p2ClippedInfo | vpMbtPolygon::FAR_CLIPPING;
432  }
433  }
434  }
435  }
436 
437  return true;
438 }
439 
449 std::vector<vpImagePoint>
451 {
452  std::vector<vpImagePoint> roi;
453  for (unsigned int i = 0; i < nbpt; i ++){
454  vpImagePoint ip;
455  vpMeterPixelConversion::convertPoint(cam, p[i].get_x(), p[i].get_y(), ip);
456  roi.push_back(ip);
457  }
458 
459  return roi;
460 }
461 
470 std::vector<vpImagePoint>
472 {
473  changeFrame(cMo);
474  return getRoi(cam);
475 }
476 
485 void
486 vpMbtPolygon::getRoiClipped(const vpCameraParameters &cam, std::vector<vpImagePoint> &roi)
487 {
488  for(unsigned int i = 0 ; i < roiPointsClip.size() ; i++){
489  vpImagePoint ip;
490  vpMeterPixelConversion::convertPoint(cam,roiPointsClip[i].first.get_x(),roiPointsClip[i].first.get_y(),ip);
491  roi.push_back(ip);
492  }
493 }
494 
502 void
503 vpMbtPolygon::getRoiClipped(const vpCameraParameters &cam, std::vector<vpImagePoint> &roi, const vpHomogeneousMatrix &cMo)
504 {
505  changeFrame(cMo);
506  computeRoiClipped(cam);
507  getRoiClipped(cam, roi);
508 }
509 
518 void
519 vpMbtPolygon::getRoiClipped(const vpCameraParameters &cam, std::vector<std::pair<vpImagePoint,unsigned int> > &roi)
520 {
521  for(unsigned int i = 0 ; i < roiPointsClip.size() ; i++){
522  vpImagePoint ip;
523  vpMeterPixelConversion::convertPoint(cam,roiPointsClip[i].first.get_x(),roiPointsClip[i].first.get_y(),ip);
524  roi.push_back(std::make_pair(ip, roiPointsClip[i].second));
525  }
526 }
527 
535 void
536 vpMbtPolygon::getRoiClipped(const vpCameraParameters &cam, std::vector<std::pair<vpImagePoint,unsigned int> > &roi, const vpHomogeneousMatrix &cMo)
537 {
538  changeFrame(cMo);
539  computeRoiClipped(cam);
540  getRoiClipped(cam, roi);
541 }
542 
543 
544 
551 unsigned int
553 {
554  unsigned int nbPolyIn = 0;
555  for (unsigned int i = 0; i < nbpt; i ++){
556  if(p[i].get_Z() > 0){
557  vpImagePoint ip;
558  vpMeterPixelConversion::convertPoint(cam, p[i].get_x(), p[i].get_y(), ip);
559  if((ip.get_i() >= 0) && (ip.get_j() >= 0) && (ip.get_i() < I.getHeight()) && (ip.get_j() < I.getWidth()))
560  nbPolyIn++;
561  }
562  }
563 
564  nbCornersInsidePrev = nbPolyIn;
565 
566  return nbPolyIn;
567 }
568 
569 //###################################
570 // Static functions
571 //###################################
572 
573 void
574 vpMbtPolygon::getMinMaxRoi(const std::vector<vpImagePoint> &iroi, int & i_min, int &i_max, int &j_min, int &j_max)
575 {
576  // i_min_d = std::numeric_limits<double>::max(); // create an error under Windows. To fix it we have to add #undef max
577  double i_min_d = (double) INT_MAX;
578  double i_max_d = 0;
579  double j_min_d = (double) INT_MAX;
580  double j_max_d = 0;
581 
582  for (unsigned int i = 0; i < iroi.size(); i += 1){
583  if(i_min_d > iroi[i].get_i())
584  i_min_d = iroi[i].get_i();
585 
586  if(iroi[i].get_i() < 0)
587  i_min_d = 1;
588 
589  if((iroi[i].get_i() > 0) && (i_max_d < iroi[i].get_i()))
590  i_max_d = iroi[i].get_i();
591 
592  if(j_min_d > iroi[i].get_j())
593  j_min_d = iroi[i].get_j();
594 
595  if(iroi[i].get_j() < 0)
596  j_min_d = 1;//border
597 
598  if((iroi[i].get_j() > 0) && j_max_d < iroi[i].get_j())
599  j_max_d = iroi[i].get_j();
600  }
601  i_min = static_cast<int> (i_min_d);
602  i_max = static_cast<int> (i_max_d);
603  j_min = static_cast<int> (j_min_d);
604  j_max = static_cast<int> (j_max_d);
605 }
606 
614 bool
615 vpMbtPolygon::roiInsideImage(const vpImage<unsigned char>& I, const std::vector<vpImagePoint>& corners)
616 {
617  double nbPolyIn = 0;
618  for(unsigned int i=0; i<corners.size(); ++i){
619  if((corners[i].get_i() >= 0) && (corners[i].get_j() >= 0) &&
620  (corners[i].get_i() < I.getHeight()) && (corners[i].get_j() < I.getWidth())){
621  nbPolyIn++;
622  }
623  }
624 
625  if(nbPolyIn < 3 && nbPolyIn < 0.7 * corners.size())
626  return false;
627 
628  return true;
629 }
630 
631 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
632 
642 bool
643 vpMbtPolygon::isVisible(const vpHomogeneousMatrix &cMo, const bool &depthTest)
644 {
645  changeFrame(cMo) ;
646 
647  if(depthTest)
648  for (unsigned int i = 0 ; i < nbpt ; i++){
649  if(p[i].get_Z() < 0){
650  isappearing = false;
651  isvisible = false ;
652  return false ;
653  }
654  }
655 
656  return isVisible(cMo, vpMath::rad(89));
657 }
658 #endif
659 
660 
void projection(const vpColVector &_cP, vpColVector &_p)
Projection onto the image plane of a point. Input: the 3D coordinates in the camera frame _cP...
Definition: vpPoint.cpp:132
void changeFrame(const vpHomogeneousMatrix &cMo)
bool isVisible() const
Definition: vpMbtPolygon.h:189
unsigned int getNbCornerInsideImage(const vpImage< unsigned char > &I, const vpCameraParameters &cam)
double get_i() const
Definition: vpImagePoint.h:181
unsigned int getWidth() const
Definition: vpImage.h:159
The class provides a data structure for the homogeneous matrices as well as a set of operations on th...
#define vpTRACE
Definition: vpDebug.h:401
unsigned int clippingFlag
Clipping flag.
Definition: vpMbtPolygon.h:99
virtual ~vpMbtPolygon()
Definition of the row vector class.
Definition: vpRowVector.h:73
bool isFovComputed() const
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 ...
vpPoint & getPoint(const unsigned int _index)
error that can be emited by ViSP classes.
Definition: vpException.h:75
void getRoiClipped(const vpCameraParameters &cam, std::vector< vpImagePoint > &roi)
unsigned int nbpt
Number of points used to define the polygon.
Definition: vpMbtPolygon.h:87
void set_X(const double X)
Set the point X coordinate in the camera frame.
Definition: vpPoint.h:176
unsigned int nbCornersInsidePrev
Number of corners inside the image during the last call to getNbCornerInsideImage.
Definition: vpMbtPolygon.h:89
double get_j() const
Definition: vpImagePoint.h:192
Class that defines what is a point.
Definition: vpPoint.h:65
std::vector< std::pair< vpPoint, unsigned int > > roiPointsClip
Region of interest clipped.
Definition: vpMbtPolygon.h:97
double distFarClip
Distance for near clipping.
Definition: vpMbtPolygon.h:103
void addPoint(const unsigned int n, const vpPoint &P)
void set_Z(const double Z)
Set the point Z coordinate in the camera frame.
Definition: vpPoint.h:180
Generic class defining intrinsic camera parameters.
void set_Y(const double Y)
Set the point Y coordinate in the camera frame.
Definition: vpPoint.h:178
void computeRoiClipped(const vpCameraParameters &cam=vpCameraParameters())
double get_Y() const
Get the point Y coordinate in the camera frame.
Definition: vpPoint.h:120
static double rad(double deg)
Definition: vpMath.h:100
double get_Z() const
Get the point Z coordinate in the camera frame.
Definition: vpPoint.h:122
std::vector< vpImagePoint > getRoi(const vpCameraParameters &cam)
bool isappearing
flag to specify whether the face is appearing or not
Definition: vpMbtPolygon.h:93
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
std::vector< vpColVector > getFovNormals() const
static double dotProd(const vpColVector &a, const vpColVector &b)
Dot Product.
static void getMinMaxRoi(const std::vector< vpImagePoint > &roi, int &i_min, int &i_max, int &j_min, int &j_max)
unsigned int getHeight() const
Definition: vpImage.h:150
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
static bool roiInsideImage(const vpImage< unsigned char > &I, const std::vector< vpImagePoint > &corners)
static vpColVector crossProd(const vpColVector &a, const vpColVector &b)
normalise the vector
void changeFrame(const vpHomogeneousMatrix &cMo, vpColVector &_cP)
Definition: vpPoint.cpp:150
virtual void setNbPoint(const unsigned int nb)
bool isvisible
flag to specify whether the face is visible or not
Definition: vpMbtPolygon.h:91
vpColVector & normalize()
normalise the vector
double get_X() const
Get the point X coordinate in the camera frame.
Definition: vpPoint.h:118
double distNearClip
Distance for near clipping.
Definition: vpMbtPolygon.h:101
vpPoint * p
corners in the object frame
Definition: vpMbtPolygon.h:95