Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpPolygon3D.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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 https://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
38
39#include <limits.h>
40
41#include <visp3/core/vpConfig.h>
42
43#include <visp3/core/vpPolygon.h>
44#include <visp3/core/vpPolygon3D.h>
45
54
58{
59 if (p)
60 delete[] p;
61 p = new vpPoint[nbpt];
62 for (unsigned int i = 0; i < nbpt; i++)
63 p[i] = mbtp.p[i];
64}
65
67{
68 nbpt = mbtp.nbpt;
74
75 if (p)
76 delete[] p;
77 p = new vpPoint[nbpt];
78 for (unsigned int i = 0; i < nbpt; i++)
79 p[i] = mbtp.p[i];
80
81 return (*this);
82}
83
88{
89 if (p != nullptr) {
90 delete[] p;
91 p = nullptr;
92 }
93}
94
102vpPoint &vpPolygon3D::getPoint(const unsigned int _index)
103{
104 if (_index >= nbpt) {
105 throw vpException(vpException::dimensionError, "index out of range");
106 }
107 return p[_index];
108}
109
115void vpPolygon3D::setNbPoint(unsigned int nb)
116{
117 nbpt = nb;
118 if (p != nullptr)
119 delete[] p;
120 p = new vpPoint[nb];
121}
122
129void vpPolygon3D::addPoint(unsigned int n, const vpPoint &P)
130{
131 // if( p!nullptr && n < nbpt )
132 p[n] = P;
133}
134
142{
143 for (unsigned int i = 0; i < nbpt; i++) {
144 p[i].changeFrame(cMo);
145 p[i].projection();
146 }
147}
148
157{
158 polyClipped.clear();
159 std::vector<vpColVector> fovNormals;
160 std::vector<std::pair<vpPoint, unsigned int> > polyClippedTemp;
161 std::vector<std::pair<vpPoint, unsigned int> > polyClippedTemp2;
162
163 if (cam.isFovComputed() && clippingFlag > 3)
164 fovNormals = cam.getFovNormals();
165
166 for (unsigned int i = 0; i < nbpt; i++) {
167 p[i % nbpt].projection();
168 polyClippedTemp.push_back(std::make_pair(p[i % nbpt], vpPolygon3D::NO_CLIPPING));
169 }
170
172 for (unsigned int i = 1; i < 64; i = i * 2) {
173 if (((clippingFlag & i) == i) || ((clippingFlag > vpPolygon3D::FAR_CLIPPING) && (i == 1))) {
174 if (i > vpPolygon3D::FAR_CLIPPING && !cam.isFovComputed()) // To make sure we do not compute FOV
175 // clipping if camera normals are not
176 // computed
177 continue;
178
179 for (unsigned int j = 0; j < polyClippedTemp.size(); j++) {
180 vpPoint p1Clipped = polyClippedTemp[j].first;
181 vpPoint p2Clipped = polyClippedTemp[(j + 1) % polyClippedTemp.size()].first;
182
183 unsigned int p2ClippedInfoBefore = polyClippedTemp[(j + 1) % polyClippedTemp.size()].second;
184 unsigned int p1ClippedInfo = polyClippedTemp[j].second;
185 unsigned int p2ClippedInfo = polyClippedTemp[(j + 1) % polyClippedTemp.size()].second;
186
187 bool problem = true;
188
189 switch (i) {
190 case 1:
191 problem = !(vpPolygon3D::getClippedPointsDistance(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
192 p2ClippedInfo, i, distNearClip));
193 break;
194 case 2:
195 problem = !(vpPolygon3D::getClippedPointsDistance(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
196 p2ClippedInfo, i, distFarClip));
197 break;
198 case 4:
199 problem =
200 !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
201 p2ClippedInfo, fovNormals[0], vpPolygon3D::LEFT_CLIPPING));
202 break;
203 case 8:
204 problem =
205 !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
206 p2ClippedInfo, fovNormals[1], vpPolygon3D::RIGHT_CLIPPING));
207 break;
208 case 16:
209 problem =
210 !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
211 p2ClippedInfo, fovNormals[2], vpPolygon3D::UP_CLIPPING));
212 break;
213 case 32:
214 problem =
215 !(vpPolygon3D::getClippedPointsFovGeneric(p1Clipped, p2Clipped, p1Clipped, p2Clipped, p1ClippedInfo,
216 p2ClippedInfo, fovNormals[3], vpPolygon3D::DOWN_CLIPPING));
217 break;
218 }
219
220 if (!problem) {
221 p1Clipped.projection();
222 polyClippedTemp2.push_back(std::make_pair(p1Clipped, p1ClippedInfo));
223
224 if (p2ClippedInfo != p2ClippedInfoBefore) {
225 p2Clipped.projection();
226 polyClippedTemp2.push_back(std::make_pair(p2Clipped, p2ClippedInfo));
227 }
228
229 if (nbpt == 2) {
230 if (p2ClippedInfo == p2ClippedInfoBefore) {
231 p2Clipped.projection();
232 polyClippedTemp2.push_back(std::make_pair(p2Clipped, p2ClippedInfo));
233 }
234 break;
235 }
236 }
237 }
238
239 polyClippedTemp = polyClippedTemp2;
240 polyClippedTemp2.clear();
241 }
242 }
243 }
244
245 polyClipped = polyClippedTemp;
246}
247
262bool vpPolygon3D::getClippedPointsFovGeneric(const vpPoint &p1, const vpPoint &p2, vpPoint &p1Clipped,
263 vpPoint &p2Clipped, unsigned int &p1ClippedInfo,
264 unsigned int &p2ClippedInfo, const vpColVector &normal,
265 const unsigned int &flag)
266{
267 vpRowVector p1Vec(3);
268 p1Vec[0] = p1.get_X();
269 p1Vec[1] = p1.get_Y();
270 p1Vec[2] = p1.get_Z();
271 p1Vec.normalize();
272
273 vpRowVector p2Vec(3);
274 p2Vec[0] = p2.get_X();
275 p2Vec[1] = p2.get_Y();
276 p2Vec[2] = p2.get_Z();
277 p2Vec.normalize();
278
279 if ((clippingFlag & flag) == flag) {
280 double beta1 = acos(p1Vec * normal);
281 double beta2 = acos(p2Vec * normal);
282
283 // std::cout << beta1 << " && " << beta2 << std::endl;
284
285 // if(!(beta1 < M_PI / 2.0 && beta2 < M_PI / 2.0))
286 if (beta1 < M_PI / 2.0 && beta2 < M_PI / 2.0)
287 return false;
288 else if (beta1 < M_PI / 2.0 || beta2 < M_PI / 2.0) {
289 vpPoint pClipped;
290 double t = -(normal[0] * p1.get_X() + normal[1] * p1.get_Y() + normal[2] * p1.get_Z());
291 t = t / (normal[0] * (p2.get_X() - p1.get_X()) + normal[1] * (p2.get_Y() - p1.get_Y()) +
292 normal[2] * (p2.get_Z() - p1.get_Z()));
293
294 pClipped.set_X((p2.get_X() - p1.get_X()) * t + p1.get_X());
295 pClipped.set_Y((p2.get_Y() - p1.get_Y()) * t + p1.get_Y());
296 pClipped.set_Z((p2.get_Z() - p1.get_Z()) * t + p1.get_Z());
297
298 if (beta1 < M_PI / 2.0) {
299 p1ClippedInfo = p1ClippedInfo | flag;
300 p1Clipped = pClipped;
301 }
302 else {
303 p2ClippedInfo = p2ClippedInfo | flag;
304 p2Clipped = pClipped;
305 }
306 }
307 }
308
309 return true;
310}
311
312bool vpPolygon3D::getClippedPointsDistance(const vpPoint &p1, const vpPoint &p2, vpPoint &p1Clipped, vpPoint &p2Clipped,
313 unsigned int &p1ClippedInfo, unsigned int &p2ClippedInfo,
314 const unsigned int &flag, const double &distance)
315{
316 // Since p1 and p1Clipped can be the same object as well as p2 and p2Clipped
317 // to avoid a valgrind "Source and destination overlap in memcpy" error,
318 // we introduce a two temporary points.
319 vpPoint p1Clipped_, p2Clipped_;
320 p1Clipped_ = p1;
321 p2Clipped_ = p2;
322
323 p1Clipped = p1Clipped_;
324 p2Clipped = p2Clipped_;
325
326 bool test1 = (p1Clipped.get_Z() < distance && p2Clipped.get_Z() < distance);
327 if (flag == vpPolygon3D::FAR_CLIPPING)
328 test1 = (p1Clipped.get_Z() > distance && p2Clipped.get_Z() > distance);
329
330 bool test2 = (p1Clipped.get_Z() < distance || p2Clipped.get_Z() < distance);
331 if (flag == vpPolygon3D::FAR_CLIPPING)
332 test2 = (p1Clipped.get_Z() > distance || p2Clipped.get_Z() > distance);
333
334 bool test3 = (p1Clipped.get_Z() < distance);
335 if (flag == vpPolygon3D::FAR_CLIPPING)
336 test3 = (p1Clipped.get_Z() > distance);
337
338 if (test1)
339 return false;
340
341 else if (test2) {
342 vpPoint pClippedNear;
343 double t;
344 t = (p2Clipped.get_Z() - p1Clipped.get_Z());
345 t = (distance - p1Clipped.get_Z()) / t;
346
347 pClippedNear.set_X((p2Clipped.get_X() - p1Clipped.get_X()) * t + p1Clipped.get_X());
348 pClippedNear.set_Y((p2Clipped.get_Y() - p1Clipped.get_Y()) * t + p1Clipped.get_Y());
349 pClippedNear.set_Z(distance);
350
351 if (test3) {
352 p1Clipped = pClippedNear;
353 if (flag == vpPolygon3D::FAR_CLIPPING)
354 p1ClippedInfo = p1ClippedInfo | vpPolygon3D::FAR_CLIPPING;
355 else
356 p1ClippedInfo = p1ClippedInfo | vpPolygon3D::NEAR_CLIPPING;
357 }
358 else {
359 p2Clipped = pClippedNear;
360 if (flag == vpPolygon3D::FAR_CLIPPING)
361 p2ClippedInfo = p2ClippedInfo | vpPolygon3D::FAR_CLIPPING;
362 else
363 p2ClippedInfo = p2ClippedInfo | vpPolygon3D::NEAR_CLIPPING;
364 }
365 }
366
367 return true;
368}
369
379std::vector<vpImagePoint> vpPolygon3D::getRoi(const vpCameraParameters &cam)
380{
381 std::vector<vpImagePoint> roi;
382 for (unsigned int i = 0; i < nbpt; i++) {
383 vpImagePoint ip;
384 vpMeterPixelConversion::convertPoint(cam, p[i].get_x(), p[i].get_y(), ip);
385 roi.push_back(ip);
386 }
387
388 return roi;
389}
390
399std::vector<vpImagePoint> vpPolygon3D::getRoi(const vpCameraParameters &cam, const vpHomogeneousMatrix &cMo)
400{
401 changeFrame(cMo);
402 return getRoi(cam);
403}
404
405#ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
414void vpPolygon3D::getRoiClipped(std::vector<vpPoint> &points)
415{
416 for (unsigned int i = 0; i < polyClipped.size(); i++) {
417 points.push_back(polyClipped[i].first);
418 }
419}
420#endif
421
430void vpPolygon3D::getPolygonClipped(std::vector<std::pair<vpPoint, unsigned int> > &poly) { poly = polyClipped; }
431
440void vpPolygon3D::getPolygonClipped(std::vector<vpPoint> &poly)
441{
442 for (unsigned int i = 0; i < polyClipped.size(); i++) {
443 poly.push_back(polyClipped[i].first);
444 }
445}
446
456void vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<vpImagePoint> &roi)
457{
458 for (unsigned int i = 0; i < polyClipped.size(); i++) {
459 vpImagePoint ip;
460 vpMeterPixelConversion::convertPoint(cam, polyClipped[i].first.get_x(), polyClipped[i].first.get_y(), ip);
461 // std::cout << "## " << ip.get_j() << " - " << ip.get_i() <<
462 // std::endl;
463 roi.push_back(ip);
464 }
465}
466
474void vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<vpImagePoint> &roi,
475 const vpHomogeneousMatrix &cMo)
476{
477 changeFrame(cMo);
479 getRoiClipped(cam, roi);
480}
481
493void vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<std::pair<vpImagePoint, unsigned int> > &roi)
494{
495 for (unsigned int i = 0; i < polyClipped.size(); i++) {
496 vpImagePoint ip;
497 polyClipped[i].first.projection();
498 vpMeterPixelConversion::convertPoint(cam, polyClipped[i].first.get_x(), polyClipped[i].first.get_y(), ip);
499 roi.push_back(std::make_pair(ip, polyClipped[i].second));
500 }
501}
502
511void vpPolygon3D::getRoiClipped(const vpCameraParameters &cam, std::vector<std::pair<vpImagePoint, unsigned int> > &roi,
512 const vpHomogeneousMatrix &cMo)
513{
514 changeFrame(cMo);
516 getRoiClipped(cam, roi);
517}
518
527{
528 unsigned int nbPolyIn = 0;
529 for (unsigned int i = 0; i < nbpt; i++) {
530 if (p[i].get_Z() > 0) {
531 vpImagePoint ip;
532 vpMeterPixelConversion::convertPoint(cam, p[i].get_x(), p[i].get_y(), ip);
533 if ((ip.get_i() >= 0) && (ip.get_j() >= 0) && (ip.get_i() < I.getHeight()) && (ip.get_j() < I.getWidth()))
534 nbPolyIn++;
535 }
536 }
537
538 nbCornersInsidePrev = nbPolyIn;
539
540 return nbPolyIn;
541}
542
543//###################################
544// Static functions
545//###################################
546
561void vpPolygon3D::getClippedPolygon(const std::vector<vpPoint> &ptIn, std::vector<vpPoint> &ptOut,
562 const vpHomogeneousMatrix &cMo, const unsigned int &clippingFlags,
563 const vpCameraParameters &cam, const double &znear, const double &zfar)
564{
565 ptOut.clear();
566 vpPolygon3D poly;
567 poly.setNbPoint(static_cast<unsigned int>(ptIn.size()));
568 poly.setClipping(clippingFlags);
569
571 poly.setNearClippingDistance(znear);
572
574 poly.setFarClippingDistance(zfar);
575
576 for (unsigned int i = 0; i < ptIn.size(); i++)
577 poly.addPoint(i, ptIn[i]);
578
579 poly.changeFrame(cMo);
580 poly.computePolygonClipped(cam);
581 poly.getPolygonClipped(ptOut);
582}
583
584void vpPolygon3D::getMinMaxRoi(const std::vector<vpImagePoint> &iroi, int &i_min, int &i_max, int &j_min, int &j_max)
585{
586 // i_min_d = std::numeric_limits<double>::max(); // create an error under
587 // Windows. To fix it we have to add #undef max
588 double i_min_d = static_cast<double>(INT_MAX);
589 double i_max_d = 0;
590 double j_min_d = static_cast<double>(INT_MAX);
591 double j_max_d = 0;
592
593 for (unsigned int i = 0; i < iroi.size(); i += 1) {
594 if (i_min_d > iroi[i].get_i())
595 i_min_d = iroi[i].get_i();
596
597 if (iroi[i].get_i() < 0)
598 i_min_d = 1;
599
600 if ((iroi[i].get_i() > 0) && (i_max_d < iroi[i].get_i()))
601 i_max_d = iroi[i].get_i();
602
603 if (j_min_d > iroi[i].get_j())
604 j_min_d = iroi[i].get_j();
605
606 if (iroi[i].get_j() < 0)
607 j_min_d = 1; // border
608
609 if ((iroi[i].get_j() > 0) && j_max_d < iroi[i].get_j())
610 j_max_d = iroi[i].get_j();
611 }
612 i_min = static_cast<int>(i_min_d);
613 i_max = static_cast<int>(i_max_d);
614 j_min = static_cast<int>(j_min_d);
615 j_max = static_cast<int>(j_max_d);
616}
617
625bool vpPolygon3D::roiInsideImage(const vpImage<unsigned char> &I, const std::vector<vpImagePoint> &corners)
626{
627 double nbPolyIn = 0;
628 for (unsigned int i = 0; i < corners.size(); ++i) {
629 if ((corners[i].get_i() >= 0) && (corners[i].get_j() >= 0) && (corners[i].get_i() < I.getHeight()) &&
630 (corners[i].get_j() < I.getWidth())) {
631 nbPolyIn++;
632 }
633 }
634
635 if (nbPolyIn < 3 && nbPolyIn < 0.7 * corners.size())
636 return false;
637
638 return true;
639}
640END_VISP_NAMESPACE
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ dimensionError
Bad dimension.
Definition vpException.h:71
Implementation of an homogeneous matrix and operations on such kind of matrices.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
double get_j() const
double get_i() const
Definition of the vpImage class member functions.
Definition vpImage.h:131
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition vpPoint.h:79
void projection(const vpColVector &_cP, vpColVector &_p) const VP_OVERRIDE
Definition vpPoint.cpp:252
double get_Y() const
Get the point cY coordinate in the camera frame.
Definition vpPoint.cpp:411
void set_X(double cX)
Set the point cX coordinate in the camera frame.
Definition vpPoint.cpp:453
void set_Y(double cY)
Set the point cY coordinate in the camera frame.
Definition vpPoint.cpp:455
double get_Z() const
Get the point cZ coordinate in the camera frame.
Definition vpPoint.cpp:413
void set_Z(double cZ)
Set the point cZ coordinate in the camera frame.
Definition vpPoint.cpp:457
double get_X() const
Get the point cX coordinate in the camera frame.
Definition vpPoint.cpp:409
void changeFrame(const vpHomogeneousMatrix &cMo)
void setFarClippingDistance(const double &dist)
unsigned int nbpt
Number of points used to define the polygon.
Definition vpPolygon3D.h:74
void setNearClippingDistance(const double &dist)
virtual ~vpPolygon3D()
double distNearClip
Distance for near clipping.
Definition vpPolygon3D.h:85
vpPoint & getPoint(const unsigned int _index)
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)
vpPoint * p
corners in the object frame
Definition vpPolygon3D.h:79
void computePolygonClipped(const vpCameraParameters &cam=vpCameraParameters())
static bool roiInsideImage(const vpImage< unsigned char > &I, const std::vector< vpImagePoint > &corners)
std::vector< vpImagePoint > getRoi(const vpCameraParameters &cam)
virtual void setNbPoint(unsigned int nb)
unsigned int clippingFlag
Clipping flag.
Definition vpPolygon3D.h:83
void setClipping(const unsigned int &flags)
void getRoiClipped(const vpCameraParameters &cam, std::vector< vpImagePoint > &roi)
unsigned int getNbCornerInsideImage(const vpImage< unsigned char > &I, const vpCameraParameters &cam)
std::vector< std::pair< vpPoint, unsigned int > > polyClipped
Region of interest clipped.
Definition vpPolygon3D.h:81
void addPoint(unsigned int n, const vpPoint &P)
double distFarClip
Distance for near clipping.
Definition vpPolygon3D.h:87
void getPolygonClipped(std::vector< std::pair< vpPoint, unsigned int > > &poly)
vpPolygon3D & operator=(const vpPolygon3D &mbtp)
unsigned int nbCornersInsidePrev
Definition vpPolygon3D.h:77
static void getMinMaxRoi(const std::vector< vpImagePoint > &roi, int &i_min, int &i_max, int &j_min, int &j_max)
Implementation of row vector and the associated operations.