33 #include <visp3/ustk_core/usPolynomialCurve3D.h>
37 #include <visp3/core/vpException.h>
40 : m_order(0), m_startParameter(0), m_endParameter(1), m_polynomialCoefficients(3, 1, 0)
45 : m_order(curve.m_order), m_startParameter(curve.m_startParameter), m_endParameter(curve.m_endParameter),
46 m_polynomialCoefficients(curve.m_polynomialCoefficients)
63 : m_order(order), m_startParameter(0), m_endParameter(1), m_polynomialCoefficients(3, m_order + 1, 0)
77 int nb_coef = order + 1;
78 int nb_constraints_begin = nb_coef / 2 + nb_coef % 2;
79 int nb_constraints_end = nb_coef / 2;
81 vpColVector startParameter_power(
m_order + 1, 0);
82 vpColVector endParameter_power(
m_order + 1, 0);
83 startParameter_power[0] = 1;
84 endParameter_power[0] = 1;
85 for (
unsigned int i = 1; i <=
m_order; i++) {
87 endParameter_power[i] =
m_endParameter * endParameter_power[i - 1];
90 vpMatrix A(nb_coef, nb_coef, 0);
91 for (
int i = 0; i < nb_constraints_begin; i++) {
92 for (
int j = i; j < nb_coef; j++) {
93 A[i][j] = startParameter_power[j - i];
94 for (
int n = 0; n < i; n++)
98 for (
int i = 0; i < nb_constraints_end; i++) {
99 for (
int j = 0; j < nb_coef; j++) {
100 A[nb_constraints_begin + i][j] = endParameter_power[j - i];
101 for (
int n = 0; n < i; n++)
106 vpMatrix Ainvt = A.inverseByLU().t();
108 vpMatrix B(3, nb_coef);
109 for (
int i = 0; i < nb_constraints_begin; i++) {
110 vpColVector col(3, 0);
111 for (
unsigned int j = nb_constraints_begin; j <=
m_order; j++) {
112 double coef = startParameter_power[j - i];
113 for (
int n = 0; n < i; n++)
119 for (
int i = 0; i < nb_constraints_end; i++) {
120 vpColVector col(3, 0);
121 for (
unsigned int j = nb_constraints_begin; j <=
m_order; j++) {
122 double coef = endParameter_power[j - i];
123 for (
int n = 0; n < i; n++)
127 B.insert(col, 0, nb_constraints_begin + i);
148 if (startParameter <= endParameter) {
165 throw vpException(vpException::badValue,
"usPolynomialCurve3D::setLength: precision should be strictly positive");
167 throw vpException(vpException::badValue,
"usPolynomialCurve3D::setLength: length should be strictly positive");
171 double lMetricPrev = 0;
172 double lParamPrev = 0;
173 double diffMetric = length - lMetric;
175 while (fabs(diffMetric) > length * precision) {
176 double slope = (lParam - lParamPrev) / (lMetric - lMetricPrev);
178 lMetricPrev = lMetric;
182 diffMetric = length - lMetric;
188 vpColVector params(nbCountSeg + 1);
191 for (
int i = 1; i < nbCountSeg + 1; i++)
192 params[i] = params[i - 1] + step;
194 vpMatrix points = this->
getPoints(params);
197 for (
int i = 0; i < nbCountSeg; i++)
198 length += (points.getCol(i) - points.getCol(i + 1)).frobeniusNorm();
204 if (polynomialCoefficients.getCols() < 2)
205 throw vpException(vpException::dimensionError,
206 "usPolynomialCurve3D::setPolynomialCoefficients: empty coefficient matrix");
207 if (polynomialCoefficients.getRows() != 3)
208 throw vpException(vpException::dimensionError,
209 "usPolynomialCurve3D::setPolynomialCoefficients: space dimension should be 3");
211 m_order = polynomialCoefficients.getCols() - 1;
221 for (
unsigned int i = 1; i <
m_order + 1; i++)
222 T[i] = T[i - 1] * parameter;
228 vpMatrix T(
m_order + 1, parameters.size());
229 for (
unsigned int j = 0; j < parameters.size(); j++) {
231 for (
unsigned int i = 1; i <
m_order + 1; i++)
232 T[i][j] = T[i - 1][j] * parameters[j];
246 for (
unsigned int i = 1; i <
m_order + 1; i++) {
261 if (order > 0 && order <=
m_order) {
262 vpColVector factor_coef(
m_order + 1, 0);
263 factor_coef[order] = 1;
264 for (
unsigned int i = order + 1; i <=
m_order; i++)
265 factor_coef[i] = parameter * factor_coef[i - 1];
267 for (
unsigned int i = order; i <=
m_order; i++) {
268 for (
unsigned int n = 0; n < order; n++)
269 factor_coef[i] *= i - n;
281 unsigned int nbPoints = points.size();
283 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromPoints(const "
284 "std::vector<vpColVector> &points, const std::vector<double> "
285 "¶m, unsigned int order): need at least two points to fit");
286 if (param.size() != nbPoints)
287 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromPoints(const "
288 "std::vector<vpColVector> &points, const std::vector<double> "
289 "¶m, unsigned int order): mismatching number of points and "
290 "parametric values");
295 unsigned int nbCoef = order + 1;
297 vpMatrix M(nbCoef, nbCoef, 0);
298 vpMatrix B(nbCoef, 3, 0);
300 unsigned int nb_pow = 2 * nbCoef - 1;
301 vpMatrix t_pow(nbPoints, nb_pow);
302 for (
unsigned int i = 0; i < nbPoints; i++) {
303 double ti = param.at(i);
305 for (
unsigned int j = 1; j < nb_pow; j++) {
306 t_pow[i][j] = ti * t_pow[i][j - 1];
310 for (
unsigned int line = 0; line < nbCoef; line++) {
311 for (
unsigned int i = 0; i < nbPoints; i++) {
312 for (
unsigned int j = 0; j < nbCoef; j++) {
313 M[line][j] += t_pow[i][line + j];
315 for (
unsigned int dim = 0; dim < 3; dim++) {
316 B[line][dim] += t_pow[i][line] * points.at(i)[dim];
323 if (nbCoef > nbPoints)
324 A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
326 A = M.inverseByCholeskyLapack() * B;
327 }
catch (std::exception &e) {
328 throw vpException(vpException::fatalError,
"usPolynomialCurve3D::defineFromPoints(const std::vector<vpColVector> "
329 "&points, const std::vector<double> ¶m, unsigned int order): %s",
339 unsigned int nbPoints = points.getCols();
341 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromPoints(const "
342 "std::vector<vpColVector> &points, const std::vector<double> "
343 "¶m, unsigned int order): need at least two points to fit");
344 if (param.size() != nbPoints)
345 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromPoints(const "
346 "std::vector<vpColVector> &points, const std::vector<double> "
347 "¶m, unsigned int order): mismatching number of points and "
348 "parametric values");
353 unsigned int nbCoef = order + 1;
355 vpMatrix M(nbCoef, nbCoef, 0);
356 vpMatrix B(nbCoef, 3, 0);
358 unsigned int nb_pow = 2 * nbCoef - 1;
359 vpMatrix t_pow(nbPoints, nb_pow);
360 for (
unsigned int i = 0; i < nbPoints; i++) {
361 double ti = param[i];
363 for (
unsigned int j = 1; j < nb_pow; j++) {
364 t_pow[i][j] = ti * t_pow[i][j - 1];
368 for (
unsigned int line = 0; line < nbCoef; line++) {
369 for (
unsigned int i = 0; i < nbPoints; i++) {
370 for (
unsigned int j = 0; j < nbCoef; j++) {
371 M[line][j] += t_pow[i][line + j];
373 for (
unsigned int dim = 0; dim < 3; dim++) {
374 B[line][dim] += t_pow[i][line] * points[dim][i];
381 if (nbCoef > nbPoints)
382 A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
384 A = M.inverseByCholeskyLapack() * B;
385 }
catch (std::exception &e) {
386 throw vpException(vpException::fatalError,
"usPolynomialCurve3D::defineFromPoints(const std::vector<vpColVector> "
387 "&points, const std::vector<double> ¶m, unsigned int order): %s",
397 unsigned int nbPoints = points.size();
399 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromPointsAuto(const "
400 "std::vector<vpColVector> &points, unsigned int order): need at "
401 "least two points to fit");
409 for (
unsigned int i = 0; i < nbPoints; i++) {
410 for (
unsigned int j = 0; j < i; j++) {
411 double v = (points.at(i) - points.at(j)).sumSquare();
419 vpColVector dir((points.at(max_i) - points.at(max_j)).normalize());
426 unsigned int nbPoints = points.getCols();
428 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromPointsAuto(const vpMatrix &points, "
429 "unsigned int order): need at least two points to fit");
437 for (
unsigned int i = 0; i < nbPoints; i++) {
438 for (
unsigned int j = 0; j < i; j++) {
439 double v = (points.getCol(i) - points.getCol(j)).sumSquare();
447 vpColVector dir((points.getCol(max_i) - points.getCol(max_j)).normalize());
455 unsigned int nbPoints = points.size();
457 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromPointsAuto(const "
458 "std::vector<vpColVector> &points, const vpColVector &direction, "
459 "unsigned int order): need at least two points to fit");
464 std::vector<double> t(nbPoints, 0);
466 double min = std::numeric_limits<double>::max();
467 for (
unsigned int i = 0; i < nbPoints; i++) {
468 t.at(i) = vpColVector::dotProd(points.at(i), direction);
472 for (
unsigned int i = 0; i < nbPoints; i++)
475 std::vector<int> index(nbPoints);
476 for (
unsigned int i = 0; i < nbPoints; i++)
479 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
481 std::vector<vpColVector> newPoints(nbPoints);
482 std::vector<double> interLength(nbPoints - 1);
483 newPoints.front() = points.at(index[0]);
485 double newLength = 0;
486 for (
unsigned int i = 1; i < nbPoints; i++) {
487 newPoints.at(i) = points.at(index[i]);
488 interLength.at(i - 1) = sqrt(vpMath::sqr(newPoints.at(i)[0] - newPoints.at(i - 1)[0]) +
489 vpMath::sqr(newPoints.at(i)[1] - newPoints.at(i - 1)[1]) +
490 +vpMath::sqr(newPoints.at(i)[2] - newPoints.at(i - 1)[2]));
491 newLength += interLength.at(i - 1);
493 double scaling = oldLength / newLength;
494 std::vector<double> param(nbPoints);
496 for (
unsigned int i = 1; i < nbPoints; i++)
497 param.at(i) = param.at(i - 1) + scaling * interLength.at(i - 1);
504 unsigned int nbPoints = points.getCols();
506 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromPointsAuto(const vpMatrix &points, "
507 "const vpColVector &direction, unsigned int order): need at least "
508 "two points to fit");
513 std::vector<double> t(nbPoints, 0);
515 double min = std::numeric_limits<double>::max();
516 for (
unsigned int i = 0; i < nbPoints; i++) {
517 t.at(i) = vpColVector::dotProd(points.getCol(i), direction);
521 for (
unsigned int i = 0; i < nbPoints; i++)
524 std::vector<int> index(nbPoints);
525 for (
unsigned int i = 0; i < nbPoints; i++)
528 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
530 vpMatrix newPoints(3, nbPoints);
531 vpColVector interLength(nbPoints - 1);
532 for (
unsigned int j = 0; j < 3; j++)
533 newPoints[j][0] = points[j][index[0]];
535 double newLength = 0;
536 for (
unsigned int i = 1; i < nbPoints; i++) {
537 for (
unsigned int j = 0; j < 3; j++)
538 newPoints[j][i] = points[j][index[i]];
540 sqrt(vpMath::sqr(newPoints[0][i] - newPoints[0][i - 1]) + vpMath::sqr(newPoints[1][i] - newPoints[1][i - 1]) +
541 vpMath::sqr(newPoints[2][i] - newPoints[2][i - 1]));
542 newLength += interLength[i - 1];
544 double scaling = oldLength / newLength;
545 vpColVector param(nbPoints);
547 for (
unsigned int i = 1; i < nbPoints; i++)
548 param[i] = param[i - 1] + scaling * interLength[i - 1];
554 const std::vector<double> ¶m,
const std::vector<double> &weights,
557 unsigned int nbPoints = points.size();
559 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPoints(const "
560 "std::vector<vpColVector> &points, const std::vector<double> "
561 "¶m, const std::vector<double> &weights, unsigned int order): "
562 "need at least two points to fit");
563 if (param.size() != nbPoints)
564 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPoints(const "
565 "std::vector<vpColVector> &points, const std::vector<double> "
566 "¶m, const std::vector<double> &weights, unsigned int order): "
567 "mismatching number of points and parametric values or weights");
568 if (weights.size() != nbPoints)
569 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPoints(const "
570 "std::vector<vpColVector> &points, const std::vector<double> "
571 "¶m, const std::vector<double> &weights, unsigned int order): "
572 "mismatching number of points and weights");
577 unsigned int nbCoef = order + 1;
579 vpMatrix M(nbCoef, nbCoef, 0);
580 vpMatrix B(nbCoef, 3, 0);
582 unsigned int nb_pow = 2 * nbCoef - 1;
583 vpMatrix t_pow(nbPoints, nb_pow);
584 for (
unsigned int i = 0; i < nbPoints; i++) {
585 double ti = param.at(i);
586 t_pow[i][0] = weights.at(i);
587 for (
unsigned int j = 1; j < nb_pow; j++) {
588 t_pow[i][j] = ti * t_pow[i][j - 1];
592 for (
unsigned int line = 0; line < nbCoef; line++) {
593 for (
unsigned int i = 0; i < nbPoints; i++) {
594 for (
unsigned int j = 0; j < nbCoef; j++) {
595 M[line][j] += t_pow[i][line + j];
597 for (
unsigned int dim = 0; dim < 3; dim++) {
598 B[line][dim] += t_pow[i][line] * points.at(i)[dim];
605 A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
606 }
catch (std::exception &e) {
607 throw vpException(vpException::fatalError,
"usPolynomialCurve3D::defineFromWeightedPoints(const vpMatrix &points, "
608 "const vpColVector ¶m, const vpColVector &weights, unsigned int "
618 const vpColVector &weights,
unsigned int order)
620 unsigned int nbPoints = points.getCols();
622 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPoints(const vpMatrix "
623 "&points, const vpColVector ¶m, const vpColVector &weights, "
624 "unsigned int order): need at least two points to fit");
625 if (param.size() != nbPoints)
626 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPoints(const vpMatrix "
627 "&points, const vpColVector ¶m, const vpColVector &weights, "
628 "unsigned int order): mismatching number of points and parametric "
629 "values or weights");
630 if (weights.size() != nbPoints)
631 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPoints(const vpMatrix "
632 "&points, const vpColVector ¶m, const vpColVector &weights, "
633 "unsigned int order): mismatching number of points and weights");
638 unsigned int nbCoef = order + 1;
640 vpMatrix M(nbCoef, nbCoef, 0);
641 vpMatrix B(nbCoef, 3, 0);
643 unsigned int nb_pow = 2 * nbCoef - 1;
644 vpMatrix t_pow(nbPoints, nb_pow);
645 for (
unsigned int i = 0; i < nbPoints; i++) {
646 double ti = param[i];
647 t_pow[i][0] = weights[i];
648 for (
unsigned int j = 1; j < nb_pow; j++) {
649 t_pow[i][j] = ti * t_pow[i][j - 1];
653 for (
unsigned int line = 0; line < nbCoef; line++) {
654 for (
unsigned int i = 0; i < nbPoints; i++) {
655 for (
unsigned int j = 0; j < nbCoef; j++) {
656 M[line][j] += t_pow[i][line + j];
658 for (
unsigned int dim = 0; dim < 3; dim++) {
659 B[line][dim] += t_pow[i][line] * points[dim][i];
666 A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
667 }
catch (std::exception &e) {
668 throw vpException(vpException::fatalError,
"usPolynomialCurve3D::defineFromWeightedPoints(const vpMatrix &points, "
669 "const vpColVector ¶m, const vpColVector &weights, unsigned int "
679 const std::vector<double> &weights,
unsigned int order)
681 unsigned int nbPoints = points.size();
683 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPointsAuto(const "
684 "std::vector<vpColVector> &points, const std::vector<double> "
685 "&weights, unsigned int order): need at least two points to fit");
686 if (weights.size() != nbPoints)
687 throw vpException(vpException::dimensionError,
688 "usPolynomialCurve3D::defineFromWeightedPointsAuto(const std::vector<vpColVector> &points, const "
689 "std::vector<double> &weights, unsigned int order): mismatching number of points and weights");
694 std::vector<double> t(nbPoints, 0);
696 vpColVector Pmean(3, 0);
697 for (
unsigned int i = 0; i < nbPoints; i++)
698 Pmean += points.at(i);
701 vpMatrix M(nbPoints, 3);
702 for (
unsigned int i = 0; i < nbPoints; i++)
703 for (
int j = 0; j < 3; j++)
704 M[i][j] = points.at(i)[j] - Pmean[j];
711 vpColVector dir(V.getCol(0));
712 double min = std::numeric_limits<double>::max();
713 for (
unsigned int i = 0; i < nbPoints; i++) {
714 t.at(i) = vpColVector::dotProd(points.at(i), dir);
718 for (
unsigned int i = 0; i < nbPoints; i++)
721 std::vector<int> index(nbPoints);
722 for (
unsigned int i = 0; i < nbPoints; i++)
725 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
727 std::vector<vpColVector> newPoints(nbPoints);
728 std::vector<double> newWeights(nbPoints);
729 std::vector<double> interLength(nbPoints - 1);
730 newPoints.front() = points.at(index[0]);
731 newWeights.front() = weights.at(index[0]);
733 double newLength = 0;
734 for (
unsigned int i = 1; i < nbPoints; i++) {
735 newPoints.at(i) = points.at(index[i]);
736 newWeights.at(i) = weights.at(index[i]);
737 interLength.at(i - 1) = sqrt(vpMath::sqr(newPoints.at(i)[0] - newPoints.at(i - 1)[0]) +
738 vpMath::sqr(newPoints.at(i)[1] - newPoints.at(i - 1)[1]) +
739 vpMath::sqr(newPoints.at(i)[2] - newPoints.at(i - 1)[2]));
740 newLength += interLength.at(i - 1);
742 double scaling = oldLength / newLength;
743 std::vector<double> param(nbPoints);
745 for (
unsigned int i = 1; i < nbPoints; i++)
746 param.at(i) = param.at(i - 1) + scaling * interLength.at(i - 1);
754 unsigned int nbPoints = points.getCols();
756 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPointsAuto(const vpMatrix "
757 "&points, const vpColVector &weights, unsigned int order): need at "
758 "least two points to fit");
759 if (weights.size() != nbPoints)
760 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPointsAuto(const vpMatrix "
761 "&points, const vpColVector &weights, unsigned int order): "
762 "mismatching number of points and weights");
767 std::vector<double> t(nbPoints, 0);
769 vpColVector Pmean(3, 0);
770 for (
unsigned int i = 0; i < nbPoints; i++)
771 Pmean += points.getCol(i);
774 vpMatrix M(nbPoints, 3);
775 for (
unsigned int i = 0; i < nbPoints; i++)
776 for (
int j = 0; j < 3; j++)
777 M[i][j] = points[j][i] - Pmean[j];
784 vpColVector dir(V.getCol(0));
785 double min = std::numeric_limits<double>::max();
786 for (
unsigned int i = 0; i < nbPoints; i++) {
787 t.at(i) = vpColVector::dotProd(points.getCol(i), dir);
791 for (
unsigned int i = 0; i < nbPoints; i++)
794 std::vector<int> index(nbPoints);
795 for (
unsigned int i = 0; i < nbPoints; i++)
798 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
800 vpMatrix newPoints(3, nbPoints);
801 vpColVector newWeights(nbPoints);
802 vpColVector interLength(nbPoints - 1);
803 for (
unsigned int j = 0; j < 3; j++)
804 newPoints[j][0] = points[j][index[0]];
805 newWeights[0] = weights[index[0]];
807 double newLength = 0;
808 for (
unsigned int i = 1; i < nbPoints; i++) {
809 for (
unsigned int j = 0; j < 3; j++)
810 newPoints[j][i] = points[j][index[i]];
811 newWeights[i] = weights[index[i]];
813 sqrt(vpMath::sqr(newPoints[0][i] - newPoints[0][i - 1]) + vpMath::sqr(newPoints[1][i] - newPoints[1][i - 1]) +
814 vpMath::sqr(newPoints[2][i] - newPoints[2][i - 1]));
815 newLength += interLength[i - 1];
817 double scaling = oldLength / newLength;
818 vpColVector param(nbPoints);
820 for (
unsigned int i = 1; i < nbPoints; i++)
821 param[i] = param[i - 1] + scaling * interLength[i - 1];
827 const std::vector<double> &weights,
const vpColVector &direction,
830 unsigned int nbPoints = points.size();
832 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPointsAuto(const "
833 "std::vector<vpColVector> &points, const std::vector<double> "
834 "&weights, const vpColVector &direction, unsigned int order): need "
835 "at least two points to fit");
836 if (weights.size() != nbPoints)
837 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPointsAuto(const "
838 "std::vector<vpColVector> &points, const std::vector<double> "
839 "&weights, const vpColVector &direction, unsigned int order): "
840 "mismatching number of points and weights");
845 std::vector<double> t(nbPoints, 0);
847 double min = std::numeric_limits<double>::max();
848 for (
unsigned int i = 0; i < nbPoints; i++) {
849 t.at(i) = vpColVector::dotProd(points.at(i), direction);
853 for (
unsigned int i = 0; i < nbPoints; i++)
856 std::vector<int> index(nbPoints);
857 for (
unsigned int i = 0; i < nbPoints; i++)
860 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
862 std::vector<vpColVector> newPoints(nbPoints);
863 std::vector<double> newWeights(nbPoints);
864 std::vector<double> interLength(nbPoints - 1);
865 newPoints.front() = points.at(index[0]);
866 newWeights.front() = weights.at(index[0]);
868 double newLength = 0;
869 for (
unsigned int i = 1; i < nbPoints; i++) {
870 newPoints.at(i) = points.at(index[i]);
871 newWeights.at(i) = weights.at(index[i]);
872 interLength.at(i - 1) = sqrt(vpMath::sqr(newPoints.at(i)[0] - newPoints.at(i - 1)[0]) +
873 vpMath::sqr(newPoints.at(i)[1] - newPoints.at(i - 1)[1]) +
874 vpMath::sqr(newPoints.at(i)[2] - newPoints.at(i - 1)[2]));
875 newLength += interLength.at(i - 1);
877 double scaling = oldLength / newLength;
878 std::vector<double> param(nbPoints);
880 for (
unsigned int i = 1; i < nbPoints; i++)
881 param.at(i) = param.at(i - 1) + scaling * interLength.at(i - 1);
887 const vpColVector &direction,
unsigned int order)
889 unsigned int nbPoints = points.getCols();
891 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPointsAuto(const vpMatrix "
892 "&points, const vpColVector &weights, const vpColVector &direction, "
893 "unsigned int order): need at least two points to fit");
894 if (weights.size() != nbPoints)
895 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::defineFromWeightedPointsAuto(const vpMatrix "
896 "&points, const vpColVector &weights, const vpColVector &direction, "
897 "unsigned int order): mismatching number of points and weights");
902 std::vector<double> t(nbPoints, 0);
904 double min = std::numeric_limits<double>::max();
905 for (
unsigned int i = 0; i < nbPoints; i++) {
906 t.at(i) = vpColVector::dotProd(points.getCol(i), direction);
910 for (
unsigned int i = 0; i < nbPoints; i++)
913 std::vector<int> index(nbPoints);
914 for (
unsigned int i = 0; i < nbPoints; i++)
917 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
919 vpMatrix newPoints(3, nbPoints);
920 vpColVector newWeights(nbPoints);
921 vpColVector interLength(nbPoints - 1);
922 for (
unsigned int j = 0; j < 3; j++)
923 newPoints[j][0] = points[j][index[0]];
924 newWeights[0] = weights[index[0]];
926 double newLength = 0;
927 for (
unsigned int i = 1; i < nbPoints; i++) {
928 for (
unsigned int j = 0; j < 3; j++)
929 newPoints[j][i] = points[j][index[i]];
930 newWeights[i] = weights[index[i]];
932 sqrt(vpMath::sqr(newPoints[0][i] - newPoints[0][i - 1]) + vpMath::sqr(newPoints[1][i] - newPoints[1][i - 1]) +
933 vpMath::sqr(newPoints[2][i] - newPoints[2][i - 1]));
934 newLength += interLength[i - 1];
936 double scaling = oldLength / newLength;
937 vpColVector param(nbPoints);
939 for (
unsigned int i = 1; i < nbPoints; i++)
940 param[i] = param[i - 1] + scaling * interLength[i - 1];
950 double norm = dX_dl.frobeniusNorm();
951 double curvature = vpColVector::crossProd(dX_dl, dX2_dl2).frobeniusNorm() / pow(norm, 3);
957 vpColVector &direction3D)
const
977 double step = (end - start) / (nbPoints - 1);
978 vpColVector params(nbPoints);
980 for (
int i = 1; i < nbPoints; i++)
981 params[i] = params[i - 1] + step;
984 vpRowVector mean(3, 0);
986 for (
int i = 0; i < nbPoints; i++)
990 for (
int i = 0; i < nbPoints; i++) {
1005 U.resize(nbPoints, 2,
false);
1007 S.resize(2, 2,
false);
1012 vpColVector d(nbPoints);
1013 for (
int i = 0; i < nbPoints; i++) {
1014 d[i] = pow(P.t().getCol(i).frobeniusNorm(), 2);
1017 vpColVector x(nbPoints, 1);
1018 vpMatrix B(nbPoints, 3);
1022 vpColVector y = B.pseudoInverse(0) * d;
1024 vpColVector center(2);
1025 center[0] = y[0] / 2;
1026 center[1] = y[1] / 2;
1028 double r = sqrt(y[2] + pow(center.frobeniusNorm(), 2));
1039 if (direction3D.size() == 3) {
1040 direction3D = V.getCol(2);
1041 }
else if (direction3D.size() == 4) {
1042 direction3D.insert(0, V.getCol(2));
1046 if (center3D.size() == 3) {
1047 V.resize(3, 2,
false);
1048 center3D = V * center;
1049 }
else if (center3D.size() == 4) {
1050 V.resize(3, 2,
false);
1051 center3D.insert(0, V * center + mean.t());
1075 throw vpException(vpException::badValue,
"usPolynomialCurve3D::getMeanAxisDeviation: should use at least 2 segment "
1076 "to compute approximate deviation from axis");
1078 vpColVector params(nbCountSeg + 1);
1081 for (
int i = 1; i < nbCountSeg + 1; i++)
1082 params[i] = params[i - 1] + step;
1084 vpMatrix points(this->
getPoints(params));
1086 vpColVector axis = (points.getCol(nbCountSeg) - points.getCol(0)).normalize();
1087 vpColVector origin = points.getCol(0);
1088 double meanDeviation = 0;
1089 for (
int i = 0; i < nbCountSeg + 1; i++)
1090 meanDeviation += vpColVector::dotProd(points.getCol(i) - origin, axis);
1092 meanDeviation /= nbCountSeg + 1;
1093 return meanDeviation;
1098 if (controlPoints.getRows() != 3)
1099 throw vpException(vpException::dimensionError,
1100 "usPolynomialCurve3D::setControlPoints(const vpMatrix&): invalid points dimension, should be 3");
1101 if (controlPoints.getCols() < 2)
1103 vpException::dimensionError,
1104 "usPolynomialCurve3D::setControlPoints(const vpMatrix&): invalid number of points, should greater than 1");
1106 vpColVector direction = controlPoints.getCol(controlPoints.getCols() - 1) - controlPoints.getCol(0);
1113 memcpy(M.data, *controlPoints, M.size() *
sizeof(
double));
1122 vpColVector params(
m_order + 1);
1125 for (
unsigned int i = 1; i <
m_order + 1; i++)
1126 params[i] = params[i - 1] + step;
1133 int nbRenderingPoints = (
m_order < 2) ? 2 : 10;
1134 vpColVector params(nbRenderingPoints);
1137 for (
int i = 1; i < nbRenderingPoints; i++)
1138 params[i] = params[i - 1] + step;
1145 unsigned int order1 = n1.
getOrder();
1146 unsigned int order2 = n2.
getOrder();
1147 vpMatrix coords1(order1, 50);
1148 vpMatrix coords2(order2, 50);
1149 for (
unsigned int j = 0; j < 50; ++j) {
1150 coords1[0][j] = 1.0;
1151 coords2[0][j] = 1.0;
1152 double t =
static_cast<double>(j) / 49.0;
1153 for (
unsigned int i = 1; i < order1; ++i)
1154 coords1[i][j] = coords1[i - 1][j] * t;
1155 for (
unsigned int i = 1; i < order2; ++i)
1156 coords2[i][j] = coords2[i - 1][j] * t;
1160 double distance = 0.0;
1161 for (
unsigned int i = 0; i < 50; ++i)
1162 distance += (p1.getCol(i) - p2.getCol(i)).frobeniusNorm();
1189 if (startParameter == endParameter)
1190 throw vpException(vpException::dimensionError,
"usPolynomialCurve3D::changeCoefficientsToFitBoundaries(double "
1191 "startParameter, double endParameter): new parametric boundaries "
1192 "should be different");
1195 vpColVector beta_pow(
m_order + 1);
1197 for (
unsigned int i = 1; i <=
m_order; i++)
1198 beta_pow[i] = beta * beta_pow[i - 1];
1201 vpColVector alpha_pow(
m_order + 1);
1203 for (
unsigned int i = 1; i <=
m_order; i++)
1204 alpha_pow[i] = alpha * alpha_pow[i - 1];
1208 for (
unsigned int i = 1; i <=
m_order; i++) {
1210 for (
unsigned int j = 1; j <= i; j++) {
1211 M[i][j] = M[i - 1][j - 1] + M[i - 1][j];
1215 for (
unsigned int i = 1; i <=
m_order; i++) {
1216 for (
unsigned int j = 0; j <= i; j++) {
1217 M[i][j] *= alpha_pow[j] * beta_pow[i - j];
1238 vpMatrix R(H.getRotationMatrix());
1240 for (
int i = 0; i < 3; i++)
1248 this->
move(vpHomogeneousMatrix(x, y, z, tx, ty, tz));
1255 s <<
"usPolynomialCurve3D\n";
1257 for (
int i = 0; i < 3; i++) {
1258 for (
unsigned int j = 0; j < seg.
m_order + 1; j++)
1272 if (c !=
"usPolynomialCurve3D") {
1273 vpException e(vpException::ioError,
1274 "operator>>(std::istream&, Polynomial3D&): Stream does not contain usPolynomialCurve3D data");
1279 for (
unsigned int i = 0; i < 3; i++)
1280 for (
unsigned int j = 0; j < seg.
m_order + 1; j++)
1290 s.write(
"usPolynomialCurve3D", 20);
1291 s.write((
char *)&(seg.
m_order),
sizeof(
int));
1292 for (
unsigned int i = 0; i < 3; i++)
1293 for (
unsigned int j = 0; j < seg.
m_order + 1; j++)
1305 if (strcmp(c,
"usPolynomialCurve3D")) {
1306 vpException e(vpException::ioError,
1307 "operator>>=(std::istream&, Polynomial3D&): Stream does not contain usPolynomialCurve3D data");
1310 s.read((
char *)&(seg.
m_order),
sizeof(
int));
1312 for (
unsigned int i = 0; i < 3; i++)
1313 for (
unsigned int j = 0; j < seg.
m_order + 1; j++)
vpColVector getDerivative(double parameter, unsigned int order) const
virtual ~usPolynomialCurve3D()
void defineFromPoints(const std::vector< vpColVector > &points, const std::vector< double > ¶m, unsigned int order=0)
vpMatrix getControlPoints() const
vpColVector getStartTangent() const
vpMatrix getRenderingPoints() const
usPolynomialCurve3D getSubPolynomialCurve(double startParameter, double endParameter) const
static double curveDistance(const usPolynomialCurve3D &n1, const usPolynomialCurve3D &n2)
vpMatrix m_polynomialCoefficients
usPolynomialCurve3D getNewOrderPolynomialCurve(unsigned int order) const
void setStartParameter(double startParameter)
double getLength(int nbCountSeg=50) const
void defineFromWeightedPoints(const std::vector< vpColVector > &points, const std::vector< double > ¶m, const std::vector< double > &weights, unsigned int order=0)
vpColVector getTangent(double parameter) const
unsigned int getOrder() const
vpColVector getPoint(double parameter) const
double getMeanAxisDeviation(int nbCountSeg=50) const
double getStartParameter() const
vpMatrix getPoints(const vpColVector ¶meters) const
void setParametricLength(double length)
void setPolynomialCoefficients(const vpMatrix &polynomialCoefficients)
vpColVector getEndPoint() const
vpMatrix getPolynomialCoefficients() const
void setLength(double length, double precision=1e-4)
void setOrder(unsigned int order)
void move(const vpHomogeneousMatrix &H)
vpColVector getEndTangent() const
void defineFromWeightedPointsAuto(const std::vector< vpColVector > &points, const std::vector< double > &weights, unsigned int order=0)
void changeCoefficientsToFitMetricLength()
void setControlPoints(const vpMatrix &controlPoints)
void defineFromPointsAuto(const std::vector< vpColVector > &points, unsigned int order=0)
double getCurvatureFromShape(double start, double end, vpColVector ¢er3D, vpColVector &direction3D) const
double getParametricLength() const
void changeCoefficientsToFitBoundaries(double startParameter, double endParameter)
void setEndParameter(double endParameter)
const usPolynomialCurve3D & operator=(const usPolynomialCurve3D &curve)
double getEndParameter() const
vpColVector getStartPoint() const
void setBoundaries(double startParameter, double endParamter)
double getCurvature(double param) const