1 /****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5 *
6 * This software is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 * See the file LICENSE.txt at the root directory of this source
11 * distribution for additional information about the GNU GPL.
12 *
13 * For using ViSP with software that can not be combined with the GNU
14 * GPL, please contact Inria about acquiring a ViSP Professional
15 * Edition License.
16 *
17 * See http://visp.inria.fr for more information.
18 *
19 * This software was developed at:
20 * Inria Rennes - Bretagne Atlantique
21 * Campus Universitaire de Beaulieu
22 * 35042 Rennes Cedex
23 * France
24 *
25 * If you have questions regarding the use of this file, please contact
26 * Inria at visp@inria.fr
27 *
28 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30 *
31 * Description:
32 * Make the complete tracking of an object by using its CAD model
33 *
34 * Authors:
35 * Aurelien Yol
36 *
37 *****************************************************************************/
38
39 #include <limits.h>
40
41 #include <visp3/core/vpConfig.h>
42 /*!
43 \file vpPolygon3D.cpp
44 \brief Implements a polygon of the model used by the model-based tracker.
45 */
46
47 #include <visp3/core/vpPolygon.h>
48 #include <visp3/core/vpPolygon3D.h>
49
50 /*!
51 Basic constructor.
52 */
vpPolygon3D()53 vpPolygon3D::vpPolygon3D()
54 : nbpt(0), nbCornersInsidePrev(0), p(NULL), polyClipped(), clippingFlag(vpPolygon3D::NO_CLIPPING),
55 distNearClip(0.001), distFarClip(100.)
56 {
57 }
58
vpPolygon3D(const vpPolygon3D & mbtp)59 vpPolygon3D::vpPolygon3D(const vpPolygon3D &mbtp)
60 : nbpt(mbtp.nbpt), nbCornersInsidePrev(mbtp.nbCornersInsidePrev), p(NULL), polyClipped(mbtp.polyClipped),
61 clippingFlag(mbtp.clippingFlag), distNearClip(mbtp.distNearClip), distFarClip(mbtp.distFarClip)
62 {
63 if (p)
64 delete[] p;
65 p = new vpPoint[nbpt];
66 for (unsigned int i = 0; i < nbpt; i++)
67 p[i] = mbtp.p[i];
68 }
69
operator =(const vpPolygon3D & mbtp)70 vpPolygon3D &vpPolygon3D::operator=(const vpPolygon3D &mbtp)
71 {
72 nbpt = mbtp.nbpt;
73 nbCornersInsidePrev = mbtp.nbCornersInsidePrev;
74 polyClipped = mbtp.polyClipped;
75 clippingFlag = mbtp.clippingFlag;
76 distNearClip = mbtp.distNearClip;
77 distFarClip = mbtp.distFarClip;
78
79 if (p)
80 delete[] p;
81 p = new vpPoint[nbpt];
82 for (unsigned int i = 0; i < nbpt; i++)
83 p[i] = mbtp.p[i];
84
85 return (*this);
86 }
87
88 /*!
89 Basic destructor.
90 */
~vpPolygon3D()91 vpPolygon3D::~vpPolygon3D()
92 {
93 if (p != NULL) {
94 delete[] p;
95 p = NULL;
96 }
97 }
98
99 /*!
100 Get a reference to a corner.
101
102 \throw vpException::dimensionError if the _index is out of range.
103
104 \param _index : the index of the corner
105 */
getPoint(const unsigned int _index)106 vpPoint &vpPolygon3D::getPoint(const unsigned int _index)
107 {
108 if (_index >= nbpt) {
109 throw vpException(vpException::dimensionError, "index out of range");
110 }
111 return p[_index];
112 }
113
114 /*!
115 Set the number of points which are the corners of the polygon.
116
117 \param nb : The number of corners.
118 */
setNbPoint(unsigned int nb)119 void vpPolygon3D::setNbPoint(unsigned int nb)
120 {
121 nbpt = nb;
122 if (p != NULL)
123 delete[] p;
124 p = new vpPoint[nb];
125 }
126
127 /*!
128 Add a corner point to the list of polygon's corners.
129
130 \param n : The index of the corner.
131 \param P : The point to add.
132 */
addPoint(unsigned int n,const vpPoint & P)133 void vpPolygon3D::addPoint(unsigned int n, const vpPoint &P)
134 {
135 // if( p!NULL && n < nbpt )
136 p[n] = P;
137 }
138
139 /*!
140 Project the 3D corner points into the image thanks to the pose of the
141 camera.
142
143 \param cMo : The pose of the camera.
144 */
changeFrame(const vpHomogeneousMatrix & cMo)145 void vpPolygon3D::changeFrame(const vpHomogeneousMatrix &cMo)
146 {
147 for (unsigned int i = 0; i < nbpt; i++) {
148 p[i].changeFrame(cMo);
149 p[i].projection();
150 }
151 }
152
153 /*!
154 Compute the region of interest in the image according to the used clipping.
155
156 \warning If the FOV clipping is used, camera normals have to be precomputed.
157
158 \param cam : camera parameters used to compute the field of view.
159 */
computePolygonClipped(const vpCameraParameters & cam)160 void vpPolygon3D::computePolygonClipped(const vpCameraParameters &cam)
161 {
162 polyClipped.clear();
163 std::vector<vpColVector> fovNormals;
164 std::vector<std::pair<vpPoint, unsigned int> > polyClippedTemp;
165 std::vector<std::pair<vpPoint, unsigned int> > polyClippedTemp2;
166
167 if (cam.isFovComputed() && clippingFlag > 3)
168 fovNormals = cam.getFovNormals();
169
170 for (unsigned int i = 0; i < nbpt; i++) {
171 p[i % nbpt].projection();
172 polyClippedTemp.push_back(std::make_pair(p[i % nbpt], vpPolygon3D::NO_CLIPPING));
173 }
174
175 if (clippingFlag != vpPolygon3D::NO_CLIPPING) {
176 for (unsigned int i = 1; i < 64; i = i * 2) {
177 if (((clippingFlag & i) == i) || ((clippingFlag > vpPolygon3D::FAR_CLIPPING) && (i == 1))) {
178 if (i > vpPolygon3D::FAR_CLIPPING && !cam.isFovComputed()) // To make sure we do not compute FOV
179 // clipping if camera normals are not
180 // computed
181 continue;
182
183 for (unsigned int j = 0; j < polyClippedTemp.size(); j++) {
184 vpPoint p1Clipped = polyClippedTemp[j].first;
185 vpPoint p2Clipped = polyClippedTemp[(j + 1) % polyClippedTemp.size()].first;
186
187 unsigned int p2ClippedInfoBefore = polyClippedTemp[(j + 1) % polyClippedTemp.size()].second;
188 unsigned int p1ClippedInfo = polyClippedTemp[j].second;
189 unsigned int p2ClippedInfo = polyClippedTemp[(j + 1) % polyClippedTemp.size()].second;
190
191 bool problem = true;
192
193 switch (i) {
194 case 1:
195 problem = !(vpPolygon3D::getClippedPointsDistance(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
196 p2ClippedInfo, i, distNearClip));
197 break;
198 case 2:
199 problem = !(vpPolygon3D::getClippedPointsDistance(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
200 p2ClippedInfo, i, distFarClip));
201 break;
202 case 4:
203 problem =
204 !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
205 p2ClippedInfo, fovNormals[0], vpPolygon3D::LEFT_CLIPPING));
206 break;
207 case 8:
208 problem =
209 !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
210 p2ClippedInfo, fovNormals[1], vpPolygon3D::RIGHT_CLIPPING));
211 break;
212 case 16:
213 problem =
214 !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
215 p2ClippedInfo, fovNormals[2], vpPolygon3D::UP_CLIPPING));
216 break;
217 case 32:
218 problem =
219 !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
220 p2ClippedInfo, fovNormals[3], vpPolygon3D::DOWN_CLIPPING));
221 break;
222 }
223
224 if (!problem) {
225 p1Clipped.projection();
226 polyClippedTemp2.push_back(std::make_pair(p1Clipped, p1ClippedInfo));
227
228 if (p2ClippedInfo != p2ClippedInfoBefore) {
229 p2Clipped.projection();
230 polyClippedTemp2.push_back(std::make_pair(p2Clipped, p2ClippedInfo));
231 }
232
233 if (nbpt == 2) {
234 if (p2ClippedInfo == p2ClippedInfoBefore) {
235 p2Clipped.projection();
236 polyClippedTemp2.push_back(std::make_pair(p2Clipped, p2ClippedInfo));
237 }
238 break;
239 }
240 }
241 }
242
243 polyClippedTemp = polyClippedTemp2;
244 polyClippedTemp2.clear();
245 }
246 }
247 }
248
249 polyClipped = polyClippedTemp;
250 }
251
252 /*!
253 Get the clipped points according to a plane equation.
254
255 \param cam : camera parameters
256 \param p1 : First extremity of the line.
257 \param p2 : Second extremity of the line.
258 \param p1Clipped : Resulting p1.
259 \param p2Clipped : Resulting p2.
260 \param p1ClippedInfo : Resulting clipping flag for p1.
261 \param p2ClippedInfo : Resulting clipping flag for p2.
262 \param A : Param A from plane equation.
263 \param B : Param B from plane equation.
264 \param C : Param C from plane equation.
265 \param D : Param D from plane equation.
266 \param flag : flag specifying the clipping used when calling this function.
267
268 \return True if the points have been clipped, False otherwise
269 */
getClippedPointsFovGeneric(const vpPoint & p1,const vpPoint & p2,vpPoint & p1Clipped,vpPoint & p2Clipped,unsigned int & p1ClippedInfo,unsigned int & p2ClippedInfo,const vpColVector & normal,const unsigned int & flag)270 bool vpPolygon3D::getClippedPointsFovGeneric(const vpPoint &p1, const vpPoint &p2, vpPoint &p1Clipped,
271 vpPoint &p2Clipped, unsigned int &p1ClippedInfo,
272 unsigned int &p2ClippedInfo, const vpColVector &normal,
273 const unsigned int &flag)
274 {
275 vpRowVector p1Vec(3);
276 p1Vec[0] = p1.get_X();
277 p1Vec[1] = p1.get_Y();
278 p1Vec[2] = p1.get_Z();
279 p1Vec.normalize();
280
281 vpRowVector p2Vec(3);
282 p2Vec[0] = p2.get_X();
283 p2Vec[1] = p2.get_Y();
284 p2Vec[2] = p2.get_Z();
285 p2Vec.normalize();
286
287 if ((clippingFlag & flag) == flag) {
288 double beta1 = acos(p1Vec * normal);
289 double beta2 = acos(p2Vec * normal);
290
291 // std::cout << beta1 << " && " << beta2 << std::endl;
292
293 // if(!(beta1 < M_PI / 2.0 && beta2 < M_PI / 2.0))
294 if (beta1 < M_PI / 2.0 && beta2 < M_PI / 2.0)
295 return false;
296 else if (beta1 < M_PI / 2.0 || beta2 < M_PI / 2.0) {
297 vpPoint pClipped;
298 double t = -(normal[0] * p1.get_X() + normal[1] * p1.get_Y() + normal[2] * p1.get_Z());
299 t = t / (normal[0] * (p2.get_X() - p1.get_X()) + normal[1] * (p2.get_Y() - p1.get_Y()) +
300 normal[2] * (p2.get_Z() - p1.get_Z()));
301
302 pClipped.set_X((p2.get_X() - p1.get_X()) * t + p1.get_X());
303 pClipped.set_Y((p2.get_Y() - p1.get_Y()) * t + p1.get_Y());
304 pClipped.set_Z((p2.get_Z() - p1.get_Z()) * t + p1.get_Z());
305
306 if (beta1 < M_PI / 2.0) {
307 p1ClippedInfo = p1ClippedInfo | flag;
308 p1Clipped = pClipped;
309 } else {
310 p2ClippedInfo = p2ClippedInfo | flag;
311 p2Clipped = pClipped;
312 }
313 }
314 }
315
316 return true;
317 }
318
getClippedPointsDistance(const vpPoint & p1,const vpPoint & p2,vpPoint & p1Clipped,vpPoint & p2Clipped,unsigned int & p1ClippedInfo,unsigned int & p2ClippedInfo,const unsigned int & flag,const double & distance)319 bool vpPolygon3D::getClippedPointsDistance(const vpPoint &p1, const vpPoint &p2, vpPoint &p1Clipped, vpPoint &p2Clipped,
320 unsigned int &p1ClippedInfo, unsigned int &p2ClippedInfo,
321 const unsigned int &flag, const double &distance)
322 {
323 // Since p1 and p1Clipped can be the same object as well as p2 and p2Clipped
324 // to avoid a valgrind "Source and destination overlap in memcpy" error,
325 // we introduce a two temporary points.
326 vpPoint p1Clipped_, p2Clipped_;
327 p1Clipped_ = p1;
328 p2Clipped_ = p2;
329
330 p1Clipped = p1Clipped_;
331 p2Clipped = p2Clipped_;
332
333 bool test1 = (p1Clipped.get_Z() < distance && p2Clipped.get_Z() < distance);
334 if (flag == vpPolygon3D::FAR_CLIPPING)
335 test1 = (p1Clipped.get_Z() > distance && p2Clipped.get_Z() > distance);
336
337 bool test2 = (p1Clipped.get_Z() < distance || p2Clipped.get_Z() < distance);
338 if (flag == vpPolygon3D::FAR_CLIPPING)
339 test2 = (p1Clipped.get_Z() > distance || p2Clipped.get_Z() > distance);
340
341 bool test3 = (p1Clipped.get_Z() < distance);
342 if (flag == vpPolygon3D::FAR_CLIPPING)
343 test3 = (p1Clipped.get_Z() > distance);
344
345 if (test1)
346 return false;
347
348 else if (test2) {
349 vpPoint pClippedNear;
350 double t;
351 t = (p2Clipped.get_Z() - p1Clipped.get_Z());
352 t = (distance - p1Clipped.get_Z()) / t;
353
354 pClippedNear.set_X((p2Clipped.get_X() - p1Clipped.get_X()) * t + p1Clipped.get_X());
355 pClippedNear.set_Y((p2Clipped.get_Y() - p1Clipped.get_Y()) * t + p1Clipped.get_Y());
356 pClippedNear.set_Z(distance);
357
358 if (test3) {
359 p1Clipped = pClippedNear;
360 if (flag == vpPolygon3D::FAR_CLIPPING)
361 p1ClippedInfo = p1ClippedInfo | vpPolygon3D::FAR_CLIPPING;
362 else
363 p1ClippedInfo = p1ClippedInfo | vpPolygon3D::NEAR_CLIPPING;
364 } else {
365 p2Clipped = pClippedNear;
366 if (flag == vpPolygon3D::FAR_CLIPPING)
367 p2ClippedInfo = p2ClippedInfo | vpPolygon3D::FAR_CLIPPING;
368 else
369 p2ClippedInfo = p2ClippedInfo | vpPolygon3D::NEAR_CLIPPING;
370 }
371 }
372
373 return true;
374 }
375
376 /*!
377 Get the region of interest in the image.
378
379 \warning Suppose that changeFrame() has already been called.
380
381 \param cam : camera parameters.
382
383 \return Image point corresponding to the region of interest.
384 */
getRoi(const vpCameraParameters & cam)385 std::vector<vpImagePoint> vpPolygon3D::getRoi(const vpCameraParameters &cam)
386 {
387 std::vector<vpImagePoint> roi;
388 for (unsigned int i = 0; i < nbpt; i++) {
389 vpImagePoint ip;
390 vpMeterPixelConversion::convertPoint(cam, p[i].get_x(), p[i].get_y(), ip);
391 roi.push_back(ip);
392 }
393
394 return roi;
395 }
396
397 /*!
398 Get the region of interest in the image.
399
400 \param cam : camera parameters.
401 \param cMo : pose.
402
403 \return Image point corresponding to the region of interest.
404 */
getRoi(const vpCameraParameters & cam,const vpHomogeneousMatrix & cMo)405 std::vector<vpImagePoint> vpPolygon3D::getRoi(const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo)
406 {
407 changeFrame(cMo);
408 return getRoi(cam);
409 }
410
411 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
412 /*!
413 Get the 3D points of the clipped region of interest.
414
415 \warning Suppose that changeFrame() and computePolygonClipped() have already
416 been called.
417
418 \param points : resulting points.
419 */
getRoiClipped(std::vector<vpPoint> & points)420 void vpPolygon3D::getRoiClipped(std::vector<vpPoint> &points)
421 {
422 for (unsigned int i = 0; i < polyClipped.size(); i++) {
423 points.push_back(polyClipped[i].first);
424 }
425 }
426 #endif
427
428 /*!
429 Get the 3D clipped points and their clipping information.
430
431 \warning Suppose that changeFrame() and computePolygonClipped() have already
432 been called.
433
434 \param poly : resulting points plus clipping information.
435 */
getPolygonClipped(std::vector<std::pair<vpPoint,unsigned int>> & poly)436 void vpPolygon3D::getPolygonClipped(std::vector<std::pair<vpPoint, unsigned int> > &poly) { poly = polyClipped; }
437
438 /*!
439 Get the 3D clipped points.
440
441 \warning Suppose that changeFrame() and computePolygonClipped() have already
442 been called.
443
444 \param poly : resulting points.
445 */
getPolygonClipped(std::vector<vpPoint> & poly)446 void vpPolygon3D::getPolygonClipped(std::vector<vpPoint> &poly)
447 {
448 for (unsigned int i = 0; i < polyClipped.size(); i++) {
449 poly.push_back(polyClipped[i].first);
450 }
451 }
452
453 /*!
454 Get the region of interest clipped in the image.
455
456 \warning Suppose that changeFrame() and computePolygonClipped() have already
457 been called.
458
459 \param cam : camera parameters.
460 \param roi : image point corresponding to the region of interest.
461 */
getRoiClipped(const vpCameraParameters & cam,std::vector<vpImagePoint> & roi)462 void vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<vpImagePoint> &roi)
463 {
464 for (unsigned int i = 0; i < polyClipped.size(); i++) {
465 vpImagePoint ip;
466 vpMeterPixelConversion::convertPoint(cam, polyClipped[i].first.get_x(), polyClipped[i].first.get_y(), ip);
467 // std::cout << "## " << ip.get_j() << " - " << ip.get_i() <<
468 // std::endl;
469 roi.push_back(ip);
470 }
471 }
472
473 /*!
474 Get the region of interest clipped in the image.
475
476 \param cam : camera parameters.
477 \param cMo : pose.
478 \param roi : image point corresponding to the region of interest.
479 */
getRoiClipped(const vpCameraParameters & cam,std::vector<vpImagePoint> & roi,const vpHomogeneousMatrix & cMo)480 void vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<vpImagePoint> &roi,
481 const vpHomogeneousMatrix &cMo)
482 {
483 changeFrame(cMo);
484 computePolygonClipped(cam);
485 getRoiClipped(cam, roi);
486 }
487
488 /*!
489 Get the region of interest clipped in the image and the information to know
490 if it's a clipped point.
491
492 \warning Suppose that changeFrame() and computePolygonClipped() have already
493 been called.
494
495 \param cam : camera parameters.
496 \param roi : image point corresponding to the region of interest with
497 clipping information.
498 */
getRoiClipped(const vpCameraParameters & cam,std::vector<std::pair<vpImagePoint,unsigned int>> & roi)499 void vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<std::pair<vpImagePoint, unsigned int> > &roi)
500 {
501 for (unsigned int i = 0; i < polyClipped.size(); i++) {
502 vpImagePoint ip;
503 polyClipped[i].first.projection();
504 vpMeterPixelConversion::convertPoint(cam, polyClipped[i].first.get_x(), polyClipped[i].first.get_y(), ip);
505 roi.push_back(std::make_pair(ip, polyClipped[i].second));
506 }
507 }
508
509 /*!
510 Get the region of interest clipped in the image and the information to know
511 if it's a clipped point.
512
513 \param cam : camera parameters.
514 \param roi : image point corresponding to the region of interest with
515 clipping information. \param cMo : pose.
516 */
getRoiClipped(const vpCameraParameters & cam,std::vector<std::pair<vpImagePoint,unsigned int>> & roi,const vpHomogeneousMatrix & cMo)517 void vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<std::pair<vpImagePoint, unsigned int> > &roi,
518 const vpHomogeneousMatrix &cMo)
519 {
520 changeFrame(cMo);
521 computePolygonClipped(cam);
522 getRoiClipped(cam, roi);
523 }
524
525 /*!
526 Static method to check the number of points of a region defined by the
527 vector of image point that are inside the image.
528
529 \param I : The image used for its size.
530 \param cam : The camera parameters.
531 */
getNbCornerInsideImage(const vpImage<unsigned char> & I,const vpCameraParameters & cam)532 unsigned int vpPolygon3D::getNbCornerInsideImage(const vpImage<unsigned char> &I, const vpCameraParameters &cam)
533 {
534 unsigned int nbPolyIn = 0;
535 for (unsigned int i = 0; i < nbpt; i++) {
536 if (p[i].get_Z() > 0) {
537 vpImagePoint ip;
538 vpMeterPixelConversion::convertPoint(cam, p[i].get_x(), p[i].get_y(), ip);
539 if ((ip.get_i() >= 0) && (ip.get_j() >= 0) && (ip.get_i() < I.getHeight()) && (ip.get_j() < I.getWidth()))
540 nbPolyIn++;
541 }
542 }
543
544 nbCornersInsidePrev = nbPolyIn;
545
546 return nbPolyIn;
547 }
548
549 //###################################
550 // Static functions
551 //###################################
552
553 /*!
554 Static method to compute the clipped points from a set of initial points.
555
556 \warning When using FOV clipping and personnal camera parameters, camera
557 normals have to be computed before (see vpCameraParameters::computeFov())
558
559 \param ptIn : Input points
560 \param ptOut : Output points (result of the clipping).
561 \param cMo : Pose considered for the clipping.
562 \param clippingFlags: Clipping flag (see
563 vpPolygon3D::vpPolygon3DClippingType). \param cam : Camera parameters (Only
564 used if clipping flags contain FOV clipping). \param znear : Near clipping
565 distance value (Only used if clipping flags contain Near clipping). \param
566 zfar : Far clipping distance value (Only used if clipping flags contain Far
567 clipping).
568 */
getClippedPolygon(const std::vector<vpPoint> & ptIn,std::vector<vpPoint> & ptOut,const vpHomogeneousMatrix & cMo,const unsigned int & clippingFlags,const vpCameraParameters & cam,const double & znear,const double & zfar)569 void vpPolygon3D::getClippedPolygon(const std::vector<vpPoint> &ptIn, std::vector<vpPoint> &ptOut,
570 const vpHomogeneousMatrix &cMo, const unsigned int &clippingFlags,
571 const vpCameraParameters &cam, const double &znear, const double &zfar)
572 {
573 ptOut.clear();
574 vpPolygon3D poly;
575 poly.setNbPoint((unsigned int)ptIn.size());
576 poly.setClipping(clippingFlags);
577
578 if ((clippingFlags & vpPolygon3D::NEAR_CLIPPING) == vpPolygon3D::NEAR_CLIPPING)
579 poly.setNearClippingDistance(znear);
580
581 if ((clippingFlags & vpPolygon3D::FAR_CLIPPING) == vpPolygon3D::FAR_CLIPPING)
582 poly.setFarClippingDistance(zfar);
583
584 for (unsigned int i = 0; i < ptIn.size(); i++)
585 poly.addPoint(i, ptIn[i]);
586
587 poly.changeFrame(cMo);
588 poly.computePolygonClipped(cam);
589 poly.getPolygonClipped(ptOut);
590 }
591
getMinMaxRoi(const std::vector<vpImagePoint> & iroi,int & i_min,int & i_max,int & j_min,int & j_max)592 void vpPolygon3D::getMinMaxRoi(const std::vector<vpImagePoint> &iroi, int &i_min, int &i_max, int &j_min, int &j_max)
593 {
594 // i_min_d = std::numeric_limits<double>::max(); // create an error under
595 // Windows. To fix it we have to add #undef max
596 double i_min_d = (double)INT_MAX;
597 double i_max_d = 0;
598 double j_min_d = (double)INT_MAX;
599 double j_max_d = 0;
600
601 for (unsigned int i = 0; i < iroi.size(); i += 1) {
602 if (i_min_d > iroi[i].get_i())
603 i_min_d = iroi[i].get_i();
604
605 if (iroi[i].get_i() < 0)
606 i_min_d = 1;
607
608 if ((iroi[i].get_i() > 0) && (i_max_d < iroi[i].get_i()))
609 i_max_d = iroi[i].get_i();
610
611 if (j_min_d > iroi[i].get_j())
612 j_min_d = iroi[i].get_j();
613
614 if (iroi[i].get_j() < 0)
615 j_min_d = 1; // border
616
617 if ((iroi[i].get_j() > 0) && j_max_d < iroi[i].get_j())
618 j_max_d = iroi[i].get_j();
619 }
620 i_min = static_cast<int>(i_min_d);
621 i_max = static_cast<int>(i_max_d);
622 j_min = static_cast<int>(j_min_d);
623 j_max = static_cast<int>(j_max_d);
624 }
625
626 /*!
627 Static method to check whether the region defined by the vector of image
628 point is contained entirely in the image.
629
630 \param I : The image used for its size.
631 \param corners : The vector of points defining a region
632 */
roiInsideImage(const vpImage<unsigned char> & I,const std::vector<vpImagePoint> & corners)633 bool vpPolygon3D::roiInsideImage(const vpImage<unsigned char> &I, const std::vector<vpImagePoint> &corners)
634 {
635 double nbPolyIn = 0;
636 for (unsigned int i = 0; i < corners.size(); ++i) {
637 if ((corners[i].get_i() >= 0) && (corners[i].get_j() >= 0) && (corners[i].get_i() < I.getHeight()) &&
638 (corners[i].get_j() < I.getWidth())) {
639 nbPolyIn++;
640 }
641 }
642
643 if (nbPolyIn < 3 && nbPolyIn < 0.7 * corners.size())
644 return false;
645
646 return true;
647 }
648