Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpMbtPolygon.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 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 https://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  * Romain Tallonneau
36  * Aurelien Yol
37  *
38 *****************************************************************************/
39 
40 #include <limits.h>
41 
42 #include <visp3/core/vpConfig.h>
48 #include <visp3/core/vpPolygon.h>
49 #include <visp3/mbt/vpMbtPolygon.h>
50 
56  : index(-1), isvisible(false), isappearing(false), useLod(false), minLineLengthThresh(50.0),
57  minPolygonAreaThresh(2500.0), name(""), hasOrientation(true)
58 { }
59 
61  : vpPolygon3D(mbtp), index(mbtp.index), isvisible(mbtp.isvisible), isappearing(mbtp.isappearing), useLod(mbtp.useLod),
62  minLineLengthThresh(mbtp.minLineLengthThresh), minPolygonAreaThresh(mbtp.minPolygonAreaThresh), name(mbtp.name),
63  hasOrientation(mbtp.hasOrientation)
64 {
65  //*this = mbtp; // Should not be called by copy constructor to avoid multiple assignments.
66 }
67 
69 {
71  index = mbtp.index;
72  isvisible = mbtp.isvisible;
73  isappearing = mbtp.isappearing;
74  useLod = mbtp.useLod;
77  name = mbtp.name;
79 
80  return (*this);
81 }
82 
99 bool vpMbtPolygon::isVisible(const vpHomogeneousMatrix &cMo, double alpha, const bool &modulo,
100  const vpCameraParameters &cam, unsigned int width, unsigned int height)
101 {
102  // std::cout << "Computing angle from MBT Face (cMo, alpha)" << std::endl;
103 
104  changeFrame(cMo);
105 
106  if (nbpt <= 2) {
107  // Level of detail (LOD)
108  if (useLod) {
109  vpCameraParameters c = cam;
110  if (clippingFlag > 3) { // Contains at least one FOV constraint
111  c.computeFov(width, height);
112  }
114  std::vector<vpImagePoint> roiImagePoints;
115  getRoiClipped(c, roiImagePoints);
116 
117  if (roiImagePoints.size() == 2) {
118  double x1 = roiImagePoints[0].get_u();
119  double y1 = roiImagePoints[0].get_v();
120  double x2 = roiImagePoints[1].get_u();
121  double y2 = roiImagePoints[1].get_v();
122  double length = std::sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
123  // std::cout << "Index=" << index << " ; Line length=" <<
124  // length << " ; clippingFlag=" << clippingFlag << std::endl;
125  // vpTRACE("index=%d length=%f minLineLengthThresh=%f", index,
126  // length, minLineLengthThresh);
127 
128  if (length < minLineLengthThresh) {
129  isvisible = false;
130  isappearing = false;
131  return false;
132  }
133  }
134  }
135 
136  /* a line is always visible when LOD is not used */
137  isvisible = true;
138  isappearing = false;
139  return true;
140  }
141 
142  // If the polygon has no orientation, the angle check visibility is always
143  // valid. Feature mainly used for cylinders.
144  if (!hasOrientation) {
145  isvisible = true;
146  isappearing = false;
147  return true;
148  }
149 
150  // Check visibility from normal
151  // Newell's Method for calculating the normal of an arbitrary 3D polygon
152  // https://www.opengl.org/wiki/Calculating_a_Surface_Normal
153  vpColVector faceNormal(3);
154  vpColVector currentVertex, nextVertex;
155  for (unsigned int i = 0; i < nbpt; i++) {
156  currentVertex = p[i].cP;
157  nextVertex = p[(i + 1) % nbpt].cP;
158 
159  faceNormal[0] += (currentVertex[1] - nextVertex[1]) * (currentVertex[2] + nextVertex[2]);
160  faceNormal[1] += (currentVertex[2] - nextVertex[2]) * (currentVertex[0] + nextVertex[0]);
161  faceNormal[2] += (currentVertex[0] - nextVertex[0]) * (currentVertex[1] + nextVertex[1]);
162  }
163  faceNormal.normalize();
164 
165  vpColVector e4(3);
166  vpPoint pt;
167  for (unsigned int i = 0; i < nbpt; i += 1) {
168  pt.set_X(pt.get_X() + p[i].get_X());
169  pt.set_Y(pt.get_Y() + p[i].get_Y());
170  pt.set_Z(pt.get_Z() + p[i].get_Z());
171  }
172  e4[0] = -pt.get_X() / (double)nbpt;
173  e4[1] = -pt.get_Y() / (double)nbpt;
174  e4[2] = -pt.get_Z() / (double)nbpt;
175  e4.normalize();
176 
177  double angle = acos(vpColVector::dotProd(e4, faceNormal));
178 
179  // vpCTRACE << angle << "/" << vpMath::deg(angle) << "/" <<
180  // vpMath::deg(alpha) << std::endl;
181 
182  if (angle < alpha || (modulo && (M_PI - angle) < alpha)) {
183  isvisible = true;
184  isappearing = false;
185 
186  if (useLod) {
187  vpCameraParameters c = cam;
188  if (clippingFlag > 3) { // Contains at least one FOV constraint
189  c.computeFov(width, height);
190  }
192  std::vector<vpImagePoint> roiImagePoints;
193  getRoiClipped(c, roiImagePoints);
194 
195  vpPolygon roiPolygon(roiImagePoints);
196  double area = roiPolygon.getArea();
197  // std::cout << "After normal test ; Index=" << index << " ; area="
198  // << area << " ; clippingFlag="
199  // << clippingFlag << std::endl;
200  if (area < minPolygonAreaThresh) {
201  isappearing = false;
202  isvisible = false;
203  return false;
204  }
205  }
206 
207  return true;
208  }
209 
210  if (angle < alpha + vpMath::rad(1)) {
211  isappearing = true;
212  }
213  else if (modulo && (M_PI - angle) < alpha + vpMath::rad(1)) {
214  isappearing = true;
215  }
216  else {
217  isappearing = false;
218  }
219 
220  isvisible = false;
221  return false;
222 }
223 
224 //###################################
225 // Static functions
226 //###################################
227 
275 void vpMbtPolygon::setLod(bool use_lod) { this->useLod = use_lod; }
276 END_VISP_NAMESPACE
Generic class defining intrinsic camera parameters.
void computeFov(const unsigned int &w, const unsigned int &h)
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
static double dotProd(const vpColVector &a, const vpColVector &b)
vpColVector & normalize()
Implementation of an homogeneous matrix and operations on such kind of matrices.
static double rad(double deg)
Definition: vpMath.h:129
Implementation of a polygon of the model used by the model-based tracker.
Definition: vpMbtPolygon.h:60
bool isvisible
flag to specify whether the face is visible or not
Definition: vpMbtPolygon.h:66
bool hasOrientation
Definition: vpMbtPolygon.h:82
double minLineLengthThresh
Definition: vpMbtPolygon.h:74
void setLod(bool use_lod)
double minPolygonAreaThresh
Definition: vpMbtPolygon.h:77
bool isappearing
flag to specify whether the face is appearing or not
Definition: vpMbtPolygon.h:68
std::string name
Name of the polygon.
Definition: vpMbtPolygon.h:79
bool isVisible() const
Definition: vpMbtPolygon.h:107
vpMbtPolygon & operator=(const vpMbtPolygon &mbtp)
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:79
double get_Y() const
Get the point cY coordinate in the camera frame.
Definition: vpPoint.cpp:404
void set_X(double cX)
Set the point cX coordinate in the camera frame.
Definition: vpPoint.cpp:446
void set_Y(double cY)
Set the point cY coordinate in the camera frame.
Definition: vpPoint.cpp:448
double get_Z() const
Get the point cZ coordinate in the camera frame.
Definition: vpPoint.cpp:406
void set_Z(double cZ)
Set the point cZ coordinate in the camera frame.
Definition: vpPoint.cpp:450
double get_X() const
Get the point cX coordinate in the camera frame.
Definition: vpPoint.cpp:402
Implements a 3D polygon with render functionalities like clipping.
Definition: vpPolygon3D.h:57
void changeFrame(const vpHomogeneousMatrix &cMo)
unsigned int nbpt
Number of points used to define the polygon.
Definition: vpPolygon3D.h:74
vpPoint * p
corners in the object frame
Definition: vpPolygon3D.h:79
void computePolygonClipped(const vpCameraParameters &cam=vpCameraParameters())
unsigned int clippingFlag
Clipping flag.
Definition: vpPolygon3D.h:83
void getRoiClipped(const vpCameraParameters &cam, std::vector< vpImagePoint > &roi)
vpPolygon3D & operator=(const vpPolygon3D &mbtp)
Definition: vpPolygon3D.cpp:71
Defines a generic 2D polygon.
Definition: vpPolygon.h:103
double getArea() const
Definition: vpPolygon.h:154
vpColVector cP
Definition: vpTracker.h:73