UsTK : Ultrasound ToolKit  version 2.0.1 under development (2024-05-17)
usGeometryTools.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ustk software.
4  * Copyright (C) 2016 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
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 ustk 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  * This software was developed at:
17  * Inria Rennes - Bretagne Atlantique
18  * Campus Universitaire de Beaulieu
19  * 35042 Rennes Cedex
20  * France
21  *
22  * If you have questions regarding the use of this file, please contact
23  * Inria at ustk@inria.fr
24  *
25  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27  *
28  * Author:
29  * Jason Chevrie
30  *
31  *****************************************************************************/
32 
33 #include <visp3/ustk_core/usGeometryTools.h>
34 
35 #include <limits>
36 
37 #include <visp3/core/vpException.h>
38 #include <visp3/core/vpMatrix.h>
39 #include <visp3/core/vpRotationMatrix.h>
40 #include <visp3/core/vpTranslationVector.h>
41 
42 namespace usGeometryTools
43 {
44 
45 double getPointPlaneDistance(const vpColVector &point, const usOrientedPlane3D &plane)
46 {
47  vpColVector p(plane.getPosition());
48  vpColVector d(plane.getDirection());
49  return vpColVector::dotProd(d, point - p);
50 }
51 
52 bool IsPointInFrontOfPlane(const vpColVector &point, const usOrientedPlane3D &plane)
53 {
54  return getPointPlaneDistance(point, plane) >= 0;
55 }
56 
58 {
59  return (IsPointInFrontOfPlane(poly.getStartPoint(), plane) != IsPointInFrontOfPlane(poly.getEndPoint(), plane));
60 }
61 
62 bool DoesSegmentCrossPlane(const usBSpline3D &spline, const usOrientedPlane3D &plane)
63 {
64  /*int N = spline.getNbSegments();
65  for(int i=0 ; i<N ; i++)
66  {
67  if(DoesSegmentCrossPlane(spline.accessSegment(i), plane)) return true;
68  }
69  return false;*/
70  return (IsPointInFrontOfPlane(spline.accessSegment(0).getStartPoint(), plane) !=
72 }
73 
75 {
76  return (!IsPointInFrontOfPlane(poly.getStartPoint(), plane) && IsPointInFrontOfPlane(poly.getEndPoint(), plane));
77 }
78 
80 {
81  /*int N = spline.getNbSegments();
82  for(int i=0 ; i<N ; i++)
83  {
84  if(DoesSegmentCrossPlaneDirect(spline.accessSegment(i), plane)) return true;
85  }
86  return false;*/
87  return (!IsPointInFrontOfPlane(spline.accessSegment(0).getStartPoint(), plane) &&
89 }
90 
92  double threshold, double *t)
93 {
94  if (threshold <= 0)
95  threshold = 1e-4 * poly.getParametricLength();
96 
97  double start = poly.getStartParameter();
98  vpColVector Pstart(poly.getPoint(start));
99  bool sideStart = IsPointInFrontOfPlane(Pstart, plane);
100  double end = poly.getEndParameter();
101  vpColVector Pend(poly.getPoint(end));
102  bool sideEnd = IsPointInFrontOfPlane(Pend, plane);
103  double mid = (start + end) / 2;
104  vpColVector Pmid(poly.getPoint(mid));
105  bool sideMid = IsPointInFrontOfPlane(Pmid, plane);
106 
107  double d = (Pend - Pstart).frobeniusNorm();
108 
109  while ((sideStart != sideEnd) && (d > threshold)) {
110  if (sideMid == sideStart) {
111  start = mid;
112  Pstart = Pmid;
113  } else if (sideMid == sideEnd) {
114  end = mid;
115  Pend = Pmid;
116  }
117 
118  mid = (start + end) / 2;
119  Pmid = poly.getPoint(mid);
120  sideMid = IsPointInFrontOfPlane(Pmid, plane);
121  d = (Pend - Pstart).frobeniusNorm();
122  }
123 
124  if (sideStart == sideEnd)
125  throw vpException(
126  vpException::badValue,
127  "usGeometryTools::getPlaneCurveCrossingPoint(usPolynomialCurve3D): segment and plane do not cross");
128 
129  if (t)
130  *t = mid;
131  return poly.getPoint(mid);
132 }
133 
134 vpColVector getPlaneCurveCrossingPoint(const usBSpline3D &spline, const usOrientedPlane3D &plane, double threshold,
135  double *t)
136 {
137  int seg = 0;
138  double L = 0;
139  int N = spline.getNbSegments();
140  /*while(seg < N && !usGeometryTools::DoesSegmentCrossPlane(spline.accessSegment(seg), plane))
141  {
142  L += spline.accessSegment(seg).getParametricLength();
143  seg++;
144  }*/
145 
146  if (N > 1) {
147  int start = 0;
148  vpColVector Pstart(spline.accessSegment(start).getStartPoint());
149  bool sideStart = IsPointInFrontOfPlane(Pstart, plane);
150  int end = N - 1;
151  vpColVector Pend(spline.accessSegment(end).getStartPoint());
152  bool sideEnd = IsPointInFrontOfPlane(Pend, plane);
153  int mid = (start + end) / 2;
154  vpColVector Pmid(spline.accessSegment(mid).getStartPoint());
155  bool sideMid = IsPointInFrontOfPlane(Pmid, plane);
156 
157  if (sideStart == sideEnd)
158  seg = N - 1;
159  else {
160  while (end - start > 1) {
161  if (sideMid == sideStart) {
162  start = mid;
163  Pstart = Pmid;
164  } else if (sideMid == sideEnd) {
165  end = mid;
166  Pend = Pmid;
167  }
168 
169  mid = (start + end) / 2;
170  Pmid = spline.accessSegment(mid).getStartPoint();
171  sideMid = IsPointInFrontOfPlane(Pmid, plane);
172  }
173  seg = start;
174  }
175  for (int i = 0; i < seg; i++)
176  L += spline.accessSegment(i).getParametricLength();
177  }
178 
179  if (seg >= N) {
180  throw vpException(vpException::badValue,
181  "usGeometryTools::getPlaneCurveCrossingPoint(usBSpline3D): spline and plane do not cross");
182  } else {
183  double t1 = -1;
184  vpColVector P = getPlaneCurveCrossingPoint(spline.accessSegment(seg), plane, threshold, &t1);
185  if (t)
186  *t = L + t1;
187  return P;
188  }
189 }
190 
191 vpColVector projectPointOnPlane(const vpColVector &point, const usOrientedPlane3D &plane, const vpColVector &direction)
192 {
193  vpColVector p(plane.getPosition());
194  vpColVector d(plane.getDirection());
195  if (direction.getCols() != 3) {
196  return (point - vpColVector::dotProd(point - p, d) * d);
197  } else {
198  vpColVector dp = direction;
199  dp.normalize();
200  double cos_theta = vpColVector::dotProd(dp, d);
201  if (fabs(cos_theta) < std::numeric_limits<double>::epsilon()) {
202  return (point - vpColVector::dotProd(point - p, d) * d);
203  } else {
204  return (point - vpColVector::dotProd(point - p, d) / cos_theta * dp);
205  }
206  }
207 }
208 
209 vpColVector projectPointOnCurve(const vpColVector &point, const usPolynomialCurve3D &poly, double threshold, double *t)
210 {
211  if (point.size() != 3)
212  throw vpException(vpException::dimensionError, "usGeometryTools::projectPointOnCurve: invalid point dimension");
213 
214  double start = poly.getStartParameter();
215  double stop = poly.getEndParameter();
216 
217  if (threshold <= 0)
218  threshold = fabs(stop - start) / 1000;
219 
220  double middle = (start + stop) / 2;
221  while ((stop - start) > threshold) {
222  double d0 = (poly.getPoint(start) - point).frobeniusNorm();
223  double d1 = (poly.getPoint(middle) - point).frobeniusNorm();
224  double d2 = (poly.getPoint(stop) - point).frobeniusNorm();
225 
226  if (d0 <= d1 && d0 < d2)
227  stop = middle;
228  else if (d2 < d0 && d2 <= d1)
229  start = middle;
230  else {
231  start = (start + middle) / 2;
232  stop = (middle + stop) / 2;
233  }
234  middle = (start + stop) / 2;
235  }
236 
237  vpColVector P = poly.getPoint(middle);
238  if (t)
239  *t = middle;
240 
241  return P;
242 }
243 
244 vpColVector projectPointOnCurve(const vpColVector &point, const usBSpline3D &spline, double threshold, int *index,
245  double *t)
246 {
247  if (point.size() != 3)
248  throw vpException(vpException::dimensionError, "usGeometryTools::projectPointOnCurve: invalid point dimension");
249 
250  int seg = 0;
251  double min = std::numeric_limits<double>::infinity();
252  for (int i = 0; i < spline.getNbSegments(); i++) {
253  double d = (spline.accessSegment(i).getStartPoint() - point).sumSquare();
254  if (d < min) {
255  min = d;
256  seg = i;
257  }
258  }
259 
260  if ((spline.accessLastSegment().getEndPoint() - point).sumSquare() < min) {
261  seg = spline.getNbSegments();
262  }
263 
264  if (index)
265  *index = seg;
266  if (seg == 0)
267  return projectPointOnCurve(point, spline.accessSegment(seg), threshold, t);
268  else if (seg == spline.getNbSegments()) {
269  seg--;
270  if (index)
271  *index = seg;
272  return projectPointOnCurve(point, spline.accessSegment(seg), threshold, t);
273  } else {
274  double t1;
275  double t2;
276  vpColVector P1 = projectPointOnCurve(point, spline.accessSegment(seg - 1), threshold, &t1);
277  vpColVector P2 = projectPointOnCurve(point, spline.accessSegment(seg), threshold, &t2);
278 
279  if ((P1 - point).sumSquare() < (P2 - point).sumSquare()) {
280  if (t)
281  *t = t1;
282  return P1;
283  } else {
284  if (t)
285  *t = t2;
286  return P2;
287  }
288  }
289 }
290 
292 {
293  return usOrientedPlane3D(p.getPoint(l), p.getTangent(l));
294 }
295 
297 {
298  double L = spline.getParametricLength();
299  int nbPoints = order + 1;
300  int nbSegments = order;
301  std::vector<vpColVector> p;
302  std::vector<double> l;
303  for (int i = 0; i < nbPoints; i++)
304  p.push_back(spline.getPoint(i * L / nbSegments));
305  l.push_back(0);
306  for (int i = 0; i < nbSegments; i++)
307  l.push_back(l.back() + (p.at(i + 1) - p.at(i)).frobeniusNorm());
308 
309  usPolynomialCurve3D P(order);
310  P.defineFromPoints(p, l, order);
311 
312  return P;
313 }
314 
315 usBSpline3D convertPolynomialToBSpline(const usPolynomialCurve3D &poly, int nbSegments, int order)
316 {
317  double L = poly.getParametricLength();
318  int nbPoints = nbSegments + 1;
319  std::vector<vpColVector> p;
320  std::vector<double> l;
321  for (int i = 0; i < nbPoints; i++)
322  p.push_back(poly.getPoint(i * L / nbSegments));
323  for (int i = 0; i < nbSegments; i++)
324  l.push_back((p.at(i + 1) - p.at(i)).frobeniusNorm());
325 
326  usBSpline3D S;
327  S.defineFromPoints(p, l, order);
328 
329  return S;
330 }
331 
332 vpPoseVector findPointCloudRelativePose(std::vector<vpColVector> &P1, std::vector<vpColVector> &P2, double *res)
333 {
334  unsigned int nbPoints = P1.size();
335  if (nbPoints < 2)
336  throw vpException(vpException::dimensionError, "usGeometryTools::findPointCloudRelativePose: not enough points");
337  if (nbPoints != P2.size())
338  throw vpException(vpException::dimensionError,
339  "usGeometryTools::findPointCloudRelativePose: non matching number of points");
340 
341  vpColVector Mean1(3, 0);
342  vpColVector Mean2(3, 0);
343 
344  for (unsigned int i = 0; i < nbPoints; i++) {
345  Mean1 += P1.at(i);
346  Mean2 += P2.at(i);
347  }
348  Mean1 /= nbPoints;
349  Mean2 /= nbPoints;
350 
351  vpMatrix H(3, 3, 0);
352  for (unsigned int i = 0; i < nbPoints; i++) {
353  H += (P1.at(i) - Mean1) * (P2.at(i) - Mean2).t();
354  }
355 
356  vpColVector w;
357  vpMatrix V;
358  H.svd(w, V);
359 
360  vpMatrix Rm = V * H.t();
361  if (Rm.det() < 0) {
362  for (int i = 0; i < 3; i++)
363  V[i][2] *= -1;
364  Rm = V * H.t();
365  }
366  vpRotationMatrix R;
367  for (int i = 0; i < 3; i++) {
368  for (int j = 0; j < 3; j++) {
369  R[i][j] = Rm[i][j];
370  }
371  }
372 
373  vpTranslationVector T(Mean2 - R * Mean1);
374 
375  vpPoseVector p(T, R);
376 
377  if (res != nullptr) {
378  *res = 0;
379  for (unsigned int i = 0; i < nbPoints; i++) {
380  *res += (R * P1.at(i) + T - (vpTranslationVector)P2.at(i)).sumSquare();
381  }
382  }
383 
384  return p;
385 }
386 
387 vpTranslationVector findPointCloudRelativePosition(std::vector<vpColVector> &P1, std::vector<vpColVector> &P2,
388  const vpRotationMatrix &worldRprobe, double *res)
389 {
390  unsigned int nbPoints = P1.size();
391  if (nbPoints < 2)
392  throw vpException(vpException::dimensionError, "usGeometryTools::findPointCloudRelativePose: not enough points");
393  if (nbPoints != P2.size())
394  throw vpException(vpException::dimensionError,
395  "usGeometryTools::findPointCloudRelativePose: non matching number of points");
396 
397  vpColVector Mean1(3, 0);
398  vpColVector Mean2(3, 0);
399 
400  for (unsigned int i = 0; i < nbPoints; i++) {
401  Mean1 += P1.at(i);
402  Mean2 += P2.at(i);
403  }
404  Mean1 /= nbPoints;
405  Mean2 /= nbPoints;
406 
407  vpTranslationVector T(Mean2 - worldRprobe * Mean1);
408 
409  if (res != nullptr) {
410  *res = 0;
411  for (unsigned int i = 0; i < nbPoints; i++) {
412  *res += (worldRprobe * P1.at(i) + T - (vpTranslationVector)P2.at(i)).sumSquare();
413  }
414  }
415 
416  return T;
417 }
418 
419 vpRotationMatrix findPointCloudRelativeRotation(std::vector<vpColVector> &P1, std::vector<vpColVector> &P2, double *res)
420 {
421  unsigned int nbPoints = P1.size();
422  if (nbPoints < 2)
423  throw vpException(vpException::dimensionError,
424  "usGeometryTools::findPointCloudRelativeRotation: not enough points");
425  if (nbPoints != P2.size())
426  throw vpException(vpException::dimensionError,
427  "usGeometryTools::findPointCloudRelativeRotation: non matching number of points");
428 
429  vpMatrix H(3, 3, 0);
430  for (unsigned int i = 0; i < nbPoints; i++)
431  H += P1.at(i) * P2.at(i).t();
432 
433  vpColVector w;
434  vpMatrix V;
435  H.svd(w, V);
436 
437  vpMatrix Rm = V * H.t();
438  if (Rm.det() < 0) {
439  for (int i = 0; i < 3; i++)
440  V[i][2] *= -1;
441  Rm = V * H.t();
442  }
443  vpRotationMatrix R;
444  for (int i = 0; i < 3; i++) {
445  for (int j = 0; j < 3; j++) {
446  R[i][j] = Rm[i][j];
447  }
448  }
449 
450  if (res != nullptr) {
451  *res = 0;
452  for (unsigned int i = 0; i < nbPoints; i++) {
453  *res += (R * P1.at(i) - P2.at(i)).sumSquare();
454  }
455  }
456 
457  return R;
458 }
459 
460 vpPoseVector ICPPointCloudRelativePose(std::vector<vpColVector> &P1, std::vector<vpColVector> &P2, double *res,
461  vpPoseVector *initialGuess)
462 {
463  if (P1.size() < 1 || P2.size() < 1)
464  throw vpException(vpException::dimensionError,
465  "usGeometryTools::ICPPointCloudRelativePose: not enough points to match");
466 
467  vpTranslationVector T;
468  vpRotationMatrix R;
469 
470  if (initialGuess) {
471  T = initialGuess->getTranslationVector();
472  R = initialGuess->getRotationMatrix();
473  } else {
474  vpColVector meanP1(3, 0);
475  for (unsigned int i = 0; i < P1.size(); i++)
476  meanP1 += P1[i];
477  meanP1 /= (double)P1.size();
478  vpColVector meanP2(3, 0);
479  for (unsigned int i = 0; i < P2.size(); i++)
480  meanP2 += P2[i];
481  meanP2 /= (double)P2.size();
482  T = meanP2 - meanP1;
483  }
484 
485  vpMatrix dist(P1.size(), P2.size(), 0);
486  std::vector<vpColVector> matchPoint(P1.size(), vpColVector(3));
487  double residual = 0;
488  double resRatio = 1;
489  int it = 0;
490 
491  while ((it < 10) && (resRatio > 0.01)) {
492  for (unsigned int i = 0; i < P1.size(); i++) {
493  for (unsigned int j = 0; j < P2.size(); j++) {
494  dist[i][j] = ((R * P1.at(i) + T) - (vpTranslationVector)P2.at(j)).sumSquare();
495  }
496  }
497 
498  for (unsigned int i = 0; i < P1.size(); i++) {
499  int index = 0;
500  double min = std::numeric_limits<double>::max();
501  for (unsigned int j = 0; j < P2.size(); j++) {
502  if (dist[i][j] < min) {
503  min = dist[i][j];
504  index = j;
505  }
506  }
507  matchPoint.at(i) = P2.at(index);
508  }
509 
510  double resi = 0;
511  vpPoseVector pose(findPointCloudRelativePose(P1, matchPoint, &resi));
512  T = pose.getTranslationVector();
513  R = pose.getRotationMatrix();
514  if (residual > 0)
515  resRatio = fabs(residual - resi) / residual;
516  else
517  resRatio = 1;
518  residual = resi;
519  }
520 
521  if (res)
522  *res = residual;
523 
524  return vpPoseVector(T, R);
525 }
526 
527 vpTranslationVector ICPPointCloudRelativePosition(std::vector<vpColVector> &P1, std::vector<vpColVector> &P2,
528  const vpRotationMatrix &worldRprobe, double *res,
529  vpTranslationVector *initialGuess)
530 {
531  (void)P1;
532  (void)P2;
533  (void)worldRprobe;
534  (void)res;
535  (void)initialGuess;
536  throw vpException(vpException::notImplementedError,
537  "usGeometryTools::ICPPointCloudRelativePosition: non implement yet");
538 }
539 
540 vpRotationMatrix ICPPointCloudRelativeRotation(std::vector<vpColVector> &P1, std::vector<vpColVector> &P2, double *res,
541  vpRotationMatrix *initialGuess)
542 {
543  (void)P1;
544  (void)P2;
545  (void)res;
546  (void)initialGuess;
547  throw vpException(vpException::notImplementedError,
548  "usGeometryTools::ICPPointCloudRelativeRotation: non implement yet");
549 }
550 
551 bool fitCircleTo2DPointCloud(const std::vector<vpColVector> &points, vpColVector &center, double &r)
552 {
553  // 2D nonlinear least square fitting (Coope93)
554  unsigned int nbPoints = points.size();
555  if (nbPoints < 3)
556  throw vpException(vpException::ioError, "usGeometryTools::fitCircleTo2DPointCloud: not enough points");
557 
558  // Create data matrix with centered vectors
559  vpMatrix M(3, nbPoints);
560  vpColVector mean(2, 0);
561 
562  for (unsigned int i = 0; i < nbPoints; i++)
563  mean += points.at(i);
564  mean /= nbPoints;
565 
566  vpColVector d(nbPoints);
567  for (unsigned int i = 0; i < nbPoints; i++) {
568  vpColVector v(points.at(i) - mean);
569  M.insert(v, 0, i);
570  d[i] = v.sumSquare();
571  }
572 
573  vpColVector x(nbPoints, 1);
574  vpMatrix B(nbPoints, 3);
575  B.insert(M.t(), 0, 0);
576  B.insert(x, 0, 2);
577 
578  vpColVector y = B.pseudoInverse(0) * d;
579 
580  center.resize(2);
581  center[0] = y[0] / 2;
582  center[1] = y[1] / 2;
583 
584  r = sqrt(y[2] + pow(center.frobeniusNorm(), 2));
585 
586  center += mean;
587 
588  return true;
589 }
590 
591 bool fitSphereTo3DPointCloud(const std::vector<vpColVector> &points, vpColVector &center, double &r)
592 {
593  // 2D nonlinear least square fitting (Coope93)
594  unsigned int nbPoints = points.size();
595  if (nbPoints < 3)
596  throw vpException(vpException::ioError, "usGeometryTools::fitCircleTo2DPointCloud: not enough points");
597 
598  // Create data matrix with centered vectors
599  vpMatrix M(4, nbPoints);
600  vpColVector mean(3, 0);
601 
602  for (unsigned int i = 0; i < nbPoints; i++)
603  mean += points.at(i);
604  mean /= nbPoints;
605 
606  vpColVector d(nbPoints);
607  for (unsigned int i = 0; i < nbPoints; i++) {
608  vpColVector v(points.at(i) - mean);
609  M.insert(v, 0, i);
610  d[i] = v.sumSquare();
611  }
612 
613  vpColVector x(nbPoints, 1);
614  vpMatrix B(nbPoints, 4);
615  B.insert(M.t(), 0, 0);
616  B.insert(x, 0, 3);
617 
618  vpColVector y = B.pseudoInverse(0) * d;
619 
620  center.resize(3);
621  center[0] = y[0] / 2;
622  center[1] = y[1] / 2;
623  center[2] = y[2] / 2;
624 
625  r = sqrt(y[3] + pow(center.frobeniusNorm(), 2));
626 
627  center += mean;
628 
629  return true;
630 }
631 
632 } // namespace usGeometryTools
const usPolynomialCurve3D & accessSegment(int i) const
int getNbSegments() const
Parameters setters and getters.
Definition: usBSpline3D.cpp:59
const usPolynomialCurve3D & accessLastSegment() const
vpColVector getPoint(double param) const
Measure curve information.
void defineFromPoints(const std::vector< vpColVector > &points, const std::vector< double > &lengths, int order=3)
double getParametricLength() const
Definition: usBSpline3D.cpp:61
vpColVector getDirection() const
vpColVector getPosition() const
void defineFromPoints(const std::vector< vpColVector > &points, const std::vector< double > &param, unsigned int order=0)
vpColVector getTangent(double parameter) const
vpColVector getPoint(double parameter) const
double getStartParameter() const
vpColVector getEndPoint() const
double getParametricLength() const
double getEndParameter() const
vpColVector getStartPoint() const
VISP_EXPORT bool IsPointInFrontOfPlane(const vpColVector &point, const usOrientedPlane3D &plane)
VISP_EXPORT bool fitSphereTo3DPointCloud(const std::vector< vpColVector > &points, vpColVector &center, double &r)
VISP_EXPORT bool fitCircleTo2DPointCloud(const std::vector< vpColVector > &points, vpColVector &center, double &r)
VISP_EXPORT vpColVector projectPointOnCurve(const vpColVector &point, const usPolynomialCurve3D &poly, double threshold=-1, double *t=nullptr)
VISP_EXPORT vpTranslationVector findPointCloudRelativePosition(std::vector< vpColVector > &P1, std::vector< vpColVector > &P2, const vpRotationMatrix &worldRprobe, double *res=nullptr)
VISP_EXPORT vpColVector getPlaneCurveCrossingPoint(const usPolynomialCurve3D &poly, const usOrientedPlane3D &plane, double threshold, double *t=nullptr)
VISP_EXPORT vpRotationMatrix ICPPointCloudRelativeRotation(std::vector< vpColVector > &P1, std::vector< vpColVector > &P2, double *res=nullptr, vpRotationMatrix *initialGuess=nullptr)
VISP_EXPORT double getPointPlaneDistance(const vpColVector &point, const usOrientedPlane3D &plane)
VISP_EXPORT vpRotationMatrix findPointCloudRelativeRotation(std::vector< vpColVector > &P1, std::vector< vpColVector > &P2, double *res=nullptr)
VISP_EXPORT vpColVector projectPointOnPlane(const vpColVector &point, const usOrientedPlane3D &plane, const vpColVector &direction=vpColVector())
VISP_EXPORT usBSpline3D convertPolynomialToBSpline(const usPolynomialCurve3D &poly, int nbSegments, int order)
VISP_EXPORT usOrientedPlane3D getNormalPlane(const usPolynomialCurve3D &p, double l)
VISP_EXPORT usPolynomialCurve3D convertBSplineToPolynomial(const usBSpline3D &spline, int order)
VISP_EXPORT bool DoesSegmentCrossPlaneDirect(const usPolynomialCurve3D &poly, const usOrientedPlane3D &plane)
VISP_EXPORT vpPoseVector ICPPointCloudRelativePose(std::vector< vpColVector > &P1, std::vector< vpColVector > &P2, double *res=nullptr, vpPoseVector *initialGuess=nullptr)
VISP_EXPORT vpTranslationVector ICPPointCloudRelativePosition(std::vector< vpColVector > &P1, std::vector< vpColVector > &P2, const vpRotationMatrix &worldRprobe, double *res=nullptr, vpTranslationVector *initialGuess=nullptr)
VISP_EXPORT bool DoesSegmentCrossPlane(const usPolynomialCurve3D &poly, const usOrientedPlane3D &plane)
VISP_EXPORT vpPoseVector findPointCloudRelativePose(std::vector< vpColVector > &P1, std::vector< vpColVector > &P2, double *res=nullptr)