Visual Servoing Platform  version 3.6.1 under development (2025-02-18)
vpPlane.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 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  * Plane geometrical structure.
32  */
33 
39 #include <visp3/core/vpPlane.h>
40 
41 #include <cmath> // std::fabs
42 #include <limits> // numeric_limits
43 
44 BEGIN_VISP_NAMESPACE
49 {
50  A = p.A;
51  B = p.B;
52  C = p.C;
53  D = p.D;
54 
55  return *this;
56 }
57 
61 vpPlane::vpPlane() : A(0), B(0), C(0), D(0) { }
62 
73 vpPlane::vpPlane(double a, double b, double c, double d) : A(a), B(b), C(c), D(d) { }
74 
78 vpPlane::vpPlane(const vpPlane &P) : A(0), B(0), C(0), D(0)
79 {
80  setA(P.getA());
81  setB(P.getB());
82  setC(P.getC());
83  setD(P.getD());
84 }
85 
106 vpPlane::vpPlane(const vpPoint &P, const vpColVector &normal, vpPlaneFrame frame) : A(0), B(0), C(0), D(0)
107 {
108  const unsigned int index_0 = 0;
109  const unsigned int index_1 = 1;
110  const unsigned int index_2 = 2;
111  // Equation of the plane is given by:
112  A = normal[index_0];
113  B = normal[index_1];
114  C = normal[index_2];
115 
116  if (frame == vpPlane::camera_frame) {
117  D = -((A * P.get_X()) + (B * P.get_Y()) + (C * P.get_Z()));
118  }
119  else {
120  D = -((A * P.get_oX()) + (B * P.get_oY()) + (C * P.get_oZ()));
121  }
122 }
123 
130 {
131  setA(P.getA());
132  setB(P.getB());
133  setC(P.getC());
134  setD(P.getD());
135 
136  return *this;
137 }
138 
157 vpPlane &vpPlane::init(const vpPoint &P, const vpColVector &normal, vpPlaneFrame frame)
158 {
159  const unsigned int index_0 = 0;
160  const unsigned int index_1 = 1;
161  const unsigned int index_2 = 2;
162  // Equation of the plane is given by:
163  A = normal[index_0];
164  B = normal[index_1];
165  C = normal[index_2];
166 
167  if (frame == vpPlane::camera_frame) {
168  D = -((A * P.get_X()) + (B * P.get_Y()) + (C * P.get_Z()));
169  }
170  else {
171  D = -((A * P.get_oX()) + (B * P.get_oY()) + (C * P.get_oZ()));
172  }
173 
174  return *this;
175 }
176 
188 vpPlane &vpPlane::init(const vpColVector &P, const vpColVector &normal)
189 {
190  const unsigned int index_0 = 0;
191  const unsigned int index_1 = 1;
192  const unsigned int index_2 = 2;
193  // Equation of the plane is given by:
194  A = normal[index_0];
195  B = normal[index_1];
196  C = normal[index_2];
197 
198  D = -((A * P[0]) + (B * P[1]) + (C * P[index_2]));
199 
200  return *this;
201 }
202 
214 vpPlane &vpPlane::init(const vpPoint &P, const vpPoint &Q, const vpPoint &R, vpPlaneFrame frame)
215 {
216  vpColVector a(3);
217  vpColVector b(3);
218  vpColVector n(3);
219  const unsigned int index_0 = 0;
220  const unsigned int index_1 = 1;
221  const unsigned int index_2 = 2;
222  if (frame == vpPlane::camera_frame) {
223  // Calculate vector corresponding to PQ
224  a[index_0] = P.get_X() - Q.get_X();
225  a[index_1] = P.get_Y() - Q.get_Y();
226  a[index_2] = P.get_Z() - Q.get_Z();
227 
228  // Calculate vector corresponding to PR
229  b[index_0] = P.get_X() - R.get_X();
230  b[index_1] = P.get_Y() - R.get_Y();
231  b[index_2] = P.get_Z() - R.get_Z();
232  }
233  else {
234  // Calculate vector corresponding to PQ
235  a[index_0] = P.get_oX() - Q.get_oX();
236  a[index_1] = P.get_oY() - Q.get_oY();
237  a[index_2] = P.get_oZ() - Q.get_oZ();
238 
239  // Calculate vector corresponding to PR
240  b[index_0] = P.get_oX() - R.get_oX();
241  b[index_1] = P.get_oY() - R.get_oY();
242  b[index_2] = P.get_oZ() - R.get_oZ();
243  }
244  // Calculate normal vector to plane PQ x PR
245  n = vpColVector::cross(a, b);
246 
247  // Equation of the plane is given by:
248  A = n[index_0];
249  B = n[index_1];
250  C = n[index_2];
251  if (frame == vpPlane::camera_frame) {
252  D = -((A * P.get_X()) + (B * P.get_Y()) + (C * P.get_Z()));
253  }
254  else {
255  D = -((A * P.get_oX()) + (B * P.get_oY()) + (C * P.get_oZ()));
256  }
257 
258  double norm = sqrt((A * A) + (B * B) + (C * C));
259  A /= norm;
260  B /= norm;
261  C /= norm;
262  D /= norm;
263 
264  return *this;
265 }
266 
279 vpPlane::vpPlane(const vpPoint &P, const vpPoint &Q, const vpPoint &R, vpPlaneFrame frame) : A(0), B(0), C(0), D(0)
280 {
281  init(P, Q, R, frame);
282 }
283 
289 double vpPlane::computeZ(double x, double y) const
290 {
291  return -getD() / ((getA() * x) + (getB() * y) + getC());
292 }
293 
303 {
304  const unsigned int val_3 = 3;
305  vpColVector n(val_3);
306  const unsigned int index_0 = 0;
307  const unsigned int index_1 = 1;
308  const unsigned int index_2 = 2;
309  n[index_0] = A;
310  n[index_1] = B;
311  n[index_2] = C;
312 
313  return n;
314 }
315 
327 {
328  const unsigned int val_3 = 3;
329  n.resize(val_3);
330  const unsigned int index_0 = 0;
331  const unsigned int index_1 = 1;
332  const unsigned int index_2 = 2;
333  n[index_0] = A;
334  n[index_1] = B;
335  n[index_2] = C;
336 }
337 
349 void vpPlane::projectionPointOnPlan(const vpPoint &P, vpPoint &Pproj, vpPlaneFrame frame) const
350 {
351  double x0, y0, z0;
352  double rho;
353 
354  if (frame == vpPlane::camera_frame) {
355  x0 = P.get_X() / P.get_W();
356  y0 = P.get_Y() / P.get_W();
357  z0 = P.get_Z() / P.get_W();
358 
359  rho = -((A * x0) + (B * y0) + (C * z0) + D) / ((A * A) + (B * B) + (C * C));
360 
361  Pproj.set_X(x0 + (A * rho));
362  Pproj.set_Y(y0 + (B * rho));
363  Pproj.set_Z(z0 + (C * rho));
364  Pproj.set_W(1);
365  }
366  else {
367  x0 = P.get_oX() / P.get_oW();
368  y0 = P.get_oY() / P.get_oW();
369  z0 = P.get_oZ() / P.get_oW();
370 
371  rho = -((A * x0) + (B * y0) + (C * z0) + D) / ((A * A) + (B * B) + (C * C));
372 
373  Pproj.set_oX(x0 + (A * rho));
374  Pproj.set_oY(y0 + (B * rho));
375  Pproj.set_oZ(z0 + (C * rho));
376  Pproj.set_oW(1);
377  }
378 }
379 
380 double vpPlane::rayIntersection(const vpPoint &M0, const vpPoint &M1, vpColVector &H) const
381 {
382  double k, scal;
383  const unsigned int index_0 = 0;
384  const unsigned int index_1 = 1;
385  const unsigned int index_2 = 2;
386 
387  // --comment: if M0.get_X() diff 0 or M0.get_Y() diff 0 or M0.get_Z() diff 0
388  if ((std::fabs(M0.get_X()) > std::numeric_limits<double>::epsilon()) ||
389  (std::fabs(M0.get_Y()) > std::numeric_limits<double>::epsilon()) ||
390  (std::fabs(M0.get_Z()) > std::numeric_limits<double>::epsilon())) {
391  double R[3];
392  R[index_0] = M1.get_X() - M0.get_X();
393  R[index_1] = M1.get_Y() - M0.get_Y();
394  R[index_2] = M1.get_Z() - M0.get_Z();
395 
396  scal = (getA() * R[index_0]) + (getB() * R[index_1]) + (getC() * R[index_2]);
397  // --comment: if scal != 0
398  if (std::fabs(scal) > std::numeric_limits<double>::epsilon()) {
399  k = -((getA() * M0.get_X()) + (getB() * M0.get_Y()) + (getC() * M0.get_Z()) + getD()) / scal;
400  }
401  else {
402  k = 0;
403  }
404 
405  H[index_0] = M0.get_X() + (k * R[index_0]);
406  H[index_1] = M0.get_Y() + (k * R[index_1]);
407  H[index_2] = M0.get_Z() + (k * R[index_2]);
408  }
409  else {
410  scal = (getA() * M1.get_X()) + (getB() * M1.get_Y()) + (getC() * M1.get_Z());
411  // --comment: if scal != 0
412  if (std::fabs(scal) > std::numeric_limits<double>::epsilon()) {
413  k = -getD() / scal;
414  }
415  else {
416  k = 0;
417  }
418  H[index_0] = k * M1.get_X();
419  H[index_1] = k * M1.get_Y();
420  H[index_2] = k * M1.get_Z();
421  }
422 
423  return k;
424 }
425 
427 {
428  double k, scal;
429  const unsigned int index_0 = 0;
430  const unsigned int index_1 = 1;
431  const unsigned int index_2 = 2;
432 
433  scal = (A * M1[index_0]) + (B * M1[index_1]) + (C * M1[index_2]);
434  // --comment: if scal != 0
435  if (std::fabs(scal) > std::numeric_limits<double>::epsilon()) {
436  k = -getD() / scal;
437  }
438  else {
439  k = 0;
440  }
441  H[index_0] = k * M1[index_0];
442  H[index_1] = k * M1[index_1];
443  H[index_2] = k * M1[index_2];
444 
445  return k;
446 }
447 
457 {
458  // Save current plane parameters
459  double Ao = A;
460  double Bo = B;
461  double Co = C;
462  double Do = D;
463  const unsigned int index_0 = 0;
464  const unsigned int index_1 = 1;
465  const unsigned int index_2 = 2;
466  const unsigned int index_3 = 3;
467  A = (cMo[index_0][0] * Ao) + (cMo[index_0][1] * Bo) + (cMo[index_0][index_2] * Co);
468  B = (cMo[index_1][0] * Ao) + (cMo[index_1][1] * Bo) + (cMo[index_1][index_2] * Co);
469  C = (cMo[index_2][0] * Ao) + (cMo[index_2][1] * Bo) + (cMo[index_2][index_2] * Co);
470  D = Do - ((cMo[index_0][index_3] * A) + (cMo[index_1][index_3] * B) + (cMo[index_2][index_3] * C));
471 }
472 
479 VISP_EXPORT std::ostream &operator<<(std::ostream &os, const vpPlane &p)
480 {
481  return (os << "(" << p.getA() << "," << p.getB() << "," << p.getC() << "," << p.getD() << ") ");
482 }
483 END_VISP_NAMESPACE
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:699
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
static vpColVector cross(const vpColVector &a, const vpColVector &b)
Definition: vpColVector.h:1264
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:1148
Implementation of an homogeneous matrix and operations on such kind of matrices.
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:56
vpPlaneFrame
Definition: vpPlane.h:64
@ camera_frame
Definition: vpPlane.h:64
double rayIntersection(const vpPoint &M0, const vpPoint &M1, vpColVector &H) const
Definition: vpPlane.cpp:380
void changeFrame(const vpHomogeneousMatrix &cMo)
Definition: vpPlane.cpp:456
void setA(double a)
Definition: vpPlane.h:80
vpPlane & init(const vpPoint &P, const vpColVector &normal, vpPlaneFrame frame=camera_frame)
Definition: vpPlane.cpp:157
void setD(double d)
Definition: vpPlane.h:86
double computeZ(double x, double y) const
Definition: vpPlane.cpp:289
double getD() const
Definition: vpPlane.h:106
void setC(double c)
Definition: vpPlane.h:84
void projectionPointOnPlan(const vpPoint &P, vpPoint &Pproj, vpPlaneFrame frame=camera_frame) const
Definition: vpPlane.cpp:349
vpColVector getNormal() const
Definition: vpPlane.cpp:302
double getA() const
Definition: vpPlane.h:100
double getC() const
Definition: vpPlane.h:104
double getB() const
Definition: vpPlane.h:102
vpPlane & operator=(const vpPlane &f)
Definition: vpPlane.cpp:48
vpPlane()
Definition: vpPlane.cpp:61
void setB(double b)
Definition: vpPlane.h:82
double getIntersection(const vpColVector &M1, vpColVector &H) const
Definition: vpPlane.cpp:426
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_oW() const
Get the point oW coordinate in the object frame.
Definition: vpPoint.cpp:421
double get_oX() const
Get the point oX coordinate in the object frame.
Definition: vpPoint.cpp:415
void set_W(double cW)
Set the point cW coordinate in the camera frame.
Definition: vpPoint.cpp:456
void set_oW(double oW)
Set the point oW coordinate in the object frame.
Definition: vpPoint.cpp:465
double get_Y() const
Get the point cY coordinate in the camera frame.
Definition: vpPoint.cpp:408
double get_oZ() const
Get the point oZ coordinate in the object frame.
Definition: vpPoint.cpp:419
void set_oY(double oY)
Set the point oY coordinate in the object frame.
Definition: vpPoint.cpp:461
void set_X(double cX)
Set the point cX coordinate in the camera frame.
Definition: vpPoint.cpp:450
double get_W() const
Get the point cW coordinate in the camera frame.
Definition: vpPoint.cpp:412
void set_Y(double cY)
Set the point cY coordinate in the camera frame.
Definition: vpPoint.cpp:452
double get_Z() const
Get the point cZ coordinate in the camera frame.
Definition: vpPoint.cpp:410
void set_oZ(double oZ)
Set the point oZ coordinate in the object frame.
Definition: vpPoint.cpp:463
void set_Z(double cZ)
Set the point cZ coordinate in the camera frame.
Definition: vpPoint.cpp:454
void set_oX(double oX)
Set the point oX coordinate in the object frame.
Definition: vpPoint.cpp:459
double get_oY() const
Get the point oY coordinate in the object frame.
Definition: vpPoint.cpp:417
double get_X() const
Get the point cX coordinate in the camera frame.
Definition: vpPoint.cpp:406