UsTK : Ultrasound ToolKit  version 2.0.1 under development (2023-12-07)
usBSpline3D.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ustk software.
4  * Copyright (C) 2016 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ustk with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * This software was developed at:
17  * Inria Rennes - Bretagne Atlantique
18  * Campus Universitaire de Beaulieu
19  * 35042 Rennes Cedex
20  * France
21  *
22  * If you have questions regarding the use of this file, please contact
23  * Inria at ustk@inria.fr
24  *
25  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27  *
28  * Author:
29  * Jason Chevrie
30  *
31  *****************************************************************************/
32 
33 #include <visp3/ustk_core/usBSpline3D.h>
34 
35 #include <iomanip>
36 
37 #include <visp3/core/vpConfig.h>
38 #ifdef VISP_HAVE_EIGEN3
39 #include <eigen3/Eigen/SparseCore>
40 #include <eigen3/Eigen/SparseLU>
41 #endif
42 
43 #include <visp3/core/vpException.h>
44 
46 
47 usBSpline3D::usBSpline3D(const usBSpline3D &spline) : m_spline(spline.m_spline) {}
48 
50 
52 {
53  m_spline = spline.m_spline;
54  return *this;
55 }
56 
57 usBSpline3D *usBSpline3D::clone() const { return new usBSpline3D(*this); }
58 
59 int usBSpline3D::getNbSegments() const { return m_spline.size(); }
60 
62 {
63  double l = 0;
64  for (unsigned int i = 0; i < m_spline.size(); i++) {
65  l += m_spline.at(i).getParametricLength();
66  }
67  return l;
68 }
69 
70 double usBSpline3D::getLength(int nbSubSeg) const
71 {
72  double l = 0;
73  for (unsigned int i = 0; i < m_spline.size(); i++) {
74  l += m_spline.at(i).getLength(nbSubSeg);
75  }
76  return l;
77 }
78 
80 {
81  m_spline.push_back(seg);
82  m_spline.back().changeCoefficientsToFitBoundaries(0, seg.getParametricLength());
83 }
84 
86 {
87  m_spline.insert(m_spline.begin() + i + 1, seg);
88 }
89 
90 void usBSpline3D::setSegment(int i, const usPolynomialCurve3D &poly) { m_spline.at(i) = poly; }
91 
93 
94 void usBSpline3D::removeSegment(int i) { m_spline.erase(m_spline.begin() + i, m_spline.begin() + i + 1); }
95 
96 void usBSpline3D::removeSegments(int i, int j) { m_spline.erase(m_spline.begin() + i, m_spline.begin() + j + 1); }
97 
98 void usBSpline3D::clear() { m_spline.clear(); }
99 
100 void usBSpline3D::defineFromPoints(const std::vector<vpColVector> &points, const std::vector<double> &lengths,
101  int order)
102 {
103  if (points.size() < 2)
104  throw vpException(vpException::dimensionError,
105  "usBSpline3D::defineFromPoints: should have at least two points to define the curve");
106  if (order < 1)
107  throw vpException(vpException::dimensionError, "usBSpline3D::defineFromPoints: order should be greater than zero");
108 
109  unsigned int nbSeg = points.size() - 1;
110 
111  if (lengths.size() != nbSeg)
112  throw vpException(vpException::dimensionError,
113  "usBSpline3D::defineFromPoints: mismathcing number of segments and points");
114 
115 #ifdef VISP_HAVE_EIGEN3
116 
117  int nbSegCoef = order + 1;
118  int nbCoef = nbSegCoef * nbSeg;
119 
120  typedef Eigen::Triplet<double> T;
121  std::vector<T> L;
122 
123  int nbHardConstraints = (nbSeg + 1) + (nbSeg - 1);
124  if (order > 1)
125  nbHardConstraints += (nbSeg - 1);
126  if (order > 2)
127  nbHardConstraints += (nbSeg - 1);
128 
129  L.reserve((nbHardConstraints + nbCoef) * (nbHardConstraints + nbCoef) / 10);
130 
131  Eigen::MatrixX3d A = Eigen::MatrixX3d::Zero(nbHardConstraints + nbCoef, 3);
132  Eigen::MatrixX3d B = Eigen::MatrixX3d::Zero(nbHardConstraints + nbCoef, 3);
133 
134  // Hard constraints
135 
136  // Start conditions
137  int line = nbCoef;
138 
139  // Points
140  int startIndex = 0;
141  for (unsigned int i = 0; i < nbSeg; i++) {
142  L.push_back(T(line, startIndex, 1));
143  L.push_back(T(startIndex, line, -1));
144  for (int dim = 0; dim < 3; dim++)
145  B(line, dim) = points.at(i)[dim];
146  line++;
147 
148  double segLength = lengths.at(i);
149  double *tmp = new double[nbSegCoef];
150 
151  tmp[0] = 1;
152  for (int j = 1; j < nbSegCoef; j++)
153  tmp[j] = segLength * tmp[j - 1];
154 
155  for (int j = 0; j < nbSegCoef; j++) {
156  L.push_back(T(line, startIndex + j, tmp[j]));
157  L.push_back(T(startIndex + j, line, -tmp[j]));
158  }
159  for (int dim = 0; dim < 3; dim++)
160  B(line, dim) = points.at(i + 1)[dim];
161  line++;
162 
163  delete[] tmp;
164  startIndex += nbSegCoef;
165  }
166 
167  // Continuity
168 
169  startIndex = 0;
170  for (unsigned int i = 0; i < nbSeg - 1; i++) {
171  double segLength = lengths.at(i);
172  double *tmp = new double[nbSegCoef];
173 
174  if (order > 1) // Order 1
175  {
176  tmp[0] = 0;
177  tmp[1] = 1;
178  for (int j = 2; j < nbSegCoef; j++)
179  tmp[j] = segLength * tmp[j - 1];
180  for (int j = 1; j < nbSegCoef; j++)
181  tmp[j] *= j;
182 
183  for (int j = 1; j < nbSegCoef; j++) {
184  L.push_back(T(line, startIndex + j, tmp[j]));
185  L.push_back(T(startIndex + j, line, -tmp[j]));
186  }
187  L.push_back(T(line, startIndex + nbSegCoef + 1, -1));
188  L.push_back(T(startIndex + nbSegCoef + 1, line, 1));
189  line++;
190  }
191  if (order > 2) // Order 2
192  {
193  tmp[0] = 0;
194  tmp[1] = 0;
195  tmp[2] = 1;
196  for (int j = 3; j < nbSegCoef; j++)
197  tmp[j] = segLength * tmp[j - 1];
198  for (int j = 2; j < nbSegCoef; j++)
199  tmp[j] *= j * (j - 1);
200 
201  for (int j = 2; j < nbSegCoef; j++) {
202  L.push_back(T(line, startIndex + j, tmp[j]));
203  L.push_back(T(startIndex + j, line, -tmp[j]));
204  }
205  L.push_back(T(line, startIndex + nbSegCoef + 2, -2));
206  L.push_back(T(startIndex + nbSegCoef + 2, line, 2));
207  line++;
208  }
209  delete[] tmp;
210  startIndex += nbSegCoef;
211  }
212 
213  // Optimization matrix
214 
215  line = 0;
216  startIndex = 0;
217  for (unsigned int i = 0; i < nbSeg; i++) {
218  double segLength = lengths.at(i);
219 
220  for (int j = 2; j < nbSegCoef; j++) {
221  for (int k = 2; k < nbSegCoef; k++) {
222  double c = pow(segLength, j + k - 3) * j * (j - 1) * k * (k - 1) / (j + k - 3);
223  L.push_back(T(line + j, startIndex + k, c));
224  }
225  }
226  line += nbSegCoef;
227  startIndex += nbSegCoef;
228  }
229 
230  try {
231  Eigen::SparseMatrix<double> M(nbHardConstraints + nbCoef, nbHardConstraints + nbCoef);
232  M.setFromTriplets(L.begin(), L.end());
233 
234  Eigen::SparseLU<Eigen::SparseMatrix<double> > solver;
235  solver.compute(M);
236 
237  A = solver.solve(B);
238  } catch (std::exception &e) {
239  throw vpException(vpException::fatalError, "usBSpline3D::defineFromPoints: %s\n", e.what());
240  }
241 
242  m_spline.clear();
243  startIndex = 0;
244  for (unsigned int i = 0; i < nbSeg; i++) {
245  usPolynomialCurve3D seg(order);
246  vpMatrix m(3, nbSegCoef);
247  for (int j = 0; j < nbSegCoef; j++) {
248  for (int dim = 0; dim < 3; dim++) {
249  m[dim][j] = A(startIndex + j, dim);
250  }
251  }
253  seg.setParametricLength(lengths.at(i));
254  // seg.setMaxCurvilinearCoordinate(seg.getLength());
255  m_spline.push_back(seg);
256  startIndex += nbSegCoef;
257  }
258 
259 #else
260 
261  int nbSegCoef = order + 1;
262  int nbCoef = nbSegCoef * nbSeg;
263 
264  int nbHardConstraints = (nbSeg + 1) + (nbSeg - 1);
265  if (order > 1)
266  nbHardConstraints += (nbSeg - 1);
267  if (order > 2)
268  nbHardConstraints += (nbSeg - 1);
269 
270  vpMatrix M(nbHardConstraints + nbCoef, nbHardConstraints + nbCoef, 0);
271 
272  vpMatrix A(nbHardConstraints + nbCoef, 3, 0);
273  vpMatrix B(nbHardConstraints + nbCoef, 3, 0);
274 
275  // Hard constraints
276 
277  // Start conditions
278  int line = nbCoef;
279 
280  // Points
281  int startIndex = 0;
282  for (unsigned int i = 0; i < nbSeg; i++) {
283  M[line][startIndex] = 1;
284  M[startIndex][line] = -1;
285  for (int dim = 0; dim < 3; dim++)
286  B[line][dim] = points.at(i)[dim];
287  line++;
288 
289  double segLength = lengths.at(i);
290  double *tmp = new double[nbSegCoef];
291 
292  tmp[0] = 1;
293  for (int j = 1; j < nbSegCoef; j++)
294  tmp[j] = segLength * tmp[j - 1];
295 
296  for (int j = 0; j < nbSegCoef; j++) {
297  M[line][startIndex + j] = tmp[j];
298  M[startIndex + j][line] = -tmp[j];
299  }
300  for (int dim = 0; dim < 3; dim++)
301  B[line][dim] = points.at(i + 1)[dim];
302  line++;
303 
304  delete[] tmp;
305  startIndex += nbSegCoef;
306  }
307 
308  // Continuity
309 
310  startIndex = 0;
311  for (unsigned int i = 0; i < nbSeg - 1; i++) {
312  double segLength = lengths.at(i);
313  double *tmp = new double[nbSegCoef];
314 
315  if (order > 1) // Order 1
316  {
317  tmp[0] = 0;
318  tmp[1] = 1;
319  for (int j = 2; j < nbSegCoef; j++)
320  tmp[j] = segLength * tmp[j - 1];
321  for (int j = 1; j < nbSegCoef; j++)
322  tmp[j] *= j;
323 
324  for (int j = 1; j < nbSegCoef; j++) {
325  M[line][startIndex + j] = tmp[j];
326  M[startIndex + j][line] = -tmp[j];
327  }
328  M[line][startIndex + nbSegCoef + 1] = -1;
329  M[startIndex + nbSegCoef + 1][line] = 1;
330  line++;
331  }
332  if (order > 2) // Order 2
333  {
334  tmp[0] = 0;
335  tmp[1] = 0;
336  tmp[2] = 1;
337  for (int j = 3; j < nbSegCoef; j++)
338  tmp[j] = segLength * tmp[j - 1];
339  for (int j = 2; j < nbSegCoef; j++)
340  tmp[j] *= j * (j - 1);
341 
342  for (int j = 2; j < nbSegCoef; j++) {
343  M[line][startIndex + j] = tmp[j];
344  M[startIndex + j][line] = -tmp[j];
345  }
346  M[line][startIndex + nbSegCoef + 2] = -2;
347  M[startIndex + nbSegCoef + 2][line] = 2;
348  line++;
349  }
350  delete[] tmp;
351  startIndex += nbSegCoef;
352  }
353 
354  // Optimization matrix
355 
356  line = 0;
357  startIndex = 0;
358  for (unsigned int i = 0; i < nbSeg; i++) {
359  double segLength = lengths.at(i);
360 
361  for (int j = 2; j < nbSegCoef; j++) {
362  for (int k = 2; k < nbSegCoef; k++) {
363  double c = pow(segLength, j + k - 3) * j * (j - 1) * k * (k - 1) / (j + k - 3);
364  M[line + j][startIndex + k] = c;
365  }
366  }
367  line += nbSegCoef;
368  startIndex += nbSegCoef;
369  }
370 
371  try {
372  A = M.inverseByLU() * B;
373  } catch (std::exception &e) {
374  throw vpException(vpException::fatalError, "usBSpline3D::defineFromPoints: %s\n", e.what());
375  }
376 
377  m_spline.clear();
378  startIndex = 0;
379  for (unsigned int i = 0; i < nbSeg; i++) {
380  usPolynomialCurve3D seg(order);
381  vpMatrix m(3, nbSegCoef);
382  for (int j = 0; j < nbSegCoef; j++) {
383  for (int dim = 0; dim < 3; dim++) {
384  m[dim][j] = A[startIndex + j][dim];
385  }
386  }
388  seg.setParametricLength(lengths.at(i));
389  // seg.setMaxCurvilinearCoordinate(seg.getLength());
390  m_spline.push_back(seg);
391  startIndex += nbSegCoef;
392  }
393 #endif
394 }
395 
396 const usPolynomialCurve3D &usBSpline3D::accessSegment(int i) const { return m_spline.at(i); }
397 
399 
401 
403 
404 usBSpline3D usBSpline3D::getSubSpline(double a, double b) const
405 {
406  usBSpline3D s;
408 
409  if (a <= b) {
410  unsigned int i = 0;
411  double t = 0;
412  double ta = 0;
413  double tb = 0;
414 
415  while (t + m_spline.at(i).getParametricLength() < a && i + 1 < m_spline.size()) {
416  ta = 0;
417  t += m_spline.at(i).getParametricLength();
418  i++;
419  }
420  ta = a - t;
421  t = a;
422 
423  while (t < b) {
424  if (t + (m_spline.at(i).getParametricLength() - ta) > b || i + 1 >= m_spline.size()) {
425  tb = ta + b - t;
426  p = m_spline.at(i).getSubPolynomialCurve(ta, tb);
427  ta = tb;
428  } else {
429  tb = m_spline.at(i).getParametricLength();
430  p = m_spline.at(i).getSubPolynomialCurve(ta, tb);
431  ta = 0;
432  i++;
433  }
434 
436  s.addSegment(p);
437  t += p.getParametricLength();
438  }
439 
440  } else
441  s = *this;
442 
443  return s;
444 }
445 
446 bool usBSpline3D::move(const vpHomogeneousMatrix &H)
447 {
448  for (unsigned int i = 0; i < m_spline.size(); i++) {
449  m_spline.at(i).move(H);
450  }
451  return true;
452 }
453 
454 bool usBSpline3D::move(double x, double y, double z, double tx, double ty, double tz)
455 {
456  return this->move(vpHomogeneousMatrix(x, y, z, tx, ty, tz));
457 }
458 
459 vpColVector usBSpline3D::getPoint(double l) const
460 {
461  if (l <= 0)
462  return m_spline.front().getPoint(l);
463 
464  unsigned int seg = 0;
465  double L = 0;
466 
467  while (L <= l && seg < m_spline.size()) {
468  L += m_spline.at(seg).getParametricLength();
469  seg++;
470  }
471  seg--;
472  double s = l - (L - m_spline.at(seg).getParametricLength());
473 
474  vpColVector P = m_spline.at(seg).getPoint(s);
475 
476  return P;
477 }
478 
479 vpColVector usBSpline3D::getTangent(double param) const
480 {
481  unsigned int seg = 0;
482  double L = 0;
483 
484  while (L <= param && seg < m_spline.size()) {
485  L += m_spline.at(seg).getParametricLength();
486  seg++;
487  }
488  seg--;
489  double s = param - (L - m_spline.at(seg).getParametricLength());
490 
491  vpColVector D = m_spline.at(seg).getTangent(s);
492 
493  return D;
494 }
495 
496 double usBSpline3D::getDistanceFromPoint(const vpColVector &P, double start, double stop, double threshold) const
497 {
498  if (P.size() != 3)
499  throw vpException(vpException::dimensionError, "usBSpline3D::getDistanceFromPoint: invalid point dimension");
500 
501  if (start < 0)
502  start = 0;
503  double length = this->getParametricLength();
504  if (stop == -1 || stop > length)
505  stop = length;
506  if (stop < 0)
507  stop = 0;
508  if (start > stop)
509  throw vpException(vpException::badValue, "usBSpline3D::getDistanceFromPoint: invalid start-stop parameters");
510 
511  double middle = (start + stop) / 2;
512  while ((stop - start) > threshold) {
513  double d0 = (this->getPoint(start) - P).frobeniusNorm();
514  double d1 = (this->getPoint(middle) - P).frobeniusNorm();
515  double d2 = (this->getPoint(stop) - P).frobeniusNorm();
516 
517  if (d0 <= d1 && d0 < d2)
518  stop = middle;
519  else if (d2 < d0 && d2 <= d1)
520  start = middle;
521  else {
522  start = (start + middle) / 2;
523  stop = (middle + stop) / 2;
524  }
525  middle = (start + stop) / 2;
526  }
527 
528  double l = (this->getPoint(middle) - P).frobeniusNorm();
529 
530  return l;
531 }
532 
533 bool usBSpline3D::getParametersFromLength(double l, int &index, double &param) const
534 {
535  if (l < 0)
536  return false;
537 
538  unsigned int seg = 0;
539  double L = 0;
540 
541  while (L <= l && seg < m_spline.size()) {
542  L += m_spline.at(seg).getParametricLength();
543  seg++;
544  }
545 
546  if (L <= l && seg == m_spline.size())
547  return false;
548 
549  seg--;
550  L -= m_spline.at(seg).getParametricLength();
551 
552  index = seg;
553  param = l - L;
554  return true;
555 }
556 
557 double usBSpline3D::getCurvatureFromShape(double start, double end, vpColVector &center3D,
558  vpColVector &direction3D) const
559 {
560  if (start < 0)
561  start = 0;
562  double length = this->getParametricLength();
563  if (start > length)
564  start = length;
565  if (end < 0)
566  end = 0;
567  if (end > length)
568  end = length;
569  if (start > end) {
570  double tmp = start;
571  start = end;
572  end = tmp;
573  }
574 
575  unsigned int seg = 0;
576  double L = 0;
577 
578  while (L <= start && seg < m_spline.size()) {
579  L += m_spline.at(seg).getParametricLength();
580  seg++;
581  }
582  int nStart = seg - 1;
583 
584  while (L <= end && seg < m_spline.size()) {
585  L += m_spline.at(seg).getParametricLength();
586  seg++;
587  }
588 
589  int nEnd = seg - 2;
590 
591  int nbPoints = nEnd - nStart + 1;
592 
593  if (nbPoints < 3) {
594  // std::cout << "usBSpline3D::getCurvatureFromShape: not enough points" << std::endl;
595  // std::cout << "first = " << first << " last = " << last << " nbPoints = " << nbPoints << std::endl;
596  return 0;
597  }
598 
599  // Create data matrix with centered vectors
600  vpMatrix M(nbPoints, 3);
601  vpRowVector mean(3, 0);
602 
603  for (int i = 0; i < nbPoints; i++)
604  M.insert(m_spline.at(nStart + i).getPoint(m_spline.at(nStart + i).getEndParameter()).t(), i, 0);
605 
606  for (int i = 0; i < nbPoints; i++)
607  mean += M.getRow(i);
608  mean /= nbPoints;
609 
610  for (int i = 0; i < nbPoints; i++) {
611  M[i][0] -= mean[0];
612  M[i][1] -= mean[1];
613  M[i][2] -= mean[2];
614  }
615 
616  // Reduction to two principal components using singular value decomposition
617  vpMatrix U(M);
618  vpColVector w;
619  vpMatrix V;
620  U.svd(w, V);
621 
622  vpMatrix S;
623  S.diag(w);
624 
625  U.resize(nbPoints, 2, false);
626 
627  S.resize(2, 2, false);
628 
629  vpMatrix P = U * S;
630 
631  // 2D nonlinear least square fitting (Coope93)
632  vpColVector d(nbPoints);
633  for (int i = 0; i < nbPoints; i++) {
634  d[i] = pow(P.t().getCol(i).frobeniusNorm(), 2);
635  }
636 
637  vpColVector x(nbPoints, 1);
638  vpMatrix B(nbPoints, 3);
639  B.insert(P, 0, 0);
640  B.insert(x, 0, 2);
641 
642  vpColVector y = B.pseudoInverse(0) * d;
643 
644  vpColVector center(2);
645  center[0] = y[0] / 2;
646  center[1] = y[1] / 2;
647 
648  double r = sqrt(y[2] + pow(center.frobeniusNorm(), 2));
649 
650  // Check validity
651 
652  /*vpColVector cp = P.getRow(0).t() - center;
653  for(int i=1 ; i<nbPoints ; i++)
654  {
655  double dot = vpColVector::dotProd(cp, P.getRow(i).t() - center);
656  if(dot<0) return 0;
657  }*/
658 
659  if (direction3D.size() == 3) {
660  direction3D = V.getCol(2);
661  } else if (direction3D.size() == 4) {
662  direction3D.insert(0, V.getCol(2));
663  direction3D[3] = 0;
664  }
665 
666  if (center3D.size() == 3) {
667  V.resize(3, 2, false);
668  center3D = V * center;
669  } else if (center3D.size() == 4) {
670  V.resize(3, 2, false);
671  center3D.insert(0, V * center + mean.t());
672  center3D[3] = 1;
673  }
674 
675  return 1.0 / r;
676  /*
677  usPolynomialCurve3D seg(m_spline.back());
678 
679  vpColVector dX_dl = seg.getDerivative(seg.getParametricLength(),2);
680  if(dX_dl.frobeniusNorm()<std::numeric_limits<double>::epsilon()) return 0;
681 
682  vpColVector d2X_dl2 = seg.getDerivative(seg.getParametricLength(),2);
683 
684  double k = vpColVector::crossProd(dX_dl, d2X_dl2).frobeniusNorm() / pow(dX_dl.frobeniusNorm(),3);
685 
686  center3D = seg.getEndPoint() + 1/k * ( d2X_dl2 - 1/pow(dX_dl.frobeniusNorm(),2) * vpColVector::dotProd(dX_dl,
687  d2X_dl2)*dX_dl);
688  direction3D = vpColVector::crossProd(dX_dl, d2X_dl2).normalize();
689  return k;*/
690 }
691 
692 std::ostream &operator<<(std::ostream &s, const usBSpline3D &spline)
693 {
694  s << "usBSpline3D\n";
695 
696  unsigned int n = spline.m_spline.size();
697  s << n << '\n';
698  for (unsigned int i = 0; i < n; i++)
699  s << spline.m_spline.at(i);
700 
701  s.flush();
702  return s;
703 }
704 
705 std::istream &operator>>(std::istream &s, usBSpline3D &spline)
706 {
707  std::string c;
708  s >> c;
709  if (c != "usBSpline3D") {
710  vpException e(vpException::ioError, "Stream does not contain BSpline3D data");
711  throw e;
712  }
713 
714  int n = 0;
715  s >> n;
716  spline.m_spline.clear();
717  spline.m_spline.resize(n);
718  for (int i = 0; i < n; i++)
719  s >> spline.m_spline.at(i);
720  return s;
721 }
722 
723 std::ostream &operator<<=(std::ostream &s, const usBSpline3D &spline)
724 {
725  s.write("usBSpline3D", 12);
726 
727  int n = spline.m_spline.size();
728  s.write((char *)&n, sizeof(int));
729  for (int i = 0; i < n; i++)
730  s <<= spline.m_spline.at(i);
731 
732  s.flush();
733  return s;
734 }
735 
736 std::istream &operator>>=(std::istream &s, usBSpline3D &spline)
737 {
738  char c[12];
739  s.read(c, 12);
740  if (strcmp(c, "usBSpline3D")) {
741  vpException e(vpException::ioError, "Stream does not contain BSpline3D data");
742  throw e;
743  }
744 
745  int n = 0;
746  s.read((char *)&n, sizeof(int));
747  spline.m_spline.clear();
748  spline.m_spline.resize(n);
749  for (int i = 0; i < n; i++)
750  s >>= spline.m_spline.at(i);
751  return s;
752 }
void setSegment(int i, const usPolynomialCurve3D &poly)
Definition: usBSpline3D.cpp:90
double getLength(int nbSubSeg=50) const
Definition: usBSpline3D.cpp:70
void removeLastSegment()
Definition: usBSpline3D.cpp:92
bool getParametersFromLength(double l, int &index, double &param) const
void insertSegment(int i, const usPolynomialCurve3D &seg)
Definition: usBSpline3D.cpp:85
void clear()
Definition: usBSpline3D.cpp:98
void removeSegments(int i, int j)
Definition: usBSpline3D.cpp:96
double getDistanceFromPoint(const vpColVector &point, double start=0, double stop=-1, double threshold=1e-5) const
const usPolynomialCurve3D & accessSegment(int i) const
std::vector< usPolynomialCurve3D > m_spline
Polynomials container.
Definition: usBSpline3D.h:48
vpColVector getTangent(double param) const
void addSegment(const usPolynomialCurve3D &seg)
Spline definition.
Definition: usBSpline3D.cpp:79
const usBSpline3D & operator=(const usBSpline3D &spline)
Definition: usBSpline3D.cpp:51
usBSpline3D()
Constructors, destructor.
Definition: usBSpline3D.cpp:45
int getNbSegments() const
Parameters setters and getters.
Definition: usBSpline3D.cpp:59
const usPolynomialCurve3D & accessLastSegment() const
virtual ~usBSpline3D()
Definition: usBSpline3D.cpp:49
bool move(const vpHomogeneousMatrix &H)
Move.
vpColVector getPoint(double param) const
Measure curve information.
virtual usBSpline3D * clone() const
Definition: usBSpline3D.cpp:57
usBSpline3D getSubSpline(double a, double b) const
double getCurvatureFromShape(double start, double end, vpColVector &center3D, vpColVector &direction3D) const
Curvature.
void defineFromPoints(const std::vector< vpColVector > &points, const std::vector< double > &lengths, int order=3)
void removeSegment(int i)
Definition: usBSpline3D.cpp:94
double getParametricLength() const
Definition: usBSpline3D.cpp:61
void setParametricLength(double length)
void setPolynomialCoefficients(const vpMatrix &polynomialCoefficients)
double getParametricLength() const
void changeCoefficientsToFitBoundaries(double startParameter, double endParameter)