UsTK : Ultrasound ToolKit  version 2.0.1 under development (2023-12-07)
usPolynomialCurve2D.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  * Authors:
29  * Pierre Chatelain
30  * Alexandre Krupa
31  *
32  *****************************************************************************/
33 
34 #include <visp3/ustk_core/usPolynomialCurve2D.h>
35 
36 #include <algorithm>
37 
38 #include <visp3/core/vpException.h>
39 
41  : m_order(0), m_startParameter(0), m_endParameter(1), m_polynomialCoefficients(2, 1, 0)
42 {
43 }
44 
46  : m_order(curve.m_order), m_startParameter(curve.m_startParameter), m_endParameter(curve.m_endParameter),
47  m_polynomialCoefficients(curve.m_polynomialCoefficients)
48 {
49 }
50 
52 {
53  m_order = curve.m_order;
57 
58  return *this;
59 }
60 
62 
64  : m_order(order), m_startParameter(0), m_endParameter(1), m_polynomialCoefficients(2, m_order + 1, 0)
65 {
66 }
67 
68 void usPolynomialCurve2D::setOrder(unsigned int order)
69 {
70  if (order == m_order)
71  return;
72  else if (order > m_order) {
73  // Keep same polynomial
74  m_order = order;
75  m_polynomialCoefficients.resize(2, order + 1, false);
76  } else {
77  // Find polynomial to have the same properties at the extremities (position, direction, curvature, ...)
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;
81 
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++) {
87  startParameter_power[i] = m_startParameter * startParameter_power[i - 1];
88  endParameter_power[i] = m_endParameter * endParameter_power[i - 1];
89  }
90 
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++)
96  A[i][j] *= j - n;
97  }
98  }
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++)
103  A[i][j] *= j - n;
104  }
105  }
106 
107  vpMatrix Ainvt = A.inverseByLU().t();
108 
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++)
115  coef *= j - n;
116  col += coef * m_polynomialCoefficients.getCol(j);
117  }
118  B.insert(col, 0, i);
119  }
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++)
125  coef *= j - n;
126  col += coef * m_polynomialCoefficients.getCol(j);
127  }
128  B.insert(col, 0, nb_constraints_begin + i);
129  }
130 
131  m_polynomialCoefficients.resize(2, nb_coef);
132  m_polynomialCoefficients = B * Ainvt;
133  m_order = order;
134  }
135 }
136 
137 unsigned int usPolynomialCurve2D::getOrder() const { return m_order; }
138 
139 void usPolynomialCurve2D::setStartParameter(double startParameter) { m_startParameter = startParameter; }
140 
142 
143 void usPolynomialCurve2D::setEndParameter(double endParameter) { m_endParameter = endParameter; }
144 
146 
147 void usPolynomialCurve2D::setBoundaries(double startParameter, double endParameter)
148 {
149  if (startParameter <= endParameter) {
150  m_startParameter = startParameter;
151  m_endParameter = endParameter;
152  } else {
153  m_startParameter = endParameter;
154  m_endParameter = startParameter;
155  this->reverse();
156  }
157 }
158 
160 
162 
163 void usPolynomialCurve2D::setLength(double length, double precision)
164 {
165  if (precision <= 0)
166  throw vpException(vpException::badValue, "usPolynomialCurve2D::setLength: precision should be strictly positive");
167  if (length <= 0)
168  throw vpException(vpException::badValue, "usPolynomialCurve2D::setLength: length should be strictly positive");
169 
170  double lMetric = this->getLength();
171  double lParam = this->getParametricLength();
172  double lMetricPrev = 0;
173  double lParamPrev = 0;
174  double diffMetric = length - lMetric;
175 
176  while (fabs(diffMetric) > length * precision) {
177  double slope = (lParam - lParamPrev) / (lMetric - lMetricPrev);
178  m_endParameter += diffMetric * slope;
179  lMetricPrev = lMetric;
180  lParamPrev = lParam;
181  lMetric = this->getLength();
182  lParam = this->getParametricLength();
183  diffMetric = length - lMetric;
184  }
185 }
186 
187 double usPolynomialCurve2D::getLength(int nbCountSeg) const
188 {
189  vpColVector params(nbCountSeg + 1);
190  double step = this->getParametricLength() / nbCountSeg;
191  params[0] = m_startParameter;
192  for (int i = 1; i < nbCountSeg + 1; i++)
193  params[i] = params[i - 1] + step;
194 
195  vpMatrix points = this->getPoints(params);
196 
197  double length = 0.0;
198  for (int i = 0; i < nbCountSeg; i++)
199  length += (points.getCol(i) - points.getCol(i + 1)).frobeniusNorm();
200  return length;
201 }
202 
203 void usPolynomialCurve2D::setPolynomialCoefficients(const vpMatrix &polynomialCoefficients)
204 {
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");
211 
212  m_order = polynomialCoefficients.getCols() - 1;
213  m_polynomialCoefficients = polynomialCoefficients;
214 }
215 
217 
218 vpColVector usPolynomialCurve2D::getPoint(double parameter) const
219 {
220  vpColVector T(m_order + 1);
221  T[0] = 1.0;
222  for (unsigned int i = 1; i < m_order + 1; i++)
223  T[i] = T[i - 1] * parameter;
224  return m_polynomialCoefficients * T;
225 }
226 
227 vpMatrix usPolynomialCurve2D::getPoints(vpColVector parameters) const
228 {
229  vpMatrix T(m_order + 1, parameters.size());
230  for (unsigned int j = 0; j < parameters.size(); j++) {
231  T[0][j] = 1.0;
232  for (unsigned int i = 1; i < m_order + 1; i++)
233  T[i][j] = T[i - 1][j] * parameters[j];
234  }
235  return m_polynomialCoefficients * T;
236 }
237 
238 vpColVector usPolynomialCurve2D::getStartPoint() const { return this->getPoint(m_startParameter); }
239 
240 vpColVector usPolynomialCurve2D::getEndPoint() const { return this->getPoint(m_endParameter); }
241 
242 vpColVector usPolynomialCurve2D::getTangent(double parameter) const
243 {
244  vpColVector T(m_order + 1);
245  double tt = 1.0;
246  T[0] = 0.0;
247  for (unsigned int i = 1; i < m_order + 1; i++) {
248  T[i] = i * tt;
249  tt *= parameter;
250  }
251  return (m_polynomialCoefficients * T).normalize();
252 }
253 
255 
256 vpColVector usPolynomialCurve2D::getEndTangent() const { return this->getTangent(m_endParameter); }
257 
258 vpColVector usPolynomialCurve2D::getDerivative(double parameter, unsigned int order) const
259 {
260  vpColVector P(2, 0);
261 
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];
267 
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;
271  }
272 
273  P = m_polynomialCoefficients * factor_coef;
274  }
275 
276  return P;
277 }
278 
279 void usPolynomialCurve2D::defineFromPoints(const std::vector<vpColVector> &points, const std::vector<double> &param,
280  unsigned int order)
281 {
282  unsigned int nbPoints = points.size();
283  if (nbPoints < 2)
284  throw vpException(vpException::dimensionError, "usPolynomialCurve2D::defineFromPoints(const "
285  "std::vector<vpColVector> &points, const std::vector<double> "
286  "&param, 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  "&param, unsigned int order): mismatching number of points and "
291  "parametric values");
292 
293  if (order < 1)
294  order = m_order;
295 
296  unsigned int nbCoef = order + 1;
297 
298  vpMatrix M(nbCoef, nbCoef, 0);
299  vpMatrix B(nbCoef, 2, 0);
300 
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);
305  t_pow[i][0] = 1;
306  for (unsigned int j = 1; j < nb_pow; j++) {
307  t_pow[i][j] = ti * t_pow[i][j - 1];
308  }
309  }
310 
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];
315  }
316  for (unsigned int dim = 0; dim < 2; dim++) {
317  B[line][dim] += t_pow[i][line] * points.at(i)[dim];
318  }
319  }
320  }
321 
322  vpMatrix A;
323  try {
324  if (nbCoef > nbPoints)
325  A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
326  else
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> &param, unsigned int order): %s",
331  e.what());
332  }
333 
334  this->setPolynomialCoefficients(A.t());
335  this->setBoundaries(param.front(), param.back());
336 }
337 
338 void usPolynomialCurve2D::defineFromPoints(const vpMatrix points, const vpColVector &param, unsigned int order)
339 {
340  unsigned int nbPoints = points.getCols();
341  if (nbPoints < 2)
342  throw vpException(vpException::dimensionError, "usPolynomialCurve2D::defineFromPoints(const "
343  "std::vector<vpColVector> &points, const std::vector<double> "
344  "&param, 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  "&param, unsigned int order): mismatching number of points and "
349  "parametric values");
350 
351  if (order < 1)
352  order = m_order;
353 
354  unsigned int nbCoef = order + 1;
355 
356  vpMatrix M(nbCoef, nbCoef, 0);
357  vpMatrix B(nbCoef, 2, 0);
358 
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];
363  t_pow[i][0] = 1;
364  for (unsigned int j = 1; j < nb_pow; j++) {
365  t_pow[i][j] = ti * t_pow[i][j - 1];
366  }
367  }
368 
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];
373  }
374  for (unsigned int dim = 0; dim < 2; dim++) {
375  B[line][dim] += t_pow[i][line] * points[dim][i];
376  }
377  }
378  }
379 
380  vpMatrix A;
381  try {
382  if (nbCoef > nbPoints)
383  A = M.pseudoInverse(std::numeric_limits<double>::epsilon()) * B;
384  else
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> &param, unsigned int order): %s",
389  e.what());
390  }
391 
392  this->setPolynomialCoefficients(A.t());
393  this->setBoundaries(param[0], param[param.size() - 1]);
394 }
395 
396 void usPolynomialCurve2D::defineFromPointsAuto(const std::vector<vpColVector> &points, unsigned int order)
397 {
398  unsigned int nbPoints = points.size();
399  if (nbPoints < 2)
400  throw vpException(vpException::dimensionError, "usPolynomialCurve2D::defineFromPointsAuto(const "
401  "std::vector<vpColVector> &points, unsigned int order): need at "
402  "least two points to fit");
403 
404  if (order < 1)
405  order = m_order;
406 
407  int max_i = 0;
408  int max_j = 0;
409  double max = 0;
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();
413  if (v > max) {
414  max = v;
415  max_i = i;
416  max_j = j;
417  }
418  }
419  }
420  vpColVector dir((points.at(max_i) - points.at(max_j)).normalize());
421 
422  this->defineFromPointsAuto(points, dir, order);
423 }
424 
425 void usPolynomialCurve2D::defineFromPointsAuto(const vpMatrix &points, unsigned int order)
426 {
427  unsigned int nbPoints = points.getCols();
428  if (nbPoints < 2)
429  throw vpException(vpException::dimensionError, "usPolynomialCurve2D::defineFromPointsAuto(const vpMatrix &points, "
430  "unsigned int order): need at least two points to fit");
431 
432  if (order < 1)
433  order = m_order;
434 
435  int max_i = 0;
436  int max_j = 0;
437  double max = 0;
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();
441  if (v > max) {
442  max = v;
443  max_i = i;
444  max_j = j;
445  }
446  }
447  }
448  vpColVector dir((points.getCol(max_i) - points.getCol(max_j)).normalize());
449 
450  this->defineFromPointsAuto(points, dir, order);
451 }
452 
453 void usPolynomialCurve2D::defineFromPointsAuto(const std::vector<vpColVector> &points, const vpColVector &direction,
454  unsigned int order)
455 {
456  unsigned int nbPoints = points.size();
457  if (nbPoints < 2)
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");
461 
462  if (order < 1)
463  order = m_order;
464 
465  std::vector<double> t(nbPoints, 0);
466 
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);
470  if (t.at(i) < min)
471  min = t.at(i);
472  }
473  for (unsigned int i = 0; i < nbPoints; i++)
474  t.at(i) -= min;
475 
476  std::vector<int> index(nbPoints);
477  for (unsigned int i = 0; i < nbPoints; i++)
478  index.at(i) = i;
479 
480  std::sort(index.begin(), index.end(), [&t](int i, int j) { return t[i] < t[j]; });
481 
482  std::vector<vpColVector> newPoints(nbPoints);
483  std::vector<double> interLength(nbPoints - 1);
484  newPoints.front() = points.at(index[0]);
485  double oldLength = this->getParametricLength();
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);
492  }
493  double scaling = oldLength / newLength;
494  std::vector<double> param(nbPoints);
495  param.front() = m_startParameter;
496  for (unsigned int i = 1; i < nbPoints; i++)
497  param.at(i) = param.at(i - 1) + scaling * interLength.at(i - 1);
498 
499  this->defineFromPoints(newPoints, param, order);
500 }
501 
502 void usPolynomialCurve2D::defineFromPointsAuto(const vpMatrix &points, const vpColVector &direction, unsigned int order)
503 {
504  unsigned int nbPoints = points.getCols();
505  if (nbPoints < 2)
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");
509 
510  if (order < 1)
511  order = m_order;
512 
513  std::vector<double> t(nbPoints, 0);
514 
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);
518  if (t.at(i) < min)
519  min = t.at(i);
520  }
521  for (unsigned int i = 0; i < nbPoints; i++)
522  t.at(i) -= min;
523 
524  std::vector<int> index(nbPoints);
525  for (unsigned int i = 0; i < nbPoints; i++)
526  index.at(i) = i;
527 
528  std::sort(index.begin(), index.end(), [&t](int i, int j) { return t[i] < t[j]; });
529 
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]];
534  double oldLength = this->getParametricLength();
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]];
539  interLength[i - 1] =
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];
542  }
543  double scaling = oldLength / newLength;
544  vpColVector param(nbPoints);
545  param[0] = m_startParameter;
546  for (unsigned int i = 1; i < nbPoints; i++)
547  param[i] = param[i - 1] + scaling * interLength[i - 1];
548 
549  this->defineFromPoints(newPoints, param, order);
550 }
551 
552 void usPolynomialCurve2D::defineFromWeightedPoints(const std::vector<vpColVector> &points,
553  const std::vector<double> &param, const std::vector<double> &weights,
554  unsigned int order)
555 {
556  unsigned int nbPoints = points.size();
557  if (nbPoints < 2)
558  throw vpException(vpException::dimensionError, "usPolynomialCurve2D::defineFromWeightedPoints(const "
559  "std::vector<vpColVector> &points, const std::vector<double> "
560  "&param, 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  "&param, 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  "&param, const std::vector<double> &weights, unsigned int order): "
571  "mismatching number of points and weights");
572 
573  if (order < 1)
574  order = m_order;
575 
576  unsigned int nbCoef = order + 1;
577 
578  vpMatrix M(nbCoef, nbCoef, 0);
579  vpMatrix B(nbCoef, 2, 0);
580 
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];
588  }
589  }
590 
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];
595  }
596  for (unsigned int dim = 0; dim < 2; dim++) {
597  B[line][dim] += t_pow[i][line] * points.at(i)[dim];
598  }
599  }
600  }
601 
602  vpMatrix A;
603  try {
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 &param, const vpColVector &weights, unsigned int "
608  "order): %s",
609  e.what());
610  }
611 
612  this->setPolynomialCoefficients(A.t());
613  this->setBoundaries(param.front(), param.back());
614 }
615 
616 void usPolynomialCurve2D::defineFromWeightedPoints(const vpMatrix &points, const vpColVector &param,
617  const vpColVector &weights, unsigned int order)
618 {
619  unsigned int nbPoints = points.getCols();
620  if (nbPoints < 2)
621  throw vpException(vpException::dimensionError, "usPolynomialCurve2D::defineFromWeightedPoints(const vpMatrix "
622  "&points, const vpColVector &param, 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 &param, 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 &param, const vpColVector &weights, "
632  "unsigned int order): mismatching number of points and weights");
633 
634  if (order < 1)
635  order = m_order;
636 
637  unsigned int nbCoef = order + 1;
638 
639  vpMatrix M(nbCoef, nbCoef, 0);
640  vpMatrix B(nbCoef, 2, 0);
641 
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];
649  }
650  }
651 
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];
656  }
657  for (unsigned int dim = 0; dim < 2; dim++) {
658  B[line][dim] += t_pow[i][line] * points[dim][i];
659  }
660  }
661  }
662 
663  vpMatrix A;
664  try {
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 &param, const vpColVector &weights, unsigned int "
669  "order): %s",
670  e.what());
671  }
672 
673  this->setPolynomialCoefficients(A.t());
674  this->setBoundaries(param[0], param[nbPoints - 1]);
675 }
676 
677 void usPolynomialCurve2D::defineFromWeightedPointsAuto(const std::vector<vpColVector> &points,
678  const std::vector<double> &weights, unsigned int order)
679 {
680  unsigned int nbPoints = points.size();
681  if (nbPoints < 2)
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");
689 
690  if (order < 1)
691  order = m_order;
692 
693  std::vector<double> t(nbPoints, 0);
694 
695  vpColVector Pmean(2, 0);
696  for (unsigned int i = 0; i < nbPoints; i++)
697  Pmean += points.at(i);
698  Pmean /= nbPoints;
699 
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];
704 
705  // Reduction to one principal component using singular value decomposition
706  vpColVector w;
707  vpMatrix V;
708  M.svd(w, V);
709 
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);
714  if (t.at(i) < min)
715  min = t.at(i);
716  }
717  for (unsigned int i = 0; i < nbPoints; i++)
718  t.at(i) -= min;
719 
720  std::vector<int> index(nbPoints);
721  for (unsigned int i = 0; i < nbPoints; i++)
722  index.at(i) = i;
723 
724  std::sort(index.begin(), index.end(), [&t](int i, int j) { return t[i] < t[j]; });
725 
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]);
731  double oldLength = this->getParametricLength();
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);
739  }
740  double scaling = oldLength / newLength;
741  std::vector<double> param(nbPoints);
742  param.front() = m_startParameter;
743  for (unsigned int i = 1; i < nbPoints; i++)
744  param.at(i) = param.at(i - 1) + scaling * interLength.at(i - 1);
745 
746  this->defineFromWeightedPoints(newPoints, param, newWeights, order);
747 }
748 
749 void usPolynomialCurve2D::defineFromWeightedPointsAuto(const vpMatrix &points, const vpColVector &weights,
750  unsigned int order)
751 {
752  unsigned int nbPoints = points.getCols();
753  if (nbPoints < 2)
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");
761 
762  if (order < 1)
763  order = m_order;
764 
765  std::vector<double> t(nbPoints, 0);
766 
767  vpColVector Pmean(2, 0);
768  for (unsigned int i = 0; i < nbPoints; i++)
769  Pmean += points.getCol(i);
770  Pmean /= nbPoints;
771 
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];
776 
777  // Reduction to one principal component using singular value decomposition
778  vpColVector w;
779  vpMatrix V;
780  M.svd(w, V);
781 
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);
786  if (t.at(i) < min)
787  min = t.at(i);
788  }
789  for (unsigned int i = 0; i < nbPoints; i++)
790  t.at(i) -= min;
791 
792  std::vector<int> index(nbPoints);
793  for (unsigned int i = 0; i < nbPoints; i++)
794  index.at(i) = i;
795 
796  std::sort(index.begin(), index.end(), [&t](int i, int j) { return t[i] < t[j]; });
797 
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]];
804  double oldLength = this->getParametricLength();
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]];
810  interLength[i - 1] =
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];
813  }
814  double scaling = oldLength / newLength;
815  vpColVector param(nbPoints);
816  param[0] = m_startParameter;
817  for (unsigned int i = 1; i < nbPoints; i++)
818  param[i] = param[i - 1] + scaling * interLength[i - 1];
819 
820  this->defineFromWeightedPoints(newPoints, param, newWeights, order);
821 }
822 
823 void usPolynomialCurve2D::defineFromWeightedPointsAuto(const std::vector<vpColVector> &points,
824  const std::vector<double> &weights, const vpColVector &direction,
825  unsigned int order)
826 {
827  unsigned int nbPoints = points.size();
828  if (nbPoints < 2)
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");
838 
839  if (order < 1)
840  order = m_order;
841 
842  std::vector<double> t(nbPoints, 0);
843 
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);
847  if (t.at(i) < min)
848  min = t.at(i);
849  }
850  for (unsigned int i = 0; i < nbPoints; i++)
851  t.at(i) -= min;
852 
853  std::vector<int> index(nbPoints);
854  for (unsigned int i = 0; i < nbPoints; i++)
855  index.at(i) = i;
856 
857  std::sort(index.begin(), index.end(), [&t](int i, int j) { return t[i] < t[j]; });
858 
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]);
864  double oldLength = this->getParametricLength();
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);
872  }
873  double scaling = oldLength / newLength;
874  std::vector<double> param(nbPoints);
875  param.front() = m_startParameter;
876  for (unsigned int i = 1; i < nbPoints; i++)
877  param.at(i) = param.at(i - 1) + scaling * interLength.at(i - 1);
878 
879  this->defineFromWeightedPoints(newPoints, param, newWeights, order);
880 }
881 
882 void usPolynomialCurve2D::defineFromWeightedPointsAuto(const vpMatrix &points, const vpColVector &weights,
883  const vpColVector &direction, unsigned int order)
884 {
885  unsigned int nbPoints = points.getCols();
886  if (nbPoints < 2)
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");
894 
895  if (order < 1)
896  order = m_order;
897 
898  std::vector<double> t(nbPoints, 0);
899 
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);
903  if (t.at(i) < min)
904  min = t.at(i);
905  }
906  for (unsigned int i = 0; i < nbPoints; i++)
907  t.at(i) -= min;
908 
909  std::vector<int> index(nbPoints);
910  for (unsigned int i = 0; i < nbPoints; i++)
911  index.at(i) = i;
912 
913  std::sort(index.begin(), index.end(), [&t](int i, int j) { return t[i] < t[j]; });
914 
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]];
921  double oldLength = this->getParametricLength();
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]];
927  interLength[i - 1] =
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];
930  }
931  double scaling = oldLength / newLength;
932  vpColVector param(nbPoints);
933  param[0] = m_startParameter;
934  for (unsigned int i = 1; i < nbPoints; i++)
935  param[i] = param[i - 1] + scaling * interLength[i - 1];
936 
937  this->defineFromWeightedPoints(newPoints, param, newWeights, order);
938 }
939 
940 double usPolynomialCurve2D::getCurvature(double param) const
941 {
942  vpColVector dX_dl = this->getDerivative(param, 1);
943  vpColVector dX2_dl2 = this->getDerivative(param, 2);
944 
945  double norm = dX_dl.frobeniusNorm();
946  double curvature = (dX_dl[0] * dX2_dl2[1] - dX_dl[1] * dX2_dl2[0]) / pow(norm, 3);
947 
948  return curvature;
949 }
950 
951 double usPolynomialCurve2D::getMeanAxisDeviation(int nbCountSeg) const
952 {
953  if (nbCountSeg < 2)
954  throw vpException(vpException::badValue, "usPolynomialCurve2D::getMeanAxisDeviation: should use at least 2 segment "
955  "to compute approximate deviation from axis");
956 
957  vpColVector params(nbCountSeg + 1);
958  double step = this->getParametricLength() / nbCountSeg;
959  params[0] = m_startParameter;
960  for (int i = 1; i < nbCountSeg + 1; i++)
961  params[i] = params[i - 1] + step;
962 
963  vpMatrix points(this->getPoints(params));
964 
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);
970 
971  meanDeviation /= nbCountSeg + 1;
972  return meanDeviation;
973 }
974 
975 void usPolynomialCurve2D::setControlPoints(const vpMatrix &controlPoints)
976 {
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)
981  throw vpException(
982  vpException::dimensionError,
983  "usPolynomialCurve2D::setControlPoints(const vpMatrix&): invalid number of points, should greater than 1");
984 
985  vpColVector direction = controlPoints.getCol(controlPoints.getCols() - 1) - controlPoints.getCol(0);
986  this->defineFromPointsAuto(controlPoints, direction, controlPoints.getCols() - 1);
987 }
988 
989 void usPolynomialCurve2D::setControlPoints(double **controlPoints)
990 {
991  vpMatrix M(2, m_order);
992  memcpy(M.data, *controlPoints, M.size() * sizeof(double));
993  this->setControlPoints(M);
994 }
995 
997 {
998  if (m_order == 0)
999  return this->getStartPoint();
1000 
1001  vpColVector params(m_order + 1);
1002  double step = this->getParametricLength() / m_order;
1003  params[0] = m_startParameter;
1004  for (unsigned int i = 1; i < m_order + 1; i++)
1005  params[i] = params[i - 1] + step;
1006 
1007  return this->getPoints(params);
1008 }
1009 
1011 {
1012  int nbRenderingPoints = (m_order < 2) ? 2 : 10;
1013  vpColVector params(nbRenderingPoints);
1014  double step = this->getParametricLength() / (nbRenderingPoints - 1);
1015  params[0] = m_startParameter;
1016  for (int i = 1; i < nbRenderingPoints; i++)
1017  params[i] = params[i - 1] + step;
1018 
1019  return this->getPoints(params);
1020 }
1021 
1023 {
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;
1036  }
1037  vpMatrix p1 = n1.getPolynomialCoefficients() * coords1;
1038  vpMatrix p2 = n2.getPolynomialCoefficients() * coords2;
1039  double distance = 0.0;
1040  for (unsigned int i = 0; i < 50; ++i)
1041  distance += (p1.getCol(i) - p2.getCol(i)).frobeniusNorm();
1042  distance /= 50;
1043  return distance;
1044 }
1045 
1046 usPolynomialCurve2D usPolynomialCurve2D::getSubPolynomialCurve(double startParameter, double endParameter) const
1047 {
1048  usPolynomialCurve2D seg(*this);
1049 
1050  seg.setBoundaries(startParameter, endParameter);
1051 
1052  return seg;
1053 }
1054 
1056 {
1057  usPolynomialCurve2D seg(*this);
1058 
1059  seg.setOrder(order);
1060 
1061  return seg;
1062 }
1063 
1064 void usPolynomialCurve2D::changeCoefficientsToFitBoundaries(double startParameter, double endParameter)
1065 {
1066  if (startParameter == m_startParameter && endParameter == m_endParameter)
1067  return;
1068  if (startParameter == endParameter)
1069  throw vpException(vpException::dimensionError, "usPolynomialCurve2D::changeCoefficientsToFitBoundaries(double "
1070  "startParameter, double endParameter): new parametric boundaries "
1071  "should be different");
1072 
1073  double beta = (m_startParameter * endParameter - m_endParameter * startParameter) / (endParameter - startParameter);
1074  vpColVector beta_pow(m_order + 1);
1075  beta_pow[0] = 1;
1076  for (unsigned int i = 1; i <= m_order; i++)
1077  beta_pow[i] = beta * beta_pow[i - 1];
1078 
1079  double alpha = (m_endParameter - m_startParameter) / (endParameter - startParameter);
1080  vpColVector alpha_pow(m_order + 1);
1081  alpha_pow[0] = 1;
1082  for (unsigned int i = 1; i <= m_order; i++)
1083  alpha_pow[i] = alpha * alpha_pow[i - 1];
1084 
1085  vpMatrix M(m_order + 1, m_order + 1, 0);
1086  M[0][0] = 1;
1087  for (unsigned int i = 1; i <= m_order; i++) {
1088  M[i][0] = 1;
1089  for (unsigned int j = 1; j <= i; j++) {
1090  M[i][j] = M[i - 1][j - 1] + M[i - 1][j];
1091  }
1092  }
1093 
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];
1097  }
1098  }
1099 
1101 
1102  m_startParameter = startParameter;
1103  m_endParameter = endParameter;
1104 }
1105 
1107 
1109 {
1110  double endParameter = m_endParameter;
1112  this->setBoundaries(m_startParameter, endParameter);
1113 }
1114 
1115 void usPolynomialCurve2D::move(double x, double y, double tz)
1116 {
1117  double c = cos(tz);
1118  double s = sin(tz);
1119 
1120  vpMatrix R(2, 2);
1121  R[0][0] = c;
1122  R[0][1] = -s;
1123  R[1][0] = s;
1124  R[1][1] = c;
1125 
1126  vpMatrix M = R * m_polynomialCoefficients;
1127  M[0][0] += x;
1128  M[1][0] += y;
1129 
1131 }
1132 
1134 
1135 std::ostream &operator<<(std::ostream &s, const usPolynomialCurve2D &seg)
1136 {
1137  s << "usPolynomialCurve2D\n";
1138  s << seg.m_order << '\n';
1139  for (int i = 0; i < 2; i++) {
1140  for (unsigned int j = 0; j < seg.m_order + 1; j++)
1141  s << seg.m_polynomialCoefficients[i][j] << " ";
1142  s << '\n';
1143  }
1144  s << seg.m_startParameter << '\n';
1145  s << seg.m_endParameter << '\n';
1146  s.flush();
1147  return s;
1148 }
1149 
1150 std::istream &operator>>(std::istream &s, usPolynomialCurve2D &seg)
1151 {
1152  std::string c;
1153  s >> c;
1154  if (c != "usPolynomialCurve2D") {
1155  vpException e(vpException::ioError,
1156  "operator>>(std::istream&, Polynomial2D&): Stream does not contain usPolynomialCurve2D data");
1157  throw e;
1158  }
1159  s >> seg.m_order;
1160  seg.m_polynomialCoefficients.resize(2, seg.m_order + 1);
1161  for (unsigned int i = 0; i < 2; i++)
1162  for (unsigned int j = 0; j < seg.m_order + 1; j++)
1163  s >> seg.m_polynomialCoefficients[i][j];
1164  s >> seg.m_startParameter;
1165  s >> seg.m_endParameter;
1166  s.get();
1167  return s;
1168 }
1169 
1170 std::ostream &operator<<=(std::ostream &s, const usPolynomialCurve2D &seg)
1171 {
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++)
1176  s.write((char *)&(seg.m_polynomialCoefficients[i][j]), sizeof(double));
1177  s.write((char *)&(seg.m_startParameter), sizeof(double));
1178  s.write((char *)&(seg.m_endParameter), sizeof(double));
1179  s.flush();
1180  return s;
1181 }
1182 
1183 std::istream &operator>>=(std::istream &s, usPolynomialCurve2D &seg)
1184 {
1185  char c[20];
1186  s.read(c, 20);
1187  if (strcmp(c, "usPolynomialCurve2D")) {
1188  vpException e(vpException::ioError,
1189  "operator>>=(std::istream&, Polynomial2D&): Stream does not contain usPolynomialCurve2D data");
1190  throw e;
1191  }
1192  s.read((char *)&(seg.m_order), sizeof(int));
1193  seg.m_polynomialCoefficients.resize(2, seg.m_order + 1);
1194  for (unsigned int i = 0; i < 2; i++)
1195  for (unsigned int j = 0; j < seg.m_order + 1; j++)
1196  s.read((char *)&(seg.m_polynomialCoefficients[i][j]), sizeof(double));
1197  s.read((char *)&(seg.m_startParameter), sizeof(double));
1198  s.read((char *)&(seg.m_endParameter), sizeof(double));
1199  return s;
1200 }
usPolynomialCurve2D getNewOrderPolynomialCurve(unsigned int order) const
void changeCoefficientsToFitBoundaries(double startParameter, double endParameter)
double getCurvature(double param) const
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 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 > &param, 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
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 > &param, unsigned int order=0)
unsigned int getOrder() const
usPolynomialCurve2D getSubPolynomialCurve(double startParameter, double endParameter) const
void setOrder(unsigned int order)