33 #include <visp3/ustk_core/usGeometryTools.h>
37 #include <visp3/core/vpException.h>
38 #include <visp3/core/vpMatrix.h>
39 #include <visp3/core/vpRotationMatrix.h>
40 #include <visp3/core/vpTranslationVector.h>
49 return vpColVector::dotProd(d, point - p);
92 double threshold,
double *t)
98 vpColVector Pstart(poly.
getPoint(start));
101 vpColVector Pend(poly.
getPoint(end));
103 double mid = (start + end) / 2;
104 vpColVector Pmid(poly.
getPoint(mid));
107 double d = (Pend - Pstart).frobeniusNorm();
109 while ((sideStart != sideEnd) && (d > threshold)) {
110 if (sideMid == sideStart) {
113 }
else if (sideMid == sideEnd) {
118 mid = (start + end) / 2;
121 d = (Pend - Pstart).frobeniusNorm();
124 if (sideStart == sideEnd)
126 vpException::badValue,
127 "usGeometryTools::getPlaneCurveCrossingPoint(usPolynomialCurve3D): segment and plane do not cross");
153 int mid = (start + end) / 2;
157 if (sideStart == sideEnd)
160 while (end - start > 1) {
161 if (sideMid == sideStart) {
164 }
else if (sideMid == sideEnd) {
169 mid = (start + end) / 2;
175 for (
int i = 0; i < seg; i++)
180 throw vpException(vpException::badValue,
181 "usGeometryTools::getPlaneCurveCrossingPoint(usBSpline3D): spline and plane do not cross");
195 if (direction.getCols() != 3) {
196 return (point - vpColVector::dotProd(point - p, d) * d);
198 vpColVector dp = direction;
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);
204 return (point - vpColVector::dotProd(point - p, d) / cos_theta * dp);
211 if (point.size() != 3)
212 throw vpException(vpException::dimensionError,
"usGeometryTools::projectPointOnCurve: invalid point dimension");
218 threshold = fabs(stop - start) / 1000;
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();
226 if (d0 <= d1 && d0 < d2)
228 else if (d2 < d0 && d2 <= d1)
231 start = (start + middle) / 2;
232 stop = (middle + stop) / 2;
234 middle = (start + stop) / 2;
237 vpColVector P = poly.
getPoint(middle);
247 if (point.size() != 3)
248 throw vpException(vpException::dimensionError,
"usGeometryTools::projectPointOnCurve: invalid point dimension");
251 double min = std::numeric_limits<double>::infinity();
279 if ((P1 - point).sumSquare() < (P2 - point).sumSquare()) {
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));
306 for (
int i = 0; i < nbSegments; i++)
307 l.push_back(l.back() + (p.at(i + 1) - p.at(i)).frobeniusNorm());
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());
334 unsigned int nbPoints = P1.size();
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");
341 vpColVector Mean1(3, 0);
342 vpColVector Mean2(3, 0);
344 for (
unsigned int i = 0; i < nbPoints; i++) {
352 for (
unsigned int i = 0; i < nbPoints; i++) {
353 H += (P1.at(i) - Mean1) * (P2.at(i) - Mean2).t();
360 vpMatrix Rm = V * H.t();
362 for (
int i = 0; i < 3; i++)
367 for (
int i = 0; i < 3; i++) {
368 for (
int j = 0; j < 3; j++) {
373 vpTranslationVector T(Mean2 - R * Mean1);
375 vpPoseVector p(T, R);
377 if (res !=
nullptr) {
379 for (
unsigned int i = 0; i < nbPoints; i++) {
380 *res += (R * P1.at(i) + T - (vpTranslationVector)P2.at(i)).sumSquare();
388 const vpRotationMatrix &worldRprobe,
double *res)
390 unsigned int nbPoints = P1.size();
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");
397 vpColVector Mean1(3, 0);
398 vpColVector Mean2(3, 0);
400 for (
unsigned int i = 0; i < nbPoints; i++) {
407 vpTranslationVector T(Mean2 - worldRprobe * Mean1);
409 if (res !=
nullptr) {
411 for (
unsigned int i = 0; i < nbPoints; i++) {
412 *res += (worldRprobe * P1.at(i) + T - (vpTranslationVector)P2.at(i)).sumSquare();
421 unsigned int nbPoints = P1.size();
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");
430 for (
unsigned int i = 0; i < nbPoints; i++)
431 H += P1.at(i) * P2.at(i).t();
437 vpMatrix Rm = V * H.t();
439 for (
int i = 0; i < 3; i++)
444 for (
int i = 0; i < 3; i++) {
445 for (
int j = 0; j < 3; j++) {
450 if (res !=
nullptr) {
452 for (
unsigned int i = 0; i < nbPoints; i++) {
453 *res += (R * P1.at(i) - P2.at(i)).sumSquare();
461 vpPoseVector *initialGuess)
463 if (P1.size() < 1 || P2.size() < 1)
464 throw vpException(vpException::dimensionError,
465 "usGeometryTools::ICPPointCloudRelativePose: not enough points to match");
467 vpTranslationVector T;
471 T = initialGuess->getTranslationVector();
472 R = initialGuess->getRotationMatrix();
474 vpColVector meanP1(3, 0);
475 for (
unsigned int i = 0; i < P1.size(); i++)
477 meanP1 /= (double)P1.size();
478 vpColVector meanP2(3, 0);
479 for (
unsigned int i = 0; i < P2.size(); i++)
481 meanP2 /= (double)P2.size();
485 vpMatrix dist(P1.size(), P2.size(), 0);
486 std::vector<vpColVector> matchPoint(P1.size(), vpColVector(3));
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();
498 for (
unsigned int i = 0; i < P1.size(); i++) {
500 double min = std::numeric_limits<double>::max();
501 for (
unsigned int j = 0; j < P2.size(); j++) {
502 if (dist[i][j] < min) {
507 matchPoint.at(i) = P2.at(index);
512 T = pose.getTranslationVector();
513 R = pose.getRotationMatrix();
515 resRatio = fabs(residual - resi) / residual;
524 return vpPoseVector(T, R);
528 const vpRotationMatrix &worldRprobe,
double *res,
529 vpTranslationVector *initialGuess)
536 throw vpException(vpException::notImplementedError,
537 "usGeometryTools::ICPPointCloudRelativePosition: non implement yet");
541 vpRotationMatrix *initialGuess)
547 throw vpException(vpException::notImplementedError,
548 "usGeometryTools::ICPPointCloudRelativeRotation: non implement yet");
554 unsigned int nbPoints = points.size();
556 throw vpException(vpException::ioError,
"usGeometryTools::fitCircleTo2DPointCloud: not enough points");
559 vpMatrix M(3, nbPoints);
560 vpColVector mean(2, 0);
562 for (
unsigned int i = 0; i < nbPoints; i++)
563 mean += points.at(i);
566 vpColVector d(nbPoints);
567 for (
unsigned int i = 0; i < nbPoints; i++) {
568 vpColVector v(points.at(i) - mean);
570 d[i] = v.sumSquare();
573 vpColVector x(nbPoints, 1);
574 vpMatrix B(nbPoints, 3);
575 B.insert(M.t(), 0, 0);
578 vpColVector y = B.pseudoInverse(0) * d;
581 center[0] = y[0] / 2;
582 center[1] = y[1] / 2;
584 r = sqrt(y[2] + pow(center.frobeniusNorm(), 2));
594 unsigned int nbPoints = points.size();
596 throw vpException(vpException::ioError,
"usGeometryTools::fitCircleTo2DPointCloud: not enough points");
599 vpMatrix M(4, nbPoints);
600 vpColVector mean(3, 0);
602 for (
unsigned int i = 0; i < nbPoints; i++)
603 mean += points.at(i);
606 vpColVector d(nbPoints);
607 for (
unsigned int i = 0; i < nbPoints; i++) {
608 vpColVector v(points.at(i) - mean);
610 d[i] = v.sumSquare();
613 vpColVector x(nbPoints, 1);
614 vpMatrix B(nbPoints, 4);
615 B.insert(M.t(), 0, 0);
618 vpColVector y = B.pseudoInverse(0) * d;
621 center[0] = y[0] / 2;
622 center[1] = y[1] / 2;
623 center[2] = y[2] / 2;
625 r = sqrt(y[3] + pow(center.frobeniusNorm(), 2));
const usPolynomialCurve3D & accessSegment(int i) const
int getNbSegments() const
Parameters setters and getters.
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
vpColVector getDirection() const
vpColVector getPosition() const
void defineFromPoints(const std::vector< vpColVector > &points, const std::vector< double > ¶m, 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