Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpPolygon3D.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Make the complete tracking of an object by using its CAD model
32  *
33  * Authors:
34  * Aurelien Yol
35  *
36  *****************************************************************************/
37 
38 #include <limits.h>
39 
40 #include <visp3/core/vpConfig.h>
46 #include <visp3/core/vpPolygon3D.h>
47 #include <visp3/core/vpPolygon.h>
48 
53  : nbpt(0), nbCornersInsidePrev(0),
54  p(NULL), polyClipped(), clippingFlag(vpPolygon3D::NO_CLIPPING),
55  distNearClip(0.001), distFarClip(100.)
56 {
57 }
58 
60  : nbpt(mbtp.nbpt), nbCornersInsidePrev(mbtp.nbCornersInsidePrev),
61  p(NULL), polyClipped(mbtp.polyClipped), clippingFlag(mbtp.clippingFlag),
62  distNearClip(mbtp.distNearClip), distFarClip(mbtp.distFarClip)
63 {
64  if (p) delete [] p;
65  p = new vpPoint [nbpt];
66  for(unsigned int i = 0; i < nbpt; i++)
67  p[i] = mbtp.p[i];
68 }
69 
71 {
72  nbpt = mbtp.nbpt;
74  polyClipped = mbtp.polyClipped;
77  distFarClip = mbtp.distFarClip;
78 
79  if (p) delete [] p;
80  p = new vpPoint [nbpt];
81  for(unsigned int i = 0; i < nbpt; i++)
82  p[i] = mbtp.p[i];
83 
84  return (*this);
85 }
86 
91 {
92  if (p !=NULL)
93  {
94  delete[] p;
95  p = NULL;
96  }
97 }
98 
106 vpPoint &
107 vpPolygon3D::getPoint(const unsigned int _index)
108 {
109  if(_index >= nbpt){
110  throw vpException(vpException::dimensionError, "index out of range");
111  }
112  return p[_index];
113 }
114 
120 void
121 vpPolygon3D::setNbPoint(const unsigned int nb)
122 {
123  nbpt = nb ;
124  if (p != NULL)
125  delete[] p;
126  p = new vpPoint[nb] ;
127 }
128 
135 void
136 vpPolygon3D::addPoint(const unsigned int n, const vpPoint &P)
137 {
138  //if( p!NULL && n < nbpt )
139  p[n] = P ;
140 }
141 
147 void
149 {
150  for (unsigned int i = 0 ; i < nbpt ; i++)
151  {
152  p[i].changeFrame(cMo) ;
153  p[i].projection() ;
154  }
155 }
156 
164 void
166 {
167  polyClipped.clear();
168  std::vector<vpColVector> fovNormals;
169  std::vector<std::pair<vpPoint,unsigned int> > polyClippedTemp;
170  std::vector<std::pair<vpPoint,unsigned int> > polyClippedTemp2;
171 
172  if(cam.isFovComputed() && clippingFlag > 3)
173  fovNormals = cam.getFovNormals();
174 
175  for(unsigned int i = 0 ; i < nbpt ; i++){
176  p[i%nbpt].projection();
177  polyClippedTemp.push_back(std::make_pair(p[i%nbpt],vpPolygon3D::NO_CLIPPING));
178  }
179 
181  for(unsigned int i = 1 ; i < 64 ; i=i*2)
182  {
183  if(((clippingFlag & i) == i) || ((clippingFlag > vpPolygon3D::FAR_CLIPPING) && (i==1)))
184  {
185  if(i > vpPolygon3D::FAR_CLIPPING && !cam.isFovComputed()) // To make sure we do not compute FOV clipping if camera normals are not computed
186  continue;
187 
188  for(unsigned int j = 0 ; j < polyClippedTemp.size() ; j++)
189  {
190  vpPoint p1Clipped = polyClippedTemp[j].first;
191  vpPoint p2Clipped = polyClippedTemp[(j+1)%polyClippedTemp.size()].first;
192 
193  unsigned int p2ClippedInfoBefore = polyClippedTemp[(j+1)%polyClippedTemp.size()].second;
194  unsigned int p1ClippedInfo = polyClippedTemp[j].second;
195  unsigned int p2ClippedInfo = polyClippedTemp[(j+1)%polyClippedTemp.size()].second;
196 
197  bool problem = true;
198 
199  switch(i){
200  case 1:
201  problem = !(vpPolygon3D::getClippedPointsDistance(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
202  i, distNearClip));
203  break;
204  case 2:
205  problem = !(vpPolygon3D::getClippedPointsDistance(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
206  i, distFarClip));
207  break;
208  case 4:
209  problem = !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
210  fovNormals[0], vpPolygon3D::LEFT_CLIPPING));
211  break;
212  case 8:
213  problem = !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
214  fovNormals[1], vpPolygon3D::RIGHT_CLIPPING));
215  break;
216  case 16:
217  problem = !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
218  fovNormals[2], vpPolygon3D::UP_CLIPPING));
219  break;
220  case 32:
221  problem = !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo, p2ClippedInfo,
222  fovNormals[3], vpPolygon3D::DOWN_CLIPPING));
223  break;
224  }
225 
226  if(!problem)
227  {
228  p1Clipped.projection();
229  polyClippedTemp2.push_back(std::make_pair(p1Clipped, p1ClippedInfo));
230 
231  if(p2ClippedInfo != p2ClippedInfoBefore)
232  {
233  p2Clipped.projection();
234  polyClippedTemp2.push_back(std::make_pair(p2Clipped, p2ClippedInfo));
235  }
236 
237  if(nbpt == 2){
238  if(p2ClippedInfo == p2ClippedInfoBefore)
239  {
240  p2Clipped.projection();
241  polyClippedTemp2.push_back(std::make_pair(p2Clipped, p2ClippedInfo));
242  }
243  break;
244  }
245  }
246  }
247 
248  polyClippedTemp = polyClippedTemp2;
249  polyClippedTemp2.clear();
250  }
251  }
252  }
253 
254  polyClipped = polyClippedTemp;
255 }
256 
275 bool
276 vpPolygon3D::getClippedPointsFovGeneric(const vpPoint &p1, const vpPoint &p2,
277  vpPoint &p1Clipped, vpPoint &p2Clipped,
278  unsigned int &p1ClippedInfo, unsigned int &p2ClippedInfo,
279  const vpColVector &normal, const unsigned int &flag)
280 {
281  vpRowVector p1Vec(3);
282  p1Vec[0] = p1.get_X(); p1Vec[1] = p1.get_Y(); p1Vec[2] = p1.get_Z();
283  p1Vec.normalize();
284 
285  vpRowVector p2Vec(3);
286  p2Vec[0] = p2.get_X(); p2Vec[1] = p2.get_Y(); p2Vec[2] = p2.get_Z();
287  p2Vec.normalize();
288 
289  if((clippingFlag & flag) == flag){
290  double beta1 = acos( p1Vec * normal );
291  double beta2 = acos( p2Vec * normal );
292 
293 // std::cout << beta1 << " && " << beta2 << std::endl;
294 
295  // if(!(beta1 < M_PI / 2.0 && beta2 < M_PI / 2.0))
296  if(beta1 < M_PI / 2.0 && beta2 < M_PI / 2.0)
297  return false;
298  else if (beta1 < M_PI / 2.0 || beta2 < M_PI / 2.0){
299  vpPoint pClipped;
300  double t = -(normal[0] * p1.get_X() + normal[1] * p1.get_Y() + normal[2] * p1.get_Z());
301  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()) );
302 
303  pClipped.set_X((p2.get_X() - p1.get_X())*t + p1.get_X());
304  pClipped.set_Y((p2.get_Y() - p1.get_Y())*t + p1.get_Y());
305  pClipped.set_Z((p2.get_Z() - p1.get_Z())*t + p1.get_Z());
306 
307  if(beta1 < M_PI / 2.0){
308  p1ClippedInfo = p1ClippedInfo | flag;
309  p1Clipped = pClipped;
310  }
311  else{
312  p2ClippedInfo = p2ClippedInfo | flag;
313  p2Clipped = pClipped;
314  }
315  }
316  }
317 
318  return true;
319 }
320 
321 bool
322 vpPolygon3D::getClippedPointsDistance(const vpPoint &p1, const vpPoint &p2,
323  vpPoint &p1Clipped, vpPoint &p2Clipped,
324  unsigned int &p1ClippedInfo, unsigned int &p2ClippedInfo,
325  const unsigned int &flag, const double &distance)
326 {
327  // Since p1 and p1Clipped can be the same object as well as p2 and p2Clipped
328  // to avoid a valgrind "Source and destination overlap in memcpy" error,
329  // we introduce a two temporary points.
330  vpPoint p1Clipped_, p2Clipped_;
331  p1Clipped_ = p1;
332  p2Clipped_ = p2;
333 
334  p1Clipped = p1Clipped_;
335  p2Clipped = p2Clipped_;
336 
337 
338  bool test1 = (p1Clipped.get_Z() < distance && p2Clipped.get_Z() < distance);
339  if(flag == vpPolygon3D::FAR_CLIPPING)
340  test1 = (p1Clipped.get_Z() > distance && p2Clipped.get_Z() > distance);
341 
342  bool test2 = (p1Clipped.get_Z() < distance || p2Clipped.get_Z() < distance);
343  if(flag == vpPolygon3D::FAR_CLIPPING)
344  test2 = (p1Clipped.get_Z() > distance || p2Clipped.get_Z() > distance);
345 
346  bool test3 = (p1Clipped.get_Z() < distance);
347  if(flag == vpPolygon3D::FAR_CLIPPING)
348  test3 = (p1Clipped.get_Z() > distance);
349 
350  if(test1)
351  return false;
352 
353  else if(test2){
354  vpPoint pClippedNear;
355  double t;
356  t = (p2Clipped.get_Z() - p1Clipped.get_Z());
357  t = (distance - p1Clipped.get_Z()) / t;
358 
359  pClippedNear.set_X((p2Clipped.get_X() - p1Clipped.get_X())*t + p1Clipped.get_X());
360  pClippedNear.set_Y((p2Clipped.get_Y() - p1Clipped.get_Y())*t + p1Clipped.get_Y());
361  pClippedNear.set_Z(distance);
362 
363  if(test3){
364  p1Clipped = pClippedNear;
365  if(flag == vpPolygon3D::FAR_CLIPPING)
366  p1ClippedInfo = p1ClippedInfo | vpPolygon3D::FAR_CLIPPING;
367  else
368  p1ClippedInfo = p1ClippedInfo | vpPolygon3D::NEAR_CLIPPING;
369  }
370  else{
371  p2Clipped = pClippedNear;
372  if(flag == vpPolygon3D::FAR_CLIPPING)
373  p2ClippedInfo = p2ClippedInfo | vpPolygon3D::FAR_CLIPPING;
374  else
375  p2ClippedInfo = p2ClippedInfo | vpPolygon3D::NEAR_CLIPPING;
376  }
377  }
378 
379  return true;
380 }
381 
391 std::vector<vpImagePoint>
393 {
394  std::vector<vpImagePoint> roi;
395  for (unsigned int i = 0; i < nbpt; i ++){
396  vpImagePoint ip;
397  vpMeterPixelConversion::convertPoint(cam, p[i].get_x(), p[i].get_y(), ip);
398  roi.push_back(ip);
399  }
400 
401  return roi;
402 }
403 
412 std::vector<vpImagePoint>
414 {
415  changeFrame(cMo);
416  return getRoi(cam);
417 }
418 
419 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
420 
427 void
428 vpPolygon3D::getRoiClipped(std::vector<vpPoint> &points)
429 {
430  for(unsigned int i = 0 ; i < polyClipped.size() ; i++){
431  points.push_back(polyClipped[i].first);
432  }
433 }
434 #endif
435 
443 void
444 vpPolygon3D::getPolygonClipped(std::vector<std::pair<vpPoint,unsigned int> > &poly)
445 {
446  poly = polyClipped;
447 }
448 
456 void
457 vpPolygon3D::getPolygonClipped(std::vector<vpPoint> &poly)
458 {
459  for(unsigned int i = 0 ; i < polyClipped.size() ; i++){
460  poly.push_back(polyClipped[i].first);
461  }
462 }
463 
472 void
473 vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<vpImagePoint> &roi)
474 {
475  for(unsigned int i = 0 ; i < polyClipped.size() ; i++){
476  vpImagePoint ip;
477  vpMeterPixelConversion::convertPoint(cam,polyClipped[i].first.get_x(),polyClipped[i].first.get_y(),ip);
478 // std::cout << "## " << ip.get_j() << " - " << ip.get_i() << std::endl;
479  roi.push_back(ip);
480  }
481 }
482 
490 void
491 vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<vpImagePoint> &roi, const vpHomogeneousMatrix &cMo)
492 {
493  changeFrame(cMo);
495  getRoiClipped(cam, roi);
496 }
497 
506 void
507 vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<std::pair<vpImagePoint,unsigned int> > &roi)
508 {
509  for(unsigned int i = 0 ; i < polyClipped.size() ; i++){
510  vpImagePoint ip;
511  polyClipped[i].first.projection();
512  vpMeterPixelConversion::convertPoint(cam,polyClipped[i].first.get_x(),polyClipped[i].first.get_y(),ip);
513  roi.push_back(std::make_pair(ip, polyClipped[i].second));
514  }
515 }
516 
524 void
525 vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<std::pair<vpImagePoint,unsigned int> > &roi, const vpHomogeneousMatrix &cMo)
526 {
527  changeFrame(cMo);
529  getRoiClipped(cam, roi);
530 }
531 
532 
533 
540 unsigned int
542 {
543  unsigned int nbPolyIn = 0;
544  for (unsigned int i = 0; i < nbpt; i ++){
545  if(p[i].get_Z() > 0){
546  vpImagePoint ip;
547  vpMeterPixelConversion::convertPoint(cam, p[i].get_x(), p[i].get_y(), ip);
548  if((ip.get_i() >= 0) && (ip.get_j() >= 0) && (ip.get_i() < I.getHeight()) && (ip.get_j() < I.getWidth()))
549  nbPolyIn++;
550  }
551  }
552 
553  nbCornersInsidePrev = nbPolyIn;
554 
555  return nbPolyIn;
556 }
557 
558 //###################################
559 // Static functions
560 //###################################
561 
575 void
576 vpPolygon3D::getClippedPolygon(const std::vector<vpPoint> &ptIn, std::vector<vpPoint> &ptOut, const vpHomogeneousMatrix &cMo, const unsigned int &clippingFlags,
577  const vpCameraParameters &cam, const double &znear, const double &zfar)
578 {
579  ptOut.clear();
580  vpPolygon3D poly;
581  poly.setNbPoint((unsigned int)ptIn.size());
582  poly.setClipping(clippingFlags);
583 
584  if((clippingFlags & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
585  poly.setNearClippingDistance(znear);
586 
587  if((clippingFlags & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
588  poly.setFarClippingDistance(zfar);
589 
590  for(unsigned int i = 0; i < ptIn.size(); i++)
591  poly.addPoint(i,ptIn[i]);
592 
593  poly.changeFrame(cMo);
594  poly.computePolygonClipped(cam);
595  poly.getPolygonClipped(ptOut);
596 }
597 
598 void
599 vpPolygon3D::getMinMaxRoi(const std::vector<vpImagePoint> &iroi, int & i_min, int &i_max, int &j_min, int &j_max)
600 {
601  // i_min_d = std::numeric_limits<double>::max(); // create an error under Windows. To fix it we have to add #undef max
602  double i_min_d = (double) INT_MAX;
603  double i_max_d = 0;
604  double j_min_d = (double) INT_MAX;
605  double j_max_d = 0;
606 
607  for (unsigned int i = 0; i < iroi.size(); i += 1){
608  if(i_min_d > iroi[i].get_i())
609  i_min_d = iroi[i].get_i();
610 
611  if(iroi[i].get_i() < 0)
612  i_min_d = 1;
613 
614  if((iroi[i].get_i() > 0) && (i_max_d < iroi[i].get_i()))
615  i_max_d = iroi[i].get_i();
616 
617  if(j_min_d > iroi[i].get_j())
618  j_min_d = iroi[i].get_j();
619 
620  if(iroi[i].get_j() < 0)
621  j_min_d = 1;//border
622 
623  if((iroi[i].get_j() > 0) && j_max_d < iroi[i].get_j())
624  j_max_d = iroi[i].get_j();
625  }
626  i_min = static_cast<int> (i_min_d);
627  i_max = static_cast<int> (i_max_d);
628  j_min = static_cast<int> (j_min_d);
629  j_max = static_cast<int> (j_max_d);
630 }
631 
639 bool
640 vpPolygon3D::roiInsideImage(const vpImage<unsigned char>& I, const std::vector<vpImagePoint>& corners)
641 {
642  double nbPolyIn = 0;
643  for(unsigned int i=0; i<corners.size(); ++i){
644  if((corners[i].get_i() >= 0) && (corners[i].get_j() >= 0) &&
645  (corners[i].get_i() < I.getHeight()) && (corners[i].get_j() < I.getWidth())){
646  nbPolyIn++;
647  }
648  }
649 
650  if(nbPolyIn < 3 && nbPolyIn < 0.7 * corners.size())
651  return false;
652 
653  return true;
654 }
void getRoiClipped(const vpCameraParameters &cam, std::vector< vpImagePoint > &roi)
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:229
Implements a 3D polygon with render functionnalities like clipping.
Definition: vpPolygon3D.h:59
virtual void setNbPoint(const unsigned int nb)
unsigned int nbCornersInsidePrev
Number of corners inside the image during the last call to getNbCornerInsideImage.
Definition: vpPolygon3D.h:79
static bool roiInsideImage(const vpImage< unsigned char > &I, const std::vector< vpImagePoint > &corners)
double get_i() const
Definition: vpImagePoint.h:199
unsigned int getWidth() const
Definition: vpImage.h:226
Implementation of an homogeneous matrix and operations on such kind of matrices.
Implementation of row vector and the associated operations.
Definition: vpRowVector.h:70
bool isFovComputed() const
void setFarClippingDistance(const double &dist)
Definition: vpPolygon3D.h:196
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 ...
error that can be emited by ViSP classes.
Definition: vpException.h:73
vpPoint * p
corners in the object frame
Definition: vpPolygon3D.h:81
void set_X(const double X)
Set the point X coordinate in the camera frame.
Definition: vpPoint.cpp:478
double get_j() const
Definition: vpImagePoint.h:210
static void getMinMaxRoi(const std::vector< vpImagePoint > &roi, int &i_min, int &i_max, int &j_min, int &j_max)
Class that defines what is a point.
Definition: vpPoint.h:59
void changeFrame(const vpHomogeneousMatrix &cMo)
void set_Z(const double Z)
Set the point Z coordinate in the camera frame.
Definition: vpPoint.cpp:482
vpPoint & getPoint(const unsigned int _index)
void computePolygonClipped(const vpCameraParameters &cam=vpCameraParameters())
double distFarClip
Distance for near clipping.
Definition: vpPolygon3D.h:89
double distNearClip
Distance for near clipping.
Definition: vpPolygon3D.h:87
void addPoint(const unsigned int n, const vpPoint &P)
void getPolygonClipped(std::vector< std::pair< vpPoint, unsigned int > > &poly)
Generic class defining intrinsic camera parameters.
unsigned int getNbCornerInsideImage(const vpImage< unsigned char > &I, const vpCameraParameters &cam)
void set_Y(const double Y)
Set the point Y coordinate in the camera frame.
Definition: vpPoint.cpp:480
vpPolygon3D & operator=(const vpPolygon3D &mbtp)
Definition: vpPolygon3D.cpp:70
std::vector< std::pair< vpPoint, unsigned int > > polyClipped
Region of interest clipped.
Definition: vpPolygon3D.h:83
double get_Y() const
Get the point Y coordinate in the camera frame.
Definition: vpPoint.cpp:440
void setClipping(const unsigned int &flags)
Definition: vpPolygon3D.h:189
double get_Z() const
Get the point Z coordinate in the camera frame.
Definition: vpPoint.cpp:442
unsigned int nbpt
Number of points used to define the polygon.
Definition: vpPolygon3D.h:77
std::vector< vpImagePoint > getRoi(const vpCameraParameters &cam)
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
std::vector< vpColVector > getFovNormals() const
void setNearClippingDistance(const double &dist)
Definition: vpPolygon3D.h:205
unsigned int getHeight() const
Definition: vpImage.h:175
static void getClippedPolygon(const std::vector< vpPoint > &ptIn, std::vector< vpPoint > &ptOut, const vpHomogeneousMatrix &cMo, const unsigned int &clippingFlags, const vpCameraParameters &cam=vpCameraParameters(), const double &znear=0.001, const double &zfar=100)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
unsigned int clippingFlag
Clipping flag.
Definition: vpPolygon3D.h:85
virtual ~vpPolygon3D()
Definition: vpPolygon3D.cpp:90
void changeFrame(const vpHomogeneousMatrix &cMo, vpColVector &_cP)
Definition: vpPoint.cpp:247
double get_X() const
Get the point X coordinate in the camera frame.
Definition: vpPoint.cpp:438