Visual Servoing Platform  version 3.6.1 under development (2024-11-21)
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 *****************************************************************************/
34 
40 #include <visp3/core/vpPlane.h>
41 
42 #include <cmath> // std::fabs
43 #include <limits> // numeric_limits
44 
45 BEGIN_VISP_NAMESPACE
50 {
51  A = p.A;
52  B = p.B;
53  C = p.C;
54  D = p.D;
55 
56  return *this;
57 }
58 
62 vpPlane::vpPlane() : A(0), B(0), C(0), D(0) { }
63 
74 vpPlane::vpPlane(double a, double b, double c, double d) : A(a), B(b), C(c), D(d) { }
75 
79 vpPlane::vpPlane(const vpPlane &P) : A(0), B(0), C(0), D(0)
80 {
81  setA(P.getA());
82  setB(P.getB());
83  setC(P.getC());
84  setD(P.getD());
85 }
86 
106 vpPlane::vpPlane(const vpPoint &P, const vpColVector &n, 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 = n[index_0];
113  B = n[index_1];
114  C = n[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 
129 void vpPlane::init(const vpPlane &P)
130 {
131  setA(P.getA());
132  setB(P.getB());
133  setC(P.getC());
134  setD(P.getD());
135 }
136 
148 void vpPlane::init(const vpColVector &P, const vpColVector &n)
149 {
150  const unsigned int index_0 = 0;
151  const unsigned int index_1 = 1;
152  const unsigned int index_2 = 2;
153  // Equation of the plane is given by:
154  A = n[index_0];
155  B = n[index_1];
156  C = n[index_2];
157 
158  D = -((A * P[0]) + (B * P[1]) + (C * P[index_2]));
159 }
160 
172 void vpPlane::init(const vpPoint &P, const vpPoint &Q, const vpPoint &R, vpPlaneFrame frame)
173 {
174  vpColVector a(3);
175  vpColVector b(3);
176  vpColVector n(3);
177  const unsigned int index_0 = 0;
178  const unsigned int index_1 = 1;
179  const unsigned int index_2 = 2;
180  if (frame == vpPlane::camera_frame) {
181  // Calculate vector corresponding to PQ
182  a[index_0] = P.get_X() - Q.get_X();
183  a[index_1] = P.get_Y() - Q.get_Y();
184  a[index_2] = P.get_Z() - Q.get_Z();
185 
186  // Calculate vector corresponding to PR
187  b[index_0] = P.get_X() - R.get_X();
188  b[index_1] = P.get_Y() - R.get_Y();
189  b[index_2] = P.get_Z() - R.get_Z();
190  }
191  else {
192  // Calculate vector corresponding to PQ
193  a[index_0] = P.get_oX() - Q.get_oX();
194  a[index_1] = P.get_oY() - Q.get_oY();
195  a[index_2] = P.get_oZ() - Q.get_oZ();
196 
197  // Calculate vector corresponding to PR
198  b[index_0] = P.get_oX() - R.get_oX();
199  b[index_1] = P.get_oY() - R.get_oY();
200  b[index_2] = P.get_oZ() - R.get_oZ();
201  }
202  // Calculate normal vector to plane PQ x PR
203  n = vpColVector::cross(a, b);
204 
205  // Equation of the plane is given by:
206  A = n[index_0];
207  B = n[index_1];
208  C = n[index_2];
209  if (frame == vpPlane::camera_frame) {
210  D = -((A * P.get_X()) + (B * P.get_Y()) + (C * P.get_Z()));
211  }
212  else {
213  D = -((A * P.get_oX()) + (B * P.get_oY()) + (C * P.get_oZ()));
214  }
215 
216  double norm = sqrt((A * A) + (B * B) + (C * C));
217  A /= norm;
218  B /= norm;
219  C /= norm;
220  D /= norm;
221 }
222 
235 vpPlane::vpPlane(const vpPoint &P, const vpPoint &Q, const vpPoint &R, vpPlaneFrame frame) : A(0), B(0), C(0), D(0)
236 {
237  init(P, Q, R, frame);
238 }
239 
245 double vpPlane::computeZ(double x, double y) const
246 {
247  return -getD() / ((getA() * x) + (getB() * y) + getC());
248 }
249 
259 {
260  vpColVector n(3);
261  const unsigned int index_0 = 0;
262  const unsigned int index_1 = 1;
263  const unsigned int index_2 = 2;
264  n[index_0] = A;
265  n[index_1] = B;
266  n[index_2] = C;
267 
268  return n;
269 }
270 
282 {
283  n.resize(3);
284  const unsigned int index_0 = 0;
285  const unsigned int index_1 = 1;
286  const unsigned int index_2 = 2;
287  n[index_0] = A;
288  n[index_1] = B;
289  n[index_2] = C;
290 }
291 
298 void vpPlane::projectionPointOnPlan(const vpPoint &P, vpPoint &Pproj) const
299 {
300  double x0, y0, z0;
301  double rho;
302 
303  x0 = P.get_X() / P.get_W();
304  y0 = P.get_Y() / P.get_W();
305  z0 = P.get_Z() / P.get_W();
306 
307  rho = -((A * x0) + (B * y0) + (C * z0) + D) / ((A * A) + (B * B) + (C * C));
308 
309  Pproj.set_X(x0 + (A * rho));
310  Pproj.set_Y(y0 + (B * rho));
311  Pproj.set_Z(z0 + (C * rho));
312  Pproj.set_W(1);
313 }
314 
315 double vpPlane::rayIntersection(const vpPoint &M0, const vpPoint &M1, vpColVector &H) const
316 {
317  double k, scal;
318  const unsigned int index_0 = 0;
319  const unsigned int index_1 = 1;
320  const unsigned int index_2 = 2;
321 
322  // --comment: if M0.get_X() diff 0 or M0.get_Y() diff 0 or M0.get_Z() diff 0
323  if ((std::fabs(M0.get_X()) > std::numeric_limits<double>::epsilon()) ||
324  (std::fabs(M0.get_Y()) > std::numeric_limits<double>::epsilon()) ||
325  (std::fabs(M0.get_Z()) > std::numeric_limits<double>::epsilon())) {
326  double R[3];
327  R[index_0] = M1.get_X() - M0.get_X();
328  R[index_1] = M1.get_Y() - M0.get_Y();
329  R[index_2] = M1.get_Z() - M0.get_Z();
330 
331  scal = (getA() * R[index_0]) + (getB() * R[index_1]) + (getC() * R[index_2]);
332  // --comment: if scal != 0
333  if (std::fabs(scal) > std::numeric_limits<double>::epsilon()) {
334  k = -((getA() * M0.get_X()) + (getB() * M0.get_Y()) + (getC() * M0.get_Z()) + getD()) / scal;
335  }
336  else {
337  k = 0;
338  }
339 
340  H[index_0] = M0.get_X() + (k * R[index_0]);
341  H[index_1] = M0.get_Y() + (k * R[index_1]);
342  H[index_2] = M0.get_Z() + (k * R[index_2]);
343  }
344  else {
345  scal = (getA() * M1.get_X()) + (getB() * M1.get_Y()) + (getC() * M1.get_Z());
346  // --comment: if scal != 0
347  if (std::fabs(scal) > std::numeric_limits<double>::epsilon()) {
348  k = -getD() / scal;
349  }
350  else {
351  k = 0;
352  }
353  H[index_0] = k * M1.get_X();
354  H[index_1] = k * M1.get_Y();
355  H[index_2] = k * M1.get_Z();
356  }
357 
358  return k;
359 }
360 
362 {
363  double k, scal;
364  const unsigned int index_0 = 0;
365  const unsigned int index_1 = 1;
366  const unsigned int index_2 = 2;
367 
368  scal = (A * M1[index_0]) + (B * M1[index_1]) + (C * M1[index_2]);
369  // --comment: if scal != 0
370  if (std::fabs(scal) > std::numeric_limits<double>::epsilon()) {
371  k = -getD() / scal;
372  }
373  else {
374  k = 0;
375  }
376  H[index_0] = k * M1[index_0];
377  H[index_1] = k * M1[index_1];
378  H[index_2] = k * M1[index_2];
379 
380  return k;
381 }
382 
392 {
393  // Save current plane parameters
394  double Ao = A;
395  double Bo = B;
396  double Co = C;
397  double Do = D;
398  const unsigned int index_0 = 0;
399  const unsigned int index_1 = 1;
400  const unsigned int index_2 = 2;
401  const unsigned int index_3 = 3;
402  A = (cMo[index_0][0] * Ao) + (cMo[index_0][1] * Bo) + (cMo[index_0][index_2] * Co);
403  B = (cMo[index_1][0] * Ao) + (cMo[index_1][1] * Bo) + (cMo[index_1][index_2] * Co);
404  C = (cMo[index_2][0] * Ao) + (cMo[index_2][1] * Bo) + (cMo[index_2][index_2] * Co);
405  D = Do - ((cMo[index_0][index_3] * A) + (cMo[index_1][index_3] * B) + (cMo[index_2][index_3] * C));
406 }
407 
414 VISP_EXPORT std::ostream &operator<<(std::ostream &os, const vpPlane &p)
415 {
416  return (os << "(" << p.getA() << "," << p.getB() << "," << p.getC() << "," << p.getD() << ") ");
417 };
418 END_VISP_NAMESPACE
friend std::ostream & operator<<(std::ostream &s, const vpArray2D< Type > &A)
Definition: vpArray2D.h:614
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
static vpColVector cross(const vpColVector &a, const vpColVector &b)
Definition: vpColVector.h:1259
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:1143
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:57
vpPlaneFrame
Definition: vpPlane.h:65
@ camera_frame
Definition: vpPlane.h:65
double rayIntersection(const vpPoint &M0, const vpPoint &M1, vpColVector &H) const
Definition: vpPlane.cpp:315
void changeFrame(const vpHomogeneousMatrix &cMo)
Definition: vpPlane.cpp:391
void setA(double a)
Definition: vpPlane.h:80
void projectionPointOnPlan(const vpPoint &P, vpPoint &Pproj) const
Definition: vpPlane.cpp:298
void setD(double d)
Definition: vpPlane.h:86
double computeZ(double x, double y) const
Definition: vpPlane.cpp:245
double getD() const
Definition: vpPlane.h:106
void setC(double c)
Definition: vpPlane.h:84
vpColVector getNormal() const
Definition: vpPlane.cpp:258
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:49
vpPlane()
Definition: vpPlane.cpp:62
void init(const vpPoint &P, const vpPoint &Q, const vpPoint &R, vpPlaneFrame frame=camera_frame)
Definition: vpPlane.cpp:172
void setB(double b)
Definition: vpPlane.h:82
double getIntersection(const vpColVector &M1, vpColVector &H) const
Definition: vpPlane.cpp:361
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_oX() const
Get the point oX coordinate in the object frame.
Definition: vpPoint.cpp:411
void set_W(double cW)
Set the point cW coordinate in the camera frame.
Definition: vpPoint.cpp:452
double get_Y() const
Get the point cY coordinate in the camera frame.
Definition: vpPoint.cpp:404
double get_oZ() const
Get the point oZ coordinate in the object frame.
Definition: vpPoint.cpp:415
void set_X(double cX)
Set the point cX coordinate in the camera frame.
Definition: vpPoint.cpp:446
double get_W() const
Get the point cW coordinate in the camera frame.
Definition: vpPoint.cpp:408
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_oY() const
Get the point oY coordinate in the object frame.
Definition: vpPoint.cpp:413
double get_X() const
Get the point cX coordinate in the camera frame.
Definition: vpPoint.cpp:402