34 #include <visp3/ustk_core/usPolynomialCurve2D.h>
38 #include <visp3/core/vpException.h>
41 : m_order(0), m_startParameter(0), m_endParameter(1), m_polynomialCoefficients(2, 1, 0)
46 : m_order(curve.m_order), m_startParameter(curve.m_startParameter), m_endParameter(curve.m_endParameter),
47 m_polynomialCoefficients(curve.m_polynomialCoefficients)
64 : m_order(order), m_startParameter(0), m_endParameter(1), m_polynomialCoefficients(2, m_order + 1, 0)
78 int nb_coef = order + 1;
79 int nb_constraints_begin = nb_coef / 2 + nb_coef % 2;
80 int nb_constraints_end = nb_coef / 2;
82 vpColVector startParameter_power(
m_order + 1, 0);
83 vpColVector endParameter_power(
m_order + 1, 0);
84 startParameter_power[0] = 1;
85 endParameter_power[0] = 1;
86 for (
unsigned int i = 1; i <=
m_order; i++) {
88 endParameter_power[i] =
m_endParameter * endParameter_power[i - 1];
91 vpMatrix A(nb_coef, nb_coef, 0);
92 for (
int i = 0; i < nb_constraints_begin; i++) {
93 for (
int j = i; j < nb_coef; j++) {
94 A[i][j] = startParameter_power[j - i];
95 for (
int n = 0; n < i; n++)
99 for (
int i = 0; i < nb_constraints_end; i++) {
100 for (
int j = 0; j < nb_coef; j++) {
101 A[nb_constraints_begin + i][j] = endParameter_power[j - i];
102 for (
int n = 0; n < i; n++)
107 vpMatrix Ainvt = A.inverseByLU().t();
109 vpMatrix B(2, nb_coef);
110 for (
int i = 0; i < nb_constraints_begin; i++) {
111 vpColVector col(2, 0);
112 for (
unsigned int j = nb_constraints_begin; j <=
m_order; j++) {
113 double coef = startParameter_power[j - i];
114 for (
int n = 0; n < i; n++)
120 for (
int i = 0; i < nb_constraints_end; i++) {
121 vpColVector col(2, 0);
122 for (
unsigned int j = nb_constraints_begin; j <=
m_order; j++) {
123 double coef = endParameter_power[j - i];
124 for (
int n = 0; n < i; n++)
128 B.insert(col, 0, nb_constraints_begin + i);
149 if (startParameter <= endParameter) {
166 throw vpException(vpException::badValue,
"usPolynomialCurve2D::setLength: precision should be strictly positive");
168 throw vpException(vpException::badValue,
"usPolynomialCurve2D::setLength: length should be strictly positive");
172 double lMetricPrev = 0;
173 double lParamPrev = 0;
174 double diffMetric = length - lMetric;
176 while (fabs(diffMetric) > length * precision) {
177 double slope = (lParam - lParamPrev) / (lMetric - lMetricPrev);
179 lMetricPrev = lMetric;
183 diffMetric = length - lMetric;
189 vpColVector params(nbCountSeg + 1);
192 for (
int i = 1; i < nbCountSeg + 1; i++)
193 params[i] = params[i - 1] + step;
195 vpMatrix points = this->
getPoints(params);
198 for (
int i = 0; i < nbCountSeg; i++)
199 length += (points.getCol(i) - points.getCol(i + 1)).frobeniusNorm();
205 if (polynomialCoefficients.getCols() < 2)
206 throw vpException(vpException::dimensionError,
207 "usPolynomialCurve2D::setPolynomialCoefficients: empty coefficient matrix");
208 if (polynomialCoefficients.getRows() != 2)
209 throw vpException(vpException::dimensionError,
210 "usPolynomialCurve2D::setPolynomialCoefficients: space dimension should be 2");
212 m_order = polynomialCoefficients.getCols() - 1;
222 for (
unsigned int i = 1; i <
m_order + 1; i++)
223 T[i] = T[i - 1] * parameter;
229 vpMatrix T(
m_order + 1, parameters.size());
230 for (
unsigned int j = 0; j < parameters.size(); j++) {
232 for (
unsigned int i = 1; i <
m_order + 1; i++)
233 T[i][j] = T[i - 1][j] * parameters[j];
247 for (
unsigned int i = 1; i <
m_order + 1; i++) {
262 if (order > 0 && order <=
m_order) {
263 vpColVector factor_coef(
m_order + 1, 0);
264 factor_coef[order] = 1;
265 for (
unsigned int i = order + 1; i <=
m_order; i++)
266 factor_coef[i] = parameter * factor_coef[i - 1];
268 for (
unsigned int i = order; i <=
m_order; i++) {
269 for (
unsigned int n = 0; n < order; n++)
270 factor_coef[i] *= i - n;
282 unsigned int nbPoints = points.size();
284 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromPoints(const "
285 "std::vector<vpColVector> &points, const std::vector<double> "
286 "¶m, unsigned int order): need at least two points to fit");
287 if (param.size() != nbPoints)
288 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromPoints(const "
289 "std::vector<vpColVector> &points, const std::vector<double> "
290 "¶m, unsigned int order): mismatching number of points and "
291 "parametric values");
296 unsigned int nbCoef = order + 1;
298 vpMatrix M(nbCoef, nbCoef, 0);
299 vpMatrix B(nbCoef, 2, 0);
301 unsigned int nb_pow = 2 * nbCoef - 1;
302 vpMatrix t_pow(nbPoints, nb_pow);
303 for (
unsigned int i = 0; i < nbPoints; i++) {
304 double ti = param.at(i);
306 for (
unsigned int j = 1; j < nb_pow; j++) {
307 t_pow[i][j] = ti * t_pow[i][j - 1];
311 for (
unsigned int line = 0; line < nbCoef; line++) {
312 for (
unsigned int i = 0; i < nbPoints; i++) {
313 for (
unsigned int j = 0; j < nbCoef; j++) {
314 M[line][j] += t_pow[i][line + j];
316 for (
unsigned int dim = 0; dim < 2; dim++) {
317 B[line][dim] += t_pow[i][line] * points.at(i)[dim];
324 if (nbCoef > nbPoints)
325 A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
327 A = M.inverseByCholeskyLapack() * B;
328 }
catch (std::exception &e) {
329 throw vpException(vpException::fatalError,
"usPolynomialCurve2D::defineFromPoints(const std::vector<vpColVector> "
330 "&points, const std::vector<double> ¶m, unsigned int order): %s",
340 unsigned int nbPoints = points.getCols();
342 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromPoints(const "
343 "std::vector<vpColVector> &points, const std::vector<double> "
344 "¶m, unsigned int order): need at least two points to fit");
345 if (param.size() != nbPoints)
346 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromPoints(const "
347 "std::vector<vpColVector> &points, const std::vector<double> "
348 "¶m, unsigned int order): mismatching number of points and "
349 "parametric values");
354 unsigned int nbCoef = order + 1;
356 vpMatrix M(nbCoef, nbCoef, 0);
357 vpMatrix B(nbCoef, 2, 0);
359 unsigned int nb_pow = 2 * nbCoef - 1;
360 vpMatrix t_pow(nbPoints, nb_pow);
361 for (
unsigned int i = 0; i < nbPoints; i++) {
362 double ti = param[i];
364 for (
unsigned int j = 1; j < nb_pow; j++) {
365 t_pow[i][j] = ti * t_pow[i][j - 1];
369 for (
unsigned int line = 0; line < nbCoef; line++) {
370 for (
unsigned int i = 0; i < nbPoints; i++) {
371 for (
unsigned int j = 0; j < nbCoef; j++) {
372 M[line][j] += t_pow[i][line + j];
374 for (
unsigned int dim = 0; dim < 2; dim++) {
375 B[line][dim] += t_pow[i][line] * points[dim][i];
382 if (nbCoef > nbPoints)
383 A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
385 A = M.inverseByCholeskyLapack() * B;
386 }
catch (std::exception &e) {
387 throw vpException(vpException::fatalError,
"usPolynomialCurve2D::defineFromPoints(const std::vector<vpColVector> "
388 "&points, const std::vector<double> ¶m, unsigned int order): %s",
398 unsigned int nbPoints = points.size();
400 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromPointsAuto(const "
401 "std::vector<vpColVector> &points, unsigned int order): need at "
402 "least two points to fit");
410 for (
unsigned int i = 0; i < nbPoints; i++) {
411 for (
unsigned int j = 0; j < i; j++) {
412 double v = (points.at(i) - points.at(j)).sumSquare();
420 vpColVector dir((points.at(max_i) - points.at(max_j)).normalize());
427 unsigned int nbPoints = points.getCols();
429 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromPointsAuto(const vpMatrix &points, "
430 "unsigned int order): need at least two points to fit");
438 for (
unsigned int i = 0; i < nbPoints; i++) {
439 for (
unsigned int j = 0; j < i; j++) {
440 double v = (points.getCol(i) - points.getCol(j)).sumSquare();
448 vpColVector dir((points.getCol(max_i) - points.getCol(max_j)).normalize());
456 unsigned int nbPoints = points.size();
458 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromPointsAuto(const "
459 "std::vector<vpColVector> &points, const vpColVector &direction, "
460 "unsigned int order): need at least two points to fit");
465 std::vector<double> t(nbPoints, 0);
467 double min = std::numeric_limits<double>::max();
468 for (
unsigned int i = 0; i < nbPoints; i++) {
469 t.at(i) = vpColVector::dotProd(points.at(i), direction);
473 for (
unsigned int i = 0; i < nbPoints; i++)
476 std::vector<int> index(nbPoints);
477 for (
unsigned int i = 0; i < nbPoints; i++)
480 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
482 std::vector<vpColVector> newPoints(nbPoints);
483 std::vector<double> interLength(nbPoints - 1);
484 newPoints.front() = points.at(index[0]);
486 double newLength = 0;
487 for (
unsigned int i = 1; i < nbPoints; i++) {
488 newPoints.at(i) = points.at(index[i]);
489 interLength.at(i - 1) = sqrt(vpMath::sqr(newPoints.at(i)[0] - newPoints.at(i - 1)[0]) +
490 vpMath::sqr(newPoints.at(i)[1] - newPoints.at(i - 1)[1]));
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,
"usPolynomialCurve2D::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(2, nbPoints);
531 vpColVector interLength(nbPoints - 1);
532 for (
unsigned int j = 0; j < 2; 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 < 2; 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 newLength += interLength[i - 1];
543 double scaling = oldLength / newLength;
544 vpColVector param(nbPoints);
546 for (
unsigned int i = 1; i < nbPoints; i++)
547 param[i] = param[i - 1] + scaling * interLength[i - 1];
553 const std::vector<double> ¶m,
const std::vector<double> &weights,
556 unsigned int nbPoints = points.size();
558 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPoints(const "
559 "std::vector<vpColVector> &points, const std::vector<double> "
560 "¶m, const std::vector<double> &weights, unsigned int order): "
561 "need at least two points to fit");
562 if (param.size() != nbPoints)
563 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPoints(const "
564 "std::vector<vpColVector> &points, const std::vector<double> "
565 "¶m, const std::vector<double> &weights, unsigned int order): "
566 "mismatching number of points and parametric values or weights");
567 if (weights.size() != nbPoints)
568 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPoints(const "
569 "std::vector<vpColVector> &points, const std::vector<double> "
570 "¶m, const std::vector<double> &weights, unsigned int order): "
571 "mismatching number of points and weights");
576 unsigned int nbCoef = order + 1;
578 vpMatrix M(nbCoef, nbCoef, 0);
579 vpMatrix B(nbCoef, 2, 0);
581 unsigned int nb_pow = 2 * nbCoef - 1;
582 vpMatrix t_pow(nbPoints, nb_pow);
583 for (
unsigned int i = 0; i < nbPoints; i++) {
584 double ti = param.at(i);
585 t_pow[i][0] = weights.at(i);
586 for (
unsigned int j = 1; j < nb_pow; j++) {
587 t_pow[i][j] = ti * t_pow[i][j - 1];
591 for (
unsigned int line = 0; line < nbCoef; line++) {
592 for (
unsigned int i = 0; i < nbPoints; i++) {
593 for (
unsigned int j = 0; j < nbCoef; j++) {
594 M[line][j] += t_pow[i][line + j];
596 for (
unsigned int dim = 0; dim < 2; dim++) {
597 B[line][dim] += t_pow[i][line] * points.at(i)[dim];
604 A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
605 }
catch (std::exception &e) {
606 throw vpException(vpException::fatalError,
"usPolynomialCurve2D::defineFromWeightedPoints(const vpMatrix &points, "
607 "const vpColVector ¶m, const vpColVector &weights, unsigned int "
617 const vpColVector &weights,
unsigned int order)
619 unsigned int nbPoints = points.getCols();
621 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPoints(const vpMatrix "
622 "&points, const vpColVector ¶m, const vpColVector &weights, "
623 "unsigned int order): need at least two points to fit");
624 if (param.size() != nbPoints)
625 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPoints(const vpMatrix "
626 "&points, const vpColVector ¶m, const vpColVector &weights, "
627 "unsigned int order): mismatching number of points and parametric "
628 "values or weights");
629 if (weights.size() != nbPoints)
630 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPoints(const vpMatrix "
631 "&points, const vpColVector ¶m, const vpColVector &weights, "
632 "unsigned int order): mismatching number of points and weights");
637 unsigned int nbCoef = order + 1;
639 vpMatrix M(nbCoef, nbCoef, 0);
640 vpMatrix B(nbCoef, 2, 0);
642 unsigned int nb_pow = 2 * nbCoef - 1;
643 vpMatrix t_pow(nbPoints, nb_pow);
644 for (
unsigned int i = 0; i < nbPoints; i++) {
645 double ti = param[i];
646 t_pow[i][0] = weights[i];
647 for (
unsigned int j = 1; j < nb_pow; j++) {
648 t_pow[i][j] = ti * t_pow[i][j - 1];
652 for (
unsigned int line = 0; line < nbCoef; line++) {
653 for (
unsigned int i = 0; i < nbPoints; i++) {
654 for (
unsigned int j = 0; j < nbCoef; j++) {
655 M[line][j] += t_pow[i][line + j];
657 for (
unsigned int dim = 0; dim < 2; dim++) {
658 B[line][dim] += t_pow[i][line] * points[dim][i];
665 A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
666 }
catch (std::exception &e) {
667 throw vpException(vpException::fatalError,
"usPolynomialCurve2D::defineFromWeightedPoints(const vpMatrix &points, "
668 "const vpColVector ¶m, const vpColVector &weights, unsigned int "
678 const std::vector<double> &weights,
unsigned int order)
680 unsigned int nbPoints = points.size();
682 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPointsAuto(const "
683 "std::vector<vpColVector> &points, const std::vector<double> "
684 "&weights, unsigned int order): need at least two points to fit");
685 if (weights.size() != nbPoints)
686 throw vpException(vpException::dimensionError,
687 "usPolynomialCurve2D::defineFromWeightedPointsAuto(const std::vector<vpColVector> &points, const "
688 "std::vector<double> &weights, unsigned int order): mismatching number of points and weights");
693 std::vector<double> t(nbPoints, 0);
695 vpColVector Pmean(2, 0);
696 for (
unsigned int i = 0; i < nbPoints; i++)
697 Pmean += points.at(i);
700 vpMatrix M(nbPoints, 2);
701 for (
unsigned int i = 0; i < nbPoints; i++)
702 for (
int j = 0; j < 2; j++)
703 M[i][j] = points.at(i)[j] - Pmean[j];
710 vpColVector dir(V.getCol(0));
711 double min = std::numeric_limits<double>::max();
712 for (
unsigned int i = 0; i < nbPoints; i++) {
713 t.at(i) = vpColVector::dotProd(points.at(i), dir);
717 for (
unsigned int i = 0; i < nbPoints; i++)
720 std::vector<int> index(nbPoints);
721 for (
unsigned int i = 0; i < nbPoints; i++)
724 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
726 std::vector<vpColVector> newPoints(nbPoints);
727 std::vector<double> newWeights(nbPoints);
728 std::vector<double> interLength(nbPoints - 1);
729 newPoints.front() = points.at(index[0]);
730 newWeights.front() = weights.at(index[0]);
732 double newLength = 0;
733 for (
unsigned int i = 1; i < nbPoints; i++) {
734 newPoints.at(i) = points.at(index[i]);
735 newWeights.at(i) = weights.at(index[i]);
736 interLength.at(i - 1) = sqrt(vpMath::sqr(newPoints.at(i)[0] - newPoints.at(i - 1)[0]) +
737 vpMath::sqr(newPoints.at(i)[1] - newPoints.at(i - 1)[1]));
738 newLength += interLength.at(i - 1);
740 double scaling = oldLength / newLength;
741 std::vector<double> param(nbPoints);
743 for (
unsigned int i = 1; i < nbPoints; i++)
744 param.at(i) = param.at(i - 1) + scaling * interLength.at(i - 1);
752 unsigned int nbPoints = points.getCols();
754 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPointsAuto(const vpMatrix "
755 "&points, const vpColVector &weights, unsigned int order): need at "
756 "least two points to fit");
757 if (weights.size() != nbPoints)
758 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPointsAuto(const vpMatrix "
759 "&points, const vpColVector &weights, unsigned int order): "
760 "mismatching number of points and weights");
765 std::vector<double> t(nbPoints, 0);
767 vpColVector Pmean(2, 0);
768 for (
unsigned int i = 0; i < nbPoints; i++)
769 Pmean += points.getCol(i);
772 vpMatrix M(nbPoints, 2);
773 for (
unsigned int i = 0; i < nbPoints; i++)
774 for (
int j = 0; j < 2; j++)
775 M[i][j] = points[j][i] - Pmean[j];
782 vpColVector dir(V.getCol(0));
783 double min = std::numeric_limits<double>::max();
784 for (
unsigned int i = 0; i < nbPoints; i++) {
785 t.at(i) = vpColVector::dotProd(points.getCol(i), dir);
789 for (
unsigned int i = 0; i < nbPoints; i++)
792 std::vector<int> index(nbPoints);
793 for (
unsigned int i = 0; i < nbPoints; i++)
796 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
798 vpMatrix newPoints(2, nbPoints);
799 vpColVector newWeights(nbPoints);
800 vpColVector interLength(nbPoints - 1);
801 for (
unsigned int j = 0; j < 2; j++)
802 newPoints[j][0] = points[j][index[0]];
803 newWeights[0] = weights[index[0]];
805 double newLength = 0;
806 for (
unsigned int i = 1; i < nbPoints; i++) {
807 for (
unsigned int j = 0; j < 2; j++)
808 newPoints[j][i] = points[j][index[i]];
809 newWeights[i] = weights[index[i]];
811 sqrt(vpMath::sqr(newPoints[0][i] - newPoints[0][i - 1]) + vpMath::sqr(newPoints[1][i] - newPoints[1][i - 1]));
812 newLength += interLength[i - 1];
814 double scaling = oldLength / newLength;
815 vpColVector param(nbPoints);
817 for (
unsigned int i = 1; i < nbPoints; i++)
818 param[i] = param[i - 1] + scaling * interLength[i - 1];
824 const std::vector<double> &weights,
const vpColVector &direction,
827 unsigned int nbPoints = points.size();
829 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPointsAuto(const "
830 "std::vector<vpColVector> &points, const std::vector<double> "
831 "&weights, const vpColVector &direction, unsigned int order): need "
832 "at least two points to fit");
833 if (weights.size() != nbPoints)
834 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPointsAuto(const "
835 "std::vector<vpColVector> &points, const std::vector<double> "
836 "&weights, const vpColVector &direction, unsigned int order): "
837 "mismatching number of points and weights");
842 std::vector<double> t(nbPoints, 0);
844 double min = std::numeric_limits<double>::max();
845 for (
unsigned int i = 0; i < nbPoints; i++) {
846 t.at(i) = vpColVector::dotProd(points.at(i), direction);
850 for (
unsigned int i = 0; i < nbPoints; i++)
853 std::vector<int> index(nbPoints);
854 for (
unsigned int i = 0; i < nbPoints; i++)
857 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
859 std::vector<vpColVector> newPoints(nbPoints);
860 std::vector<double> newWeights(nbPoints);
861 std::vector<double> interLength(nbPoints - 1);
862 newPoints.front() = points.at(index[0]);
863 newWeights.front() = weights.at(index[0]);
865 double newLength = 0;
866 for (
unsigned int i = 1; i < nbPoints; i++) {
867 newPoints.at(i) = points.at(index[i]);
868 newWeights.at(i) = weights.at(index[i]);
869 interLength.at(i - 1) = sqrt(vpMath::sqr(newPoints.at(i)[0] - newPoints.at(i - 1)[0]) +
870 vpMath::sqr(newPoints.at(i)[1] - newPoints.at(i - 1)[1]));
871 newLength += interLength.at(i - 1);
873 double scaling = oldLength / newLength;
874 std::vector<double> param(nbPoints);
876 for (
unsigned int i = 1; i < nbPoints; i++)
877 param.at(i) = param.at(i - 1) + scaling * interLength.at(i - 1);
883 const vpColVector &direction,
unsigned int order)
885 unsigned int nbPoints = points.getCols();
887 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPointsAuto(const vpMatrix "
888 "&points, const vpColVector &weights, const vpColVector &direction, "
889 "unsigned int order): need at least two points to fit");
890 if (weights.size() != nbPoints)
891 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::defineFromWeightedPointsAuto(const vpMatrix "
892 "&points, const vpColVector &weights, const vpColVector &direction, "
893 "unsigned int order): mismatching number of points and weights");
898 std::vector<double> t(nbPoints, 0);
900 double min = std::numeric_limits<double>::max();
901 for (
unsigned int i = 0; i < nbPoints; i++) {
902 t.at(i) = vpColVector::dotProd(points.getCol(i), direction);
906 for (
unsigned int i = 0; i < nbPoints; i++)
909 std::vector<int> index(nbPoints);
910 for (
unsigned int i = 0; i < nbPoints; i++)
913 std::sort(index.begin(), index.end(), [&t](
int i,
int j) { return t[i] < t[j]; });
915 vpMatrix newPoints(2, nbPoints);
916 vpColVector newWeights(nbPoints);
917 vpColVector interLength(nbPoints - 1);
918 for (
unsigned int j = 0; j < 2; j++)
919 newPoints[j][0] = points[j][index[0]];
920 newWeights[0] = weights[index[0]];
922 double newLength = 0;
923 for (
unsigned int i = 1; i < nbPoints; i++) {
924 for (
unsigned int j = 0; j < 2; j++)
925 newPoints[j][i] = points[j][index[i]];
926 newWeights[i] = weights[index[i]];
928 sqrt(vpMath::sqr(newPoints[0][i] - newPoints[0][i - 1]) + vpMath::sqr(newPoints[1][i] - newPoints[1][i - 1]));
929 newLength += interLength[i - 1];
931 double scaling = oldLength / newLength;
932 vpColVector param(nbPoints);
934 for (
unsigned int i = 1; i < nbPoints; i++)
935 param[i] = param[i - 1] + scaling * interLength[i - 1];
945 double norm = dX_dl.frobeniusNorm();
946 double curvature = (dX_dl[0] * dX2_dl2[1] - dX_dl[1] * dX2_dl2[0]) / pow(norm, 3);
954 throw vpException(vpException::badValue,
"usPolynomialCurve2D::getMeanAxisDeviation: should use at least 2 segment "
955 "to compute approximate deviation from axis");
957 vpColVector params(nbCountSeg + 1);
960 for (
int i = 1; i < nbCountSeg + 1; i++)
961 params[i] = params[i - 1] + step;
963 vpMatrix points(this->
getPoints(params));
965 vpColVector axis = (points.getCol(nbCountSeg) - points.getCol(0)).normalize();
966 vpColVector origin = points.getCol(0);
967 double meanDeviation = 0;
968 for (
int i = 0; i < nbCountSeg + 1; i++)
969 meanDeviation += vpColVector::dotProd(points.getCol(i) - origin, axis);
971 meanDeviation /= nbCountSeg + 1;
972 return meanDeviation;
977 if (controlPoints.getRows() != 2)
978 throw vpException(vpException::dimensionError,
979 "usPolynomialCurve2D::setControlPoints(const vpMatrix&): invalid points dimension, should be 2");
980 if (controlPoints.getCols() < 2)
982 vpException::dimensionError,
983 "usPolynomialCurve2D::setControlPoints(const vpMatrix&): invalid number of points, should greater than 1");
985 vpColVector direction = controlPoints.getCol(controlPoints.getCols() - 1) - controlPoints.getCol(0);
992 memcpy(M.data, *controlPoints, M.size() *
sizeof(
double));
1001 vpColVector params(
m_order + 1);
1004 for (
unsigned int i = 1; i <
m_order + 1; i++)
1005 params[i] = params[i - 1] + step;
1012 int nbRenderingPoints = (
m_order < 2) ? 2 : 10;
1013 vpColVector params(nbRenderingPoints);
1016 for (
int i = 1; i < nbRenderingPoints; i++)
1017 params[i] = params[i - 1] + step;
1024 unsigned int order1 = n1.
getOrder();
1025 unsigned int order2 = n2.
getOrder();
1026 vpMatrix coords1(order1, 50);
1027 vpMatrix coords2(order2, 50);
1028 for (
unsigned int j = 0; j < 50; ++j) {
1029 coords1[0][j] = 1.0;
1030 coords2[0][j] = 1.0;
1031 double t =
static_cast<double>(j) / 49.0;
1032 for (
unsigned int i = 1; i < order1; ++i)
1033 coords1[i][j] = coords1[i - 1][j] * t;
1034 for (
unsigned int i = 1; i < order2; ++i)
1035 coords2[i][j] = coords2[i - 1][j] * t;
1039 double distance = 0.0;
1040 for (
unsigned int i = 0; i < 50; ++i)
1041 distance += (p1.getCol(i) - p2.getCol(i)).frobeniusNorm();
1068 if (startParameter == endParameter)
1069 throw vpException(vpException::dimensionError,
"usPolynomialCurve2D::changeCoefficientsToFitBoundaries(double "
1070 "startParameter, double endParameter): new parametric boundaries "
1071 "should be different");
1074 vpColVector beta_pow(
m_order + 1);
1076 for (
unsigned int i = 1; i <=
m_order; i++)
1077 beta_pow[i] = beta * beta_pow[i - 1];
1080 vpColVector alpha_pow(
m_order + 1);
1082 for (
unsigned int i = 1; i <=
m_order; i++)
1083 alpha_pow[i] = alpha * alpha_pow[i - 1];
1087 for (
unsigned int i = 1; i <=
m_order; i++) {
1089 for (
unsigned int j = 1; j <= i; j++) {
1090 M[i][j] = M[i - 1][j - 1] + M[i - 1][j];
1094 for (
unsigned int i = 1; i <=
m_order; i++) {
1095 for (
unsigned int j = 0; j <= i; j++) {
1096 M[i][j] *= alpha_pow[j] * beta_pow[i - j];
1137 s <<
"usPolynomialCurve2D\n";
1139 for (
int i = 0; i < 2; i++) {
1140 for (
unsigned int j = 0; j < seg.
m_order + 1; j++)
1154 if (c !=
"usPolynomialCurve2D") {
1155 vpException e(vpException::ioError,
1156 "operator>>(std::istream&, Polynomial2D&): Stream does not contain usPolynomialCurve2D data");
1161 for (
unsigned int i = 0; i < 2; i++)
1162 for (
unsigned int j = 0; j < seg.
m_order + 1; j++)
1172 s.write(
"usPolynomialCurve2D", 20);
1173 s.write((
char *)&(seg.
m_order),
sizeof(
int));
1174 for (
unsigned int i = 0; i < 2; i++)
1175 for (
unsigned int j = 0; j < seg.
m_order + 1; j++)
1187 if (strcmp(c,
"usPolynomialCurve2D")) {
1188 vpException e(vpException::ioError,
1189 "operator>>=(std::istream&, Polynomial2D&): Stream does not contain usPolynomialCurve2D data");
1192 s.read((
char *)&(seg.
m_order),
sizeof(
int));
1194 for (
unsigned int i = 0; i < 2; i++)
1195 for (
unsigned int j = 0; j < seg.
m_order + 1; j++)
usPolynomialCurve2D getNewOrderPolynomialCurve(unsigned int order) const
void changeCoefficientsToFitBoundaries(double startParameter, double endParameter)
double getCurvature(double param) const
virtual ~usPolynomialCurve2D()
void setStartParameter(double startParameter)
void setBoundaries(double startParameter, double endParamter)
const usPolynomialCurve2D & operator=(const usPolynomialCurve2D &curve)
void setControlPoints(const vpMatrix &controlPoints)
void setEndParameter(double endParameter)
void changeCoefficientsToFitMetricLength()
void defineFromPointsAuto(const std::vector< vpColVector > &points, unsigned int order=0)
double getEndParameter() const
double getLength(int nbCountSeg=50) const
vpMatrix getPolynomialCoefficients() const
void setParametricLength(double length)
void defineFromWeightedPointsAuto(const std::vector< vpColVector > &points, const std::vector< double > &weights, unsigned int order=0)
vpMatrix getControlPoints() const
vpColVector getTangent(double parameter) const
void setLength(double length, double precision=1e-4)
double getStartParameter() const
vpColVector getEndTangent() const
double getParametricLength() const
void move(double x, double y, double tz)
void setPolynomialCoefficients(const vpMatrix &polynomialCoefficients)
vpColVector getStartPoint() const
void defineFromWeightedPoints(const std::vector< vpColVector > &points, const std::vector< double > ¶m, const std::vector< double > &weights, unsigned int order=0)
vpColVector getPoint(double parameter) const
static double curveDistance(const usPolynomialCurve2D &n1, const usPolynomialCurve2D &n2)
vpMatrix getRenderingPoints() const
vpColVector getStartTangent() const
double getMeanAxisDeviation(int nbCountSeg=50) const
vpMatrix m_polynomialCoefficients
vpColVector getEndPoint() const
vpColVector getDerivative(double parameter, unsigned int order) const
vpMatrix getPoints(vpColVector parameters) const
void defineFromPoints(const std::vector< vpColVector > &points, const std::vector< double > ¶m, unsigned int order=0)
unsigned int getOrder() const
usPolynomialCurve2D getSubPolynomialCurve(double startParameter, double endParameter) const
void setOrder(unsigned int order)