UsTK : Ultrasound ToolKit  version 2.0.1 under development (2024-05-20)
usNeedleInsertionModelRayleighRitzSpline.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_needle_modeling/usNeedleInsertionModelRayleighRitzSpline.h>
34 
35 #include <visp3/ustk_core/usGeometryTools.h>
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/vpMatrix.h>
44 #include <visp3/core/vpPoseVector.h>
45 #include <visp3/core/vpRGBa.h>
46 #include <visp3/core/vpRotationMatrix.h>
47 #include <visp3/core/vpTranslationVector.h>
48 #include <visp3/gui/vpDisplayX.h>
49 
50 #include <iomanip>
51 
53  : m_needle(), m_needleTip(new usNeedleTipBeveled()), m_needleTipType(NeedleTipType::BeveledTip), m_tissue(),
54  m_pathUpdateType(PathUpdateType::NoUpdate), m_pathUpdateLengthThreshold(0.001), m_pathUpdateMixCoefficient(0.5),
55  m_solvingMethod(SolvingMethod::FixedBeamLength)
56 {
57  m_stiffnessPerUnitLength.resize(1, 10000);
58  m_layerLength.resize(1, 1);
59  this->updateState();
60 }
61 
64  : m_needle(model.m_needle), m_needleTip(model.m_needleTip->clone()), m_needleTipType(model.m_needleTipType),
65  m_tissue(model.m_tissue), m_stiffnessPerUnitLength(model.m_stiffnessPerUnitLength),
66  m_layerLength(model.m_layerLength),
67 
68  m_pathUpdateType(model.m_pathUpdateType), m_pathUpdateLengthThreshold(model.m_pathUpdateLengthThreshold),
69  m_pathUpdateMixCoefficient(model.m_pathUpdateMixCoefficient),
70 
71  m_solvingMethod(model.m_solvingMethod), m_restDilatationFactor(model.m_restDilatationFactor)
72 {
73 }
74 
76 {
77  if (m_needleTip != nullptr)
78  delete m_needleTip;
79 }
80 
83 {
84  m_needle = model.m_needle;
85  if (m_needleTip)
86  delete m_needleTip;
87  m_needleTip = model.m_needleTip->clone();
89  m_tissue = model.m_tissue;
92 
96 
99 
100  return *this;
101 }
102 
104 {
106 }
107 
109 {
110  switch (preset) {
114  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
115  double d = m_needle.getOuterDiameter();
116  t->setDiameter(d);
117  t->setLength(d / tan(M_PI / 180 * 24));
118  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
119  this->setStiffnessPerUnitLength(i, 20000);
120  break;
121  }
125  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
126  double d = m_needle.getOuterDiameter();
127  t->setDiameter(d);
128  t->setLength(d / tan(M_PI / 180 * 24));
129  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
130  this->setStiffnessPerUnitLength(i, 20000);
131  break;
132  }
133  case ModelPreset::Symmetric: {
137  double d = m_needle.getOuterDiameter();
138  t->setDiameter(d);
139  t->setLength(d / 2 / tan(M_PI / 180 * 30 / 2));
140  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
141  this->setStiffnessPerUnitLength(i, 20000);
142  break;
143  }
147  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
148  double d = m_needle.getOuterDiameter();
149  t->setDiameter(d);
150  t->setLength(d / tan(M_PI / 180 * 30));
151  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
152  this->setStiffnessPerUnitLength(i, 35500 * 4 * 0.2 / 0.17);
153  break;
154  }
158  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
159  double d = m_needle.getOuterDiameter();
160  t->setDiameter(d);
161  t->setLength(d / tan(M_PI / 180 * 32.09));
162  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
163  this->setStiffnessPerUnitLength(i, 4830);
164  break;
165  }
169  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
170  double d = m_needle.getOuterDiameter();
171  t->setDiameter(d);
172  t->setLength(d / tan(M_PI / 180 * 30));
173  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
174  this->setStiffnessPerUnitLength(i, 150000);
175  break;
176  }
180  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
181  double d = m_needle.getOuterDiameter();
182  t->setDiameter(d);
183  t->setLength(d);
184  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
185  this->setStiffnessPerUnitLength(i, 500);
186  break;
187  }
193  t->setLength(0.005);
194  t->setTipAngleRad(0);
195  t->setSteeringAngleRad(0);
196  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
197  this->setStiffnessPerUnitLength(i, 35000);
198  break;
199  }
203  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
204  double d = m_needle.getOuterDiameter();
205  t->setDiameter(d);
206  t->setLength(d / tan(M_PI / 180 * 45));
207  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
208  this->setStiffnessPerUnitLength(i, 20000);
209  break;
210  }
214  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
215  double d = m_needle.getOuterDiameter();
216  t->setDiameter(d);
217  t->setLength(d / tan(M_PI / 180 * 30));
218  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
219  this->setStiffnessPerUnitLength(i, 20000);
220  break;
221  }
225  usNeedleTipBeveled *t = dynamic_cast<usNeedleTipBeveled *>(m_needleTip);
226  double d = m_needle.getOuterDiameter();
227  t->setDiameter(d);
228  t->setLength(d / tan(M_PI / 180 * 26));
229  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
230  this->setStiffnessPerUnitLength(i, 20000);
231  break;
232  }
233  }
234 }
235 
237 
239 
241 
243 
245 
247 
249 {
250  if (type == m_needleTipType)
251  return;
252 
253  vpPoseVector p(m_needleTip->getBasePose());
254  delete m_needleTip;
255  m_needleTip = nullptr;
256 
257  switch (type) {
261  break;
262  }
266  break;
267  }
271  break;
272  }
276  break;
277  }
278  }
279 
281 }
282 
285 {
286  return m_needleTipType;
287 }
288 
290 {
291  if (K <= 0 || l <= 0)
292  return false;
293 
294  m_stiffnessPerUnitLength.push_back(K);
295  m_layerLength.push_back(l);
296  return true;
297 }
298 
300 {
301  if (K <= 0)
302  return false;
303  m_stiffnessPerUnitLength.at(i) = K;
304  return true;
305 }
306 
308 {
309  if (K <= 0)
310  return false;
311  for (unsigned int i = 0; i < m_stiffnessPerUnitLength.size(); i++)
312  m_stiffnessPerUnitLength.at(i) = K;
313  return true;
314 }
315 
317 {
318  return m_stiffnessPerUnitLength.at(i);
319 }
320 
322 {
323  if (l <= 0)
324  return false;
325  m_layerLength.at(i) = l;
326  return true;
327 }
328 
330 
332 
334 {
335  int n = 0;
336  double l = 0;
337  while (n + 1 < this->getNbLayers() && l < this->getInsertionDepth()) {
338  l += m_layerLength.at(n);
339  n++;
340  }
341  return n;
342 }
343 
345 
347 {
349 }
350 
352 {
354 }
355 
357 
359 {
361 }
362 
364 {
365  if (this->IsNeedleInserted()) {
367  if (seg != nullptr)
368  *seg = -1;
369  if (param != nullptr)
370  *param = -1;
371  return 0;
372  }
373 
374  int nbSeg = m_needle.getNbSegments();
375  int i = 0;
376  double l = 0;
377  double ltot = 0;
378  while (i < nbSeg) {
381  i++;
382  } else {
385  ltot += l;
386  }
387  break;
388  }
389  }
390 
391  if (i < nbSeg) {
392  if (seg != nullptr)
393  *seg = i;
394  if (param != nullptr)
395  *param = l;
396  } else {
397  if (seg != nullptr)
398  *seg = -1;
399  if (param != nullptr)
400  *param = -1;
401  }
402  return ltot;
403  } else {
404  if (seg != nullptr)
405  *seg = -1;
406  if (param != nullptr)
407  *param = -1;
408  double L = 0;
409  for (int i = 0; i < m_needle.getNbSegments(); i++)
411  return L;
412  }
413 }
414 
416 {
417  return m_needle.getFullLength() - this->getNeedleFreeLength();
418 }
419 
421 {
422  if (!this->IsNeedleInserted())
423  throw vpException(vpException::fatalError,
424  "usNeedleInsertionModelRayleighRitzSpline::getNeedleInsertionPoint: needle is not inserted");
425 
426  return usGeometryTools::projectPointOnPlane(m_needle.getPoint(this->getNeedleFreeLength()), m_tissue.accessSurface());
427 }
428 
430 {
431  if (m_tissue.accessPath().getNbSegments() < 1)
432  throw vpException(vpException::fatalError,
433  "usNeedleInsertionModelRayleighRitzSpline::getTissueInsertionPoint: needle was not inserted");
434 
435  return m_tissue.accessPath().getPoint(0);
436 }
437 
439  double &correspondingRestParam) const
440 {
441  correspondingRestIndex = -1;
442  correspondingRestParam = -1;
443  if (m_tissue.accessPath().getNbSegments() < 1)
444  return false;
445 
446  int needleIndex = -1;
447  double needleParam = -1;
448  double freeLength = this->getNeedleFreeLength(&needleIndex, &needleParam);
449  if (l < freeLength || needleIndex < 0 || needleParam < 0)
450  return false;
451 
452  double insertionLength = l - freeLength;
453  double currentNeedleInsertedLength = 0;
454  int restIndex = 0;
455  double currentRestParam = 0;
456  double currentRestLength = 0;
457 
458  while (currentNeedleInsertedLength < insertionLength) {
459  // Go forward in needle
460 
461  if (needleIndex < m_needle.getNbSegments() - 1 &&
462  currentNeedleInsertedLength + m_needle.accessSegment(needleIndex).getParametricLength() - needleParam <
463  insertionLength) {
464  currentNeedleInsertedLength += m_needle.accessSegment(needleIndex).getParametricLength() - needleParam;
465  needleParam = 0;
466  } else {
467  currentNeedleInsertedLength = insertionLength;
468  }
469 
470  while (restIndex < m_tissue.accessPath().getNbSegments() - 1 &&
471  currentRestLength +
472  m_restDilatationFactor.at(needleIndex) *
473  (m_tissue.accessPath().accessSegment(restIndex).getParametricLength() - currentRestParam) <
474  currentNeedleInsertedLength) {
475  currentRestLength += m_restDilatationFactor.at(needleIndex) *
476  (m_tissue.accessPath().accessSegment(restIndex).getParametricLength() - currentRestParam);
477  currentRestParam = 0;
478  restIndex++;
479  }
480 
481  currentRestParam += (currentNeedleInsertedLength - currentRestLength) / m_restDilatationFactor.at(needleIndex);
482  currentRestLength = currentNeedleInsertedLength;
483  needleIndex++;
484  }
485 
486  correspondingRestIndex = restIndex;
487  correspondingRestParam = currentRestParam;
488 
489  return true;
490 }
491 
493 {
494  double E = 0;
495 
496  int nbSeg = m_needle.getNbSegments();
497  double totalLength = this->getNeedleFreeLength();
498 
499  double layerIndex = 0;
500  double currentDepth = 0;
501  double nextDepth = m_layerLength.front();
502  double Kt = m_stiffnessPerUnitLength.front();
503 
504  for (int i = 1; i < nbSeg; i++) {
505  const usPolynomialCurve3D &segment = m_needle.accessSegment(i);
506 
507  double dE = 0;
508  double l = 0;
509  double length = segment.getParametricLength();
510  double dl = length / 50;
511 
512  int restIndex = -1;
513  double restParameter = -1;
514  vpColVector Pn = segment.getPoint(l);
515  if (this->getCorrespondingPathPoint(totalLength + l, restIndex, restParameter)) {
516  dE += Kt * (Pn - m_tissue.accessPath().accessSegment(restIndex).getPoint(restParameter)).sumSquare() / 2;
517  }
518 
519  while (l < length) {
520  Pn = segment.getPoint(l);
521 
522  if (this->getCorrespondingPathPoint(totalLength + l, restIndex, restParameter)) {
523  dE += Kt * (Pn - m_tissue.accessPath().accessSegment(restIndex).getPoint(restParameter)).sumSquare();
524  }
525 
526  l += dl;
527  currentDepth += dl;
528 
529  while (layerIndex + 1 < m_layerLength.size() && currentDepth > nextDepth) {
530  layerIndex++;
531  nextDepth += m_layerLength.at(layerIndex);
532  Kt = m_stiffnessPerUnitLength.at(layerIndex);
533  }
534  }
535 
536  l = length;
537  Pn = segment.getPoint(l);
538 
539  if (this->getCorrespondingPathPoint(l, restIndex, restParameter)) {
540  dE += Kt * (Pn - m_tissue.accessPath().accessSegment(restIndex).getPoint(restParameter)).sumSquare() / 2;
541  }
542  E += dl * dE;
543  }
544 
545  return E;
546 }
547 
549 {
550  if (!this->IsNeedleInserted() || (m_tissue.accessPath().getNbSegments() < 1))
551  return 0;
552 
553  return (this->getTissueInsertionPoint() - this->getNeedleInsertionPoint()).frobeniusNorm();
554 }
555 
557 {
558  if (!this->IsNeedleInserted()) {
559  if (lmax != nullptr)
560  *lmax = 0;
561  return 0;
562  }
563 
564  double max = 0;
565  double maxL = 0;
566 
567  int nbSeg = m_needle.getNbSegments();
568  int i = 0;
569  double l = 0;
570  double freeLength = this->getNeedleFreeLength(&i, &l);
571  if (i == -1) {
572  if (lmax != nullptr)
573  *lmax = 0;
574  return 0;
575  }
576  double totalLength = freeLength - l;
577 
578  while (i < nbSeg) {
579  const usPolynomialCurve3D &segment = m_needle.accessSegment(i);
580 
581  double length = segment.getParametricLength();
582  double dl = (length - l) / 50;
583 
584  int restIndex = -1;
585  double restParameter = -1;
586  vpColVector Pn;
587 
588  while (l < length) {
589  Pn = segment.getPoint(l);
590 
591  if (this->getCorrespondingPathPoint(totalLength + l, restIndex, restParameter)) {
592  double s = (Pn - m_tissue.accessPath().accessSegment(restIndex).getPoint(restParameter)).frobeniusNorm();
593 
594  if (s > max) {
595  max = s;
596  maxL = totalLength + l;
597  }
598  }
599 
600  l += dl;
601  }
602 
603  l = length;
604  Pn = segment.getPoint(l);
605 
606  if (this->getCorrespondingPathPoint(totalLength + l, restIndex, restParameter)) {
607  double s = (Pn - m_tissue.accessPath().accessSegment(restIndex).getPoint(restParameter)).frobeniusNorm();
608 
609  if (s > max) {
610  max = s;
611  maxL = totalLength + l;
612  }
613  }
614 
615  l = 0;
616  totalLength += length;
617  i++;
618  }
619 
620  if (lmax != nullptr)
621  *lmax = maxL;
622 
623  return max;
624 }
625 
627 {
628  if (!this->IsNeedleInserted())
629  return 0;
630 
631  double mean = 0;
632 
633  int nbSeg = m_needle.getNbSegments();
634  int i = 0;
635  double l = 0;
636  double freeLength = this->getNeedleFreeLength(&i, &l);
637  if (i == -1)
638  return 0;
639  double totalLength = freeLength - l;
640 
641  while (i < nbSeg) {
642  const usPolynomialCurve3D &segment = m_needle.accessSegment(i);
643 
644  double dmean = 0;
645 
646  double length = segment.getParametricLength();
647  double dl = (length - l) / 50;
648 
649  int restIndex = -1;
650  double restParameter = -1;
651  vpColVector Pn = segment.getPoint(l);
652  if (this->getCorrespondingPathPoint(totalLength + l, restIndex, restParameter)) {
653  dmean += (Pn - m_tissue.accessPath().accessSegment(restIndex).getPoint(restParameter)).frobeniusNorm() / 2;
654  }
655 
656  while (l < length) {
657  Pn = segment.getPoint(l);
658 
659  if (this->getCorrespondingPathPoint(totalLength + l, restIndex, restParameter)) {
660  dmean += (Pn - m_tissue.accessPath().accessSegment(restIndex).getPoint(restParameter)).frobeniusNorm();
661  }
662 
663  l += dl;
664  }
665 
666  l = length;
667  Pn = segment.getPoint(l);
668 
669  if (this->getCorrespondingPathPoint(totalLength + l, restIndex, restParameter)) {
670  dmean += (Pn - m_tissue.accessPath().accessSegment(restIndex).getPoint(restParameter)).frobeniusNorm() / 2;
671  }
672  mean += dl * dmean;
673 
674  l = 0;
675  totalLength += length;
676  i++;
677  }
678 
679  mean /= (totalLength - freeLength);
680 
681  return mean;
682 }
683 
685 {
686  // Set base position in worldframe if the base doesn't go under the tissue
687 
688  if (m_tissue.accessSurface().getDirection().frobeniusNorm() > 0) {
689  vpColVector position(pose.getTranslationVector());
691  return false;
692  }
693 
694  m_needle.setBasePose(pose);
695 
696  this->updateState();
697 
698  return true;
699 }
700 
702 
704 {
705  vpColVector t = m_needleTip->getTipPosition();
706  vpPoseVector pose(m_needle.getTipPose());
707  for (int i = 0; i < 3; i++)
708  pose[i] = t[i];
710 }
711 
713 {
714  if (P.size() != 3)
715  throw vpException(vpException::dimensionError,
716  "usNeedleInsertionModelRayleighRitzSpline::cutPathToPoint: invalid vector dimension");
717 
719 
720  vpColVector lastPoint(3);
721  vpColVector lastDirection(3);
722  if (m_tissue.accessPath().getNbSegments() > 0) {
724  lastDirection = m_needle.getTipDirection(); // m_tissue.accessPath().accessLastSegment().getEndTangent();
725  } else {
726  lastDirection = m_needle.getTipDirection();
727  lastPoint = usGeometryTools::projectPointOnPlane(P, m_tissue.accessSurface(), lastDirection);
728  }
729 
730  if (vpColVector::dotProd(P - lastPoint, lastDirection) > m_pathUpdateLengthThreshold) {
731  if ((P - m_needle.getBasePosition()).frobeniusNorm() > 1.1*m_needle.getFullLength()) {
732  std::cout << "Warning usNeedleInsertionModelRayleighRitzSpline::cutPathToPoint: cut point is inconsistent with "
733  "current needle state"
734  << std::endl;
735  return false;
736  }
737 
738  usPolynomialCurve3D seg(1);
739  vpMatrix M(3, 2);
740  M.insert(lastPoint, 0, 0);
741  M.insert((P - lastPoint).normalize(), 0, 1);
743  seg.setParametricLength((P - lastPoint).frobeniusNorm());
745  return true;
746  } else
747  return false;
748 }
749 
751 {
752 #ifdef VISP_HAVE_EIGEN3
753 
754  double trueFreeLength = 0;
755 
757  double freeLength = -1;
759  int seg = -1;
760  double param = 0;
761  m_needle.getParametersFromLength(freeLength, seg, param);
762 
763  for (int i = 0; i < seg; i++) {
764  trueFreeLength += m_needle.accessSegment(i).getLength();
765  }
766  trueFreeLength += m_needle.accessSegment(seg).getSubPolynomialCurve(0, param).getLength();
767  } else {
768  vpColVector p(3);
769  for (int i = 0; i < 3; i++)
770  p[i] = m_needle.getBasePose()[i];
771  vpColVector d(3);
772  for (int i = 0; i < 3; i++)
773  d[i] = m_needle.getWorldMbase()[i][2];
774  double cosTheta = vpColVector::dotProd(m_tissue.accessSurface().getDirection(), d);
775  if (cosTheta > std::numeric_limits<double>::epsilon())
776  trueFreeLength = fabs(usGeometryTools::getPointPlaneDistance(p, m_tissue.accessSurface())) / cosTheta;
777  else
778  trueFreeLength = m_needle.getFullLength();
779  }
780 
781  if (trueFreeLength >= m_needle.getFullLength() ||
782  m_tissue.accessPath().getNbSegments() == 0) // needle is not inserted
783  {
785  vpMatrix M(3, seg.getOrder() + 1, 0);
786  for (int dim = 0; dim < 3; dim++) {
787  M[dim][0] = m_needle.getBasePose()[dim];
788  M[dim][1] = m_needle.getWorldMbase()[dim][2];
789  }
792  m_needle.init();
793  m_needle.setSegment(0, seg);
794 
795  return;
796  }
797 
798  m_needle.accessSegment(0).setParametricLength(trueFreeLength);
799 
800  double segDefaultLength = 0.01;
801  int nbSegments = 1 + floor((m_needle.getFullLength() - trueFreeLength) / segDefaultLength) + 1;
802  while (m_needle.getNbSegments() > nbSegments) {
804  }
805  while (m_needle.getNbSegments() < nbSegments) {
807  }
809  for (int i = 1; i < nbSegments - 1; i++)
810  m_needle.accessSegment(i).setParametricLength(segDefaultLength);
812  m_needle.getFullLength() - m_needle.accessSegment(0).getParametricLength() - segDefaultLength * (nbSegments - 2));
813 
814  int nbcoef = 0;
815  for (int i = 0; i < nbSegments; i++)
816  nbcoef += m_needle.accessSegment(i).getOrder() + 1;
817 
818  typedef Eigen::Triplet<double> T;
819  std::vector<T> L;
820 
821  double EI = m_needle.getEI();
822 
823  int nbConstraints = 2;
824  for (int i = 0; i < nbSegments - 1; i++) {
825  int order1 = m_needle.accessSegment(i).getOrder();
826  int order2 = m_needle.accessSegment(i + 1).getOrder();
827  int order = std::max(order1, order2);
828  nbConstraints += std::min(3, order);
829  }
830 
831  L.reserve((nbConstraints + nbcoef) * (nbConstraints + nbcoef) / 10);
832 
833  Eigen::MatrixX3d A = Eigen::MatrixX3d::Zero(nbConstraints + nbcoef, 3);
834  Eigen::MatrixX3d B = Eigen::MatrixX3d::Zero(nbConstraints + nbcoef, 3);
835 
836  // Constraints matrix
837 
838  // Base conditions
839  int line = nbcoef;
840  for (int dim = 0; dim < 3; dim++)
841  B(line, dim) = m_needle.getBasePose()[dim];
842  L.push_back(T(line, 0, 1));
843  L.push_back(T(0, line, -1));
844  line++;
845  for (int dim = 0; dim < 3; dim++)
846  B(line, dim) = m_needle.getWorldMbase()[dim][2];
847  L.push_back(T(line, 1, 1));
848  L.push_back(T(1, line, -1));
849  line++;
850 
851  int nbSegCoef = 0;
852  int startIndex = 0;
853  for (int i = 0; i < nbSegments - 1; i++) {
854  nbSegCoef = m_needle.accessSegment(i).getOrder() + 1;
855  int order1 = m_needle.accessSegment(i).getOrder();
856  int order2 = m_needle.accessSegment(i + 1).getOrder();
857  int order = std::max(order1, order2);
858  double segLength = m_needle.accessSegment(i).getParametricLength();
859 
860  // Continuity
861 
862  double *tmp = new double[nbSegCoef];
863 
864  if (order > 0) // Order 0
865  {
866  tmp[0] = 1;
867  for (int j = 1; j < nbSegCoef; j++)
868  tmp[j] = segLength * tmp[j - 1];
869 
870  for (int j = 0; j < nbSegCoef; j++) {
871  L.push_back(T(line, startIndex + j, tmp[j]));
872  L.push_back(T(startIndex + j, line, -tmp[j]));
873  }
874  L.push_back(T(line, startIndex + nbSegCoef, -1));
875  L.push_back(T(startIndex + nbSegCoef, line, 1));
876  line++;
877  }
878  if (order > 1) // Order 1
879  {
880  tmp[0] = 0;
881  tmp[1] = 1;
882  for (int j = 2; j < nbSegCoef; j++)
883  tmp[j] = segLength * tmp[j - 1];
884  for (int j = 1; j < nbSegCoef; j++)
885  tmp[j] *= j;
886 
887  for (int j = 1; j < nbSegCoef; j++) {
888  L.push_back(T(line, startIndex + j, tmp[j]));
889  L.push_back(T(startIndex + j, line, -tmp[j]));
890  }
891  L.push_back(T(line, startIndex + nbSegCoef + 1, -1));
892  L.push_back(T(startIndex + nbSegCoef + 1, line, 1));
893  line++;
894  }
895  if (order > 2) // Order 2
896  {
897  tmp[0] = 0;
898  tmp[1] = 0;
899  tmp[2] = 1;
900  for (int j = 3; j < nbSegCoef; j++)
901  tmp[j] = segLength * tmp[j - 1];
902  for (int j = 2; j < nbSegCoef; j++)
903  tmp[j] *= j * (j - 1);
904 
905  for (int j = 2; j < nbSegCoef; j++) {
906  L.push_back(T(line, startIndex + j, tmp[j]));
907  L.push_back(T(startIndex + j, line, -tmp[j]));
908  }
909  L.push_back(T(line, startIndex + nbSegCoef + 2, -2));
910  L.push_back(T(startIndex + nbSegCoef + 2, line, 2));
911  line++;
912  }
913  delete[] tmp;
914  startIndex += nbSegCoef;
915  }
916 
917  // Optimization matrix
918 
919  line = 0;
920 
921  nbSegCoef = m_needle.accessSegment(0).getOrder() + 1;
922  int nbSegEq = nbSegCoef;
923  double segLength = m_needle.accessSegment(0).getParametricLength();
924  for (int j = 0; j < nbSegEq; j++) {
925  // Bending minimization
926  for (int k = 2; k < nbSegCoef; k++) {
927  if (j > 1)
928  L.push_back(T(line, k, EI * pow(segLength, j + k - 3) * j * (j - 1) * k * (k - 1) / (j + k - 3)));
929  }
930  line++;
931  }
932 
933  startIndex = nbSegCoef;
934  int restIndex = 0;
935  double currentRestParam = 0;
936  int layerIndex = 0;
937  double currentDepth = 0;
938  double nextLayerDepth = m_layerLength.front();
939  for (int i = 1; i < nbSegments; i++) {
940  nbSegCoef = m_needle.accessSegment(i).getOrder() + 1;
941  nbSegEq = nbSegCoef;
942  segLength = m_needle.accessSegment(i).getParametricLength();
943 
944  double lseg = 0;
945  double LsegMin = 0;
946  double LsegMax = segLength;
947  while (lseg < segLength) {
948  double stiffnessPerUnitLength = m_stiffnessPerUnitLength.at(layerIndex);
949 
950  if (currentDepth - lseg + segLength > nextLayerDepth && layerIndex + 1 < (int)m_layerLength.size()) {
951  LsegMax = nextLayerDepth - currentDepth;
952  }
953 
954  for (int j = 0; j < nbSegEq; j++) {
955  for (int k = 0; k < nbSegCoef; k++) {
956  double c = 0;
957  // Bending minimization
958  if (j > 1 && k > 1)
959  c += EI * (pow(LsegMax, j + k - 3) - pow(LsegMin, j + k - 3)) * j * (j - 1) * k * (k - 1) / (j + k - 3);
960  // if(i==0) c*=100;
961  // Tissue deformation minimization
962  c += stiffnessPerUnitLength * (pow(LsegMax, j + k + 1) - pow(LsegMin, j + k + 1)) / (j + k + 1);
963 
964  L.push_back(T(line + j, startIndex + k, c));
965  }
966  }
967 
968  double l = LsegMin;
969  while (l < LsegMax) {
971  currentRestParam,
972  ((restIndex == m_tissue.accessPath().getNbSegments() - 1) ? currentRestParam : 0) +
975  int nbRestSegCoef = p.getOrder() + 1;
976 
977  double Lmin = l;
978  double Lmax = 0;
979  if ((LsegMax - l) < p.getParametricLength() || restIndex == m_tissue.accessPath().getNbSegments() - 1) {
980  Lmax = LsegMax;
981  currentRestParam += (LsegMax - l) / m_restDilatationFactor.at(i - 1);
982  l = LsegMax;
983  } else {
984  Lmax = l + p.getParametricLength();
985  l = Lmax;
986  currentRestParam = 0;
987  restIndex++;
988  }
989 
990  vpMatrix coefP = p.getPolynomialCoefficients();
991  for (int j = 0; j < nbSegEq; j++) {
992  for (int k = 0; k < nbRestSegCoef; k++) {
993  double c = stiffnessPerUnitLength * (pow(Lmax, j + k + 1) - pow(Lmin, j + k + 1)) / (j + k + 1);
994  for (int dim = 0; dim < 3; dim++) {
995  B(line + j, dim) += c * coefP[dim][k];
996  }
997  }
998  }
999  }
1000 
1001  if (LsegMax < segLength) {
1002  layerIndex++;
1003  nextLayerDepth += m_layerLength.at(layerIndex);
1004  lseg += LsegMax - LsegMin;
1005  } else
1006  lseg = segLength;
1007 
1008  currentDepth += LsegMax - LsegMin;
1009  LsegMin = LsegMax;
1010  LsegMax = segLength;
1011  }
1012 
1013  line += nbSegEq;
1014  startIndex += nbSegCoef;
1015  }
1016 
1017  Eigen::SparseMatrix<double> M(nbConstraints + nbcoef, nbConstraints + nbcoef);
1018  M.setFromTriplets(L.begin(), L.end());
1019 
1020  Eigen::SparseLU<Eigen::SparseMatrix<double> > solver;
1021  solver.compute(M);
1022 
1023  A = solver.solve(B);
1024 
1025  // Update coefficients
1026  startIndex = 0;
1027  for (int i = 0; i < nbSegments; i++) {
1028  int order = m_needle.accessSegment(i).getOrder();
1029  vpMatrix m(3, order + 1);
1030  for (int j = 0; j < order + 1; j++) {
1031  for (int dim = 0; dim < 3; dim++) {
1032  m[dim][j] = A(startIndex + j, dim);
1033  }
1034  }
1036  startIndex += order + 1;
1037  }
1038 #else
1039  throw vpException(
1040  vpException::functionNotImplementedError,
1041  "usNeedleInsertionModelRayleighRitzSpline::solveSegmentsParametersSparseEigen: not implemented without Eigen3");
1042 #endif
1043 }
1044 
1046 {
1047 #ifdef VISP_HAVE_EIGEN3
1048  if (m_tissue.accessPath().getNbSegments() == 0) // no path present
1049  {
1051  vpMatrix M(3, seg.getOrder() + 1, 0);
1052  for (int dim = 0; dim < 3; dim++) {
1053  M[dim][0] = m_needle.getBasePose()[dim];
1054  M[dim][1] = m_needle.getWorldMbase()[dim][2];
1055  }
1058  m_needle.init();
1059  m_needle.setSegment(0, seg);
1060 
1061  return;
1062  }
1063 
1064  double trueFreeLength = 0;
1065 
1067  double freeLength = -1;
1069  int seg = -1;
1070  double param = 0;
1071  m_needle.getParametersFromLength(freeLength, seg, param);
1072 
1073  for (int i = 0; i < seg; i++) {
1074  trueFreeLength += m_needle.accessSegment(i).getLength();
1075  }
1076  trueFreeLength += m_needle.accessSegment(seg).getSubPolynomialCurve(0, param).getLength();
1077  } else {
1078  vpColVector p(3);
1079  for (int i = 0; i < 3; i++)
1080  p[i] = m_needle.getBasePose()[i];
1081  vpColVector d(3);
1082  for (int i = 0; i < 3; i++)
1083  d[i] = m_needle.getWorldMbase()[i][2];
1084  double cosTheta = vpColVector::dotProd(m_tissue.accessSurface().getDirection(), d);
1085  if (cosTheta > std::numeric_limits<double>::epsilon())
1086  trueFreeLength = fabs(usGeometryTools::getPointPlaneDistance(p, m_tissue.accessSurface())) / cosTheta;
1087  else
1088  trueFreeLength = m_needle.getFullLength();
1089  }
1090 
1092  if (trueFreeLength >= m_needle.getFullLength() && !tipIn) // needle is not inserted
1093  {
1095  vpMatrix M(3, seg.getOrder() + 1, 0);
1096  for (int dim = 0; dim < 3; dim++) {
1097  M[dim][0] = m_needle.getBasePose()[dim];
1098  M[dim][1] = m_needle.getWorldMbase()[dim][2];
1099  }
1102  m_needle.init();
1103  m_needle.setSegment(0, seg);
1104 
1105  return;
1106  }
1107 
1108  m_needle.accessSegment(0).setParametricLength(trueFreeLength);
1109 
1110  double segDefaultLength = 0.01;
1111  int nbSegments = 1 + floor((m_needle.getFullLength() - trueFreeLength) / segDefaultLength) + 1;
1112 
1113  if (trueFreeLength >= m_needle.getFullLength())
1114  nbSegments = 1;
1115 
1116  while (m_needle.getNbSegments() > nbSegments) {
1118  }
1119  while (m_needle.getNbSegments() < nbSegments) {
1121  }
1123  for (int i = 1; i < nbSegments - 1; i++)
1124  m_needle.accessSegment(i).setParametricLength(segDefaultLength);
1125  if (nbSegments > 1)
1128  segDefaultLength * (nbSegments - 2));
1129 
1130  int nbcoef = 0;
1131  for (int i = 0; i < nbSegments; i++)
1132  nbcoef += m_needle.accessSegment(i).getOrder() + 1;
1133 
1134  typedef Eigen::Triplet<double> T;
1135  std::vector<T> L;
1136 
1137  double EI = m_needle.getEI();
1138 
1139  int nbConstraints = 2;
1140  for (int i = 0; i < nbSegments - 1; i++) {
1141  int order1 = m_needle.accessSegment(i).getOrder();
1142  int order2 = m_needle.accessSegment(i + 1).getOrder();
1143  int order = std::max(order1, order2);
1144  nbConstraints += std::min(3, order);
1145  }
1146 
1147  int nbMatrixLine = 3 * (nbConstraints + nbcoef);
1148 
1149  L.reserve(nbMatrixLine * nbMatrixLine / 10);
1150 
1151  Eigen::VectorXd A = Eigen::VectorXd::Zero(nbMatrixLine);
1152  Eigen::VectorXd B = Eigen::VectorXd::Zero(nbMatrixLine);
1153 
1154  // Constraints matrix
1155 
1156  // Base conditions
1157  int line = 3 * nbcoef;
1158  for (int dim = 0; dim < 3; dim++) {
1159  B(line) = m_needle.getBasePose()[dim];
1160  L.push_back(T(line, dim, 1));
1161  L.push_back(T(dim, line, -1));
1162  line++;
1163  }
1164  for (int dim = 0; dim < 3; dim++) {
1165  B(line) = m_needle.getWorldMbase()[dim][2];
1166  L.push_back(T(line, 3 + dim, 1));
1167  L.push_back(T(3 + dim, line, -1));
1168  line++;
1169  }
1170 
1171  int nbSegCoef = 0;
1172  int startIndex = 0;
1173  for (int i = 0; i < nbSegments - 1; i++) {
1174  nbSegCoef = m_needle.accessSegment(i).getOrder() + 1;
1175  int order1 = m_needle.accessSegment(i).getOrder();
1176  int order2 = m_needle.accessSegment(i + 1).getOrder();
1177  int order = std::max(order1, order2);
1178  double segLength = m_needle.accessSegment(i).getParametricLength();
1179 
1180  // Continuity
1181 
1182  double *tmp = new double[nbSegCoef];
1183  if (order > 0) // Order 0
1184  {
1185  tmp[0] = 1;
1186  for (int j = 1; j < nbSegCoef; j++)
1187  tmp[j] = segLength * tmp[j - 1];
1188 
1189  for (int dim = 0; dim < 3; dim++) {
1190  for (int j = 0; j < nbSegCoef; j++) {
1191  L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1192  L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1193  }
1194  L.push_back(T(line, startIndex + 3 * nbSegCoef + dim, -1));
1195  L.push_back(T(startIndex + 3 * nbSegCoef + dim, line, 1));
1196  line++;
1197  }
1198  }
1199  if (order > 1) // Order 1
1200  {
1201  tmp[0] = 0;
1202  tmp[1] = 1;
1203  for (int j = 2; j < nbSegCoef; j++)
1204  tmp[j] = segLength * tmp[j - 1];
1205  for (int j = 1; j < nbSegCoef; j++)
1206  tmp[j] *= j;
1207 
1208  for (int dim = 0; dim < 3; dim++) {
1209  for (int j = 1; j < nbSegCoef; j++) {
1210  L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1211  L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1212  }
1213  L.push_back(T(line, startIndex + 3 * (nbSegCoef + 1) + dim, -1));
1214  L.push_back(T(startIndex + 3 * (nbSegCoef + 1) + dim, line, 1));
1215  line++;
1216  }
1217  }
1218  if (order > 2) // Order 2
1219  {
1220  tmp[0] = 0;
1221  tmp[1] = 0;
1222  tmp[2] = 1;
1223  for (int j = 3; j < nbSegCoef; j++)
1224  tmp[j] = segLength * tmp[j - 1];
1225  for (int j = 2; j < nbSegCoef; j++)
1226  tmp[j] *= j * (j - 1);
1227 
1228  for (int dim = 0; dim < 3; dim++) {
1229  for (int j = 2; j < nbSegCoef; j++) {
1230  L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1231  L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1232  }
1233  L.push_back(T(line, startIndex + 3 * (nbSegCoef + 2) + dim, -2));
1234  L.push_back(T(startIndex + 3 * (nbSegCoef + 2) + dim, line, 2));
1235  line++;
1236  }
1237  }
1238  delete[] tmp;
1239  startIndex += 3 * nbSegCoef;
1240  }
1241 
1242  // Optimization matrix
1243 
1244  line = 0;
1245 
1246  nbSegCoef = m_needle.accessSegment(0).getOrder() + 1;
1247  int nbSegEq = nbSegCoef;
1248  double segLength = m_needle.accessSegment(0).getParametricLength();
1249 
1250  for (int j = 0; j < nbSegEq; j++) {
1251  // Bending minimization
1252  for (int k = 2; k < nbSegCoef; k++) {
1253  if (j > 1)
1254  for (int dim = 0; dim < 3; dim++)
1255  L.push_back(
1256  T(line + dim, 3 * k + dim, EI * pow(segLength, j + k - 3) * j * (j - 1) * k * (k - 1) / (j + k - 3)));
1257  }
1258  line += 3;
1259  }
1260 
1261  startIndex = 3 * nbSegCoef;
1262  int restIndex = 0;
1263  double currentRestParam = 0;
1264  int layerIndex = 0;
1265  double currentDepth = 0;
1266  double nextLayerDepth = m_layerLength.front();
1267  for (int i = 1; i < nbSegments; i++) {
1268  nbSegCoef = m_needle.accessSegment(i).getOrder() + 1;
1269  nbSegEq = nbSegCoef;
1270  segLength = m_needle.accessSegment(i).getParametricLength();
1271 
1272  double lseg = 0;
1273  double LsegMin = 0;
1274  double LsegMax = segLength;
1275  while (lseg < segLength) {
1276  double stiffnessPerUnitLength = m_stiffnessPerUnitLength.at(layerIndex);
1277 
1278  if (currentDepth - lseg + segLength > nextLayerDepth && layerIndex + 1 < (int)m_layerLength.size()) {
1279  LsegMax = nextLayerDepth - currentDepth;
1280  }
1281 
1282  for (int j = 0; j < nbSegEq; j++) {
1283  for (int k = 0; k < nbSegCoef; k++) {
1284  double c = 0;
1285  // Bending minimization
1286  if (j > 1 && k > 1)
1287  c += EI * (pow(LsegMax, j + k - 3) - pow(LsegMin, j + k - 3)) * j * (j - 1) * k * (k - 1) / (j + k - 3);
1288  // Tissue deformation minimization
1289  c += stiffnessPerUnitLength * (pow(LsegMax, j + k + 1) - pow(LsegMin, j + k + 1)) / (j + k + 1);
1290 
1291  for (int dim = 0; dim < 3; dim++)
1292  L.push_back(T(line + 3 * j + dim, startIndex + 3 * k + dim, c));
1293  }
1294  }
1295 
1296  double l = LsegMin;
1297  while (l < LsegMax) {
1299  currentRestParam,
1300  ((restIndex == m_tissue.accessPath().getNbSegments() - 1) ? currentRestParam : 0) +
1303  int nbRestSegCoef = p.getOrder() + 1;
1304 
1305  double Lmin = l;
1306  double Lmax = 0;
1307  if ((LsegMax - l) < p.getParametricLength() || restIndex == m_tissue.accessPath().getNbSegments() - 1) {
1308  Lmax = LsegMax;
1309  currentRestParam += (LsegMax - l) / m_restDilatationFactor.at(i);
1310  l = LsegMax;
1311  } else {
1312  Lmax = l + p.getParametricLength();
1313  l = Lmax;
1314  currentRestParam = 0;
1315  restIndex++;
1316  }
1317 
1318  vpMatrix coefP = p.getPolynomialCoefficients();
1319  for (int j = 0; j < nbSegEq; j++) {
1320  for (int k = 0; k < nbRestSegCoef; k++) {
1321  double c = stiffnessPerUnitLength * (pow(Lmax, j + k + 1) - pow(Lmin, j + k + 1)) / (j + k + 1);
1322  for (int dim = 0; dim < 3; dim++) {
1323  B(line + 3 * j + dim) += c * coefP[dim][k];
1324  }
1325  }
1326  }
1327  }
1328 
1329  if (LsegMax < segLength) {
1330  layerIndex++;
1331  nextLayerDepth += m_layerLength.at(layerIndex);
1332  lseg += LsegMax - LsegMin;
1333  } else
1334  lseg = segLength;
1335 
1336  currentDepth += LsegMax - LsegMin;
1337  LsegMin = LsegMax;
1338  LsegMax = segLength;
1339  }
1340 
1341  line += 3 * nbSegEq;
1342  startIndex += 3 * nbSegCoef;
1343  }
1344 
1345  line -= 3 * (m_needle.accessLastSegment().getOrder() + 1);
1346  startIndex -= 3 * (m_needle.accessLastSegment().getOrder() + 1);
1347 
1348  // Bevel
1349  {
1350  vpMatrix I;
1351  I.eye(3);
1352  vpRotationMatrix R(0, 0, 0);
1353 
1354  vpColVector bevelSegment = m_needleTip->getTipPosition() - m_needleTip->getBasePosition();
1355  double bevLength = bevelSegment.frobeniusNorm();
1356  bevelSegment.normalize();
1357  vpColVector p = vpColVector::crossProd(m_needleTip->getBaseAxisZ(), bevelSegment);
1358  R.buildFrom(p[0], p[1], p[2]);
1359 
1360  double segLength = m_needle.accessLastSegment().getParametricLength();
1361  double LbevMin = 0;
1362  if (currentDepth == 0) {
1363  double cosTheta = vpColVector::dotProd(m_tissue.accessSurface().getDirection(), bevelSegment);
1364  if (cosTheta > std::numeric_limits<double>::epsilon())
1365  LbevMin =
1367  cosTheta;
1368  else
1369  LbevMin = bevLength;
1370  }
1371  double lbev = LbevMin;
1372  double LbevMax = bevLength;
1373  while (lbev < bevLength) {
1374  double stiffnessPerUnitLength = m_stiffnessPerUnitLength.at(layerIndex);
1375 
1376  if (currentDepth - lbev + bevLength > nextLayerDepth && layerIndex + 1 < (int)m_layerLength.size()) {
1377  LbevMax = nextLayerDepth - currentDepth;
1378  }
1379 
1380  for (int j = 0; j < nbSegEq; j++) {
1381  for (int k = 0; k < nbSegCoef; k++) {
1382  double c0 = 0;
1383  double c1 = 0;
1384  double c2 = 0;
1385  double c3 = 0;
1386  // Tissue deformation minimization
1387  c0 = pow(segLength, j + k) * (LbevMax - LbevMin);
1388  if (j > 0)
1389  c1 = j * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
1390  if (k > 0)
1391  c2 = k * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
1392  if (j + k > 1)
1393  c3 = (j * k) * pow(segLength, j + k - 2) * (pow(LbevMax, 3) - pow(LbevMin, 3)) / 3;
1394 
1395  vpMatrix coefMat = stiffnessPerUnitLength * (c0 * I + c1 * R.t() + c2 * R + c3 * R.t() * R);
1396 
1397  for (int dimj = 0; dimj < 3; dimj++)
1398  for (int dimk = 0; dimk < 3; dimk++)
1399  L.push_back(T(line + 3 * j + dimj, startIndex + 3 * k + dimk, coefMat[dimj][dimk]));
1400  }
1401  }
1402 
1403  double l = LbevMin;
1404  while (l < LbevMax) {
1406  currentRestParam,
1407  ((restIndex == m_tissue.accessPath().getNbSegments() - 1) ? currentRestParam : 0) +
1410  int nbRestSegCoef = p.getOrder() + 1;
1411 
1412  double Lmin = l;
1413  double Lmax = 0;
1414  if ((LbevMax - l) < p.getParametricLength() || restIndex == m_tissue.accessPath().getNbSegments() - 1) {
1415  Lmax = LbevMax;
1416  currentRestParam += LbevMax - l;
1417  l = LbevMax;
1418  } else {
1419  Lmax = l + p.getParametricLength();
1420  l = Lmax;
1421  currentRestParam = 0;
1422  restIndex++;
1423  }
1424 
1425  vpMatrix coefP = p.getPolynomialCoefficients();
1426  for (int j = 0; j < nbSegEq; j++) {
1427  vpColVector b0(3, 0);
1428  vpColVector b1(3, 0);
1429  for (int k = 0; k < nbRestSegCoef; k++) {
1430  b0 += pow(segLength, j) * (pow(Lmax, k + 1) - pow(Lmin, k + 1)) / (k + 1) * coefP.getCol(k);
1431  }
1432  if (j > 0)
1433  for (int k = 0; k < nbRestSegCoef; k++) {
1434  b1 += j * pow(segLength, j - 1) * (pow(Lmax, k + 2) - pow(Lmin, k + 2)) / (k + 2) * coefP.getCol(k);
1435  }
1436  vpColVector coef = stiffnessPerUnitLength * (b0 + R.t() * b1);
1437 
1438  for (int dim = 0; dim < 3; dim++)
1439  B(line + 3 * j + dim) += coef[dim];
1440  }
1441  }
1442 
1443  if (LbevMax < bevLength) {
1444  layerIndex++;
1445  nextLayerDepth += m_layerLength.at(layerIndex);
1446  lbev += LbevMax - LbevMin;
1447  } else
1448  lbev = bevLength;
1449 
1450  currentDepth += LbevMax - LbevMin;
1451  LbevMin = LbevMax;
1452  LbevMax = bevLength;
1453  }
1454  }
1455 
1456  Eigen::SparseMatrix<double> M(nbMatrixLine, nbMatrixLine);
1457  M.setFromTriplets(L.begin(), L.end());
1458 
1459  Eigen::SparseLU<Eigen::SparseMatrix<double> > solver;
1460  solver.compute(M);
1461 
1462  A = solver.solve(B);
1463 
1464  // Update coefficients
1465  startIndex = 0;
1466  for (int i = 0; i < nbSegments; i++) {
1467  int order = m_needle.accessSegment(i).getOrder();
1468  vpMatrix m(3, order + 1);
1469  for (int j = 0; j < order + 1; j++) {
1470  for (int dim = 0; dim < 3; dim++) {
1471  m[dim][j] = A(startIndex + 3 * j + dim);
1472  }
1473  }
1475  startIndex += 3 * (order + 1);
1476  }
1477 #else
1478  throw vpException(vpException::functionNotImplementedError, "usNeedleInsertionModelRayleighRitzSpline::"
1479  "solveSegmentsParametersFullSparseEigen: not implemented "
1480  "without Eigen3");
1481 #endif
1482 }
1483 
1485 {
1486 #ifdef VISP_HAVE_EIGEN3
1487  if (m_tissue.accessPath().getNbSegments() == 0 ||
1488  m_needle.getFullLength() <= std::numeric_limits<double>::epsilon()) // no path present
1489  {
1491  vpMatrix M(3, seg.getOrder() + 1, 0);
1492  for (int dim = 0; dim < 3; dim++) {
1493  M[dim][0] = m_needle.getBasePose()[dim];
1494  M[dim][1] = m_needle.getWorldMbase()[dim][2];
1495  }
1498  m_needle.init();
1499  m_needle.setSegment(0, seg);
1500 
1501  return;
1502  }
1503 
1504  double trueFreeLength = 0;
1505 
1507  double freeLength = -1;
1509  int seg = -1;
1510  double param = 0;
1511  m_needle.getParametersFromLength(freeLength, seg, param);
1512 
1513  for (int i = 0; i < seg; i++) {
1514  trueFreeLength += m_needle.accessSegment(i).getLength();
1515  }
1516  trueFreeLength += m_needle.accessSegment(seg).getSubPolynomialCurve(0, param).getLength();
1517  } else {
1518  vpColVector p(3);
1519  for (int i = 0; i < 3; i++)
1520  p[i] = m_needle.getBasePose()[i];
1521  vpColVector d(3);
1522  for (int i = 0; i < 3; i++)
1523  d[i] = m_needle.getWorldMbase()[i][2];
1524  double cosTheta = vpColVector::dotProd(m_tissue.accessSurface().getDirection(), d);
1525  if (cosTheta > std::numeric_limits<double>::epsilon())
1526  trueFreeLength = fabs(usGeometryTools::getPointPlaneDistance(p, m_tissue.accessSurface())) / cosTheta;
1527  else
1528  trueFreeLength = m_needle.getFullLength();
1529  }
1530 
1532  if (trueFreeLength >= m_needle.getFullLength() && !tipIn) // needle is not inserted
1533  {
1535  vpMatrix M(3, seg.getOrder() + 1, 0);
1536  for (int dim = 0; dim < 3; dim++) {
1537  M[dim][0] = m_needle.getBasePose()[dim];
1538  M[dim][1] = m_needle.getWorldMbase()[dim][2];
1539  }
1542  m_needle.init();
1543  m_needle.setSegment(0, seg);
1544 
1545  return;
1546  }
1547 
1548  double segDefaultLength = 0.01;
1549  int nbSegments = 1 + floor(m_needle.getFullLength() / segDefaultLength);
1550 
1551  while (m_needle.getNbSegments() > nbSegments) {
1553  }
1554  while (m_needle.getNbSegments() < nbSegments) {
1556  }
1558  for (int i = 0; i < nbSegments - 1; i++)
1559  m_needle.accessSegment(i).setParametricLength(segDefaultLength);
1560  if (nbSegments > 1) {
1561  double l = m_needle.getFullLength() - segDefaultLength * (nbSegments - 1);
1562  if (l > std::numeric_limits<double>::epsilon())
1564  else {
1566  nbSegments--;
1567  }
1568  }
1569  int nbcoef = 0;
1570  for (int i = 0; i < nbSegments; i++)
1571  nbcoef += m_needle.accessSegment(i).getOrder() + 1;
1572 
1573  typedef Eigen::Triplet<double> T;
1574  std::vector<T> L;
1575 
1576  double EI = m_needle.getEI();
1577 
1578  int nbConstraints = 2;
1579  for (int i = 0; i < nbSegments - 1; i++) {
1580  int order1 = m_needle.accessSegment(i).getOrder();
1581  int order2 = m_needle.accessSegment(i + 1).getOrder();
1582  int order = std::max(order1, order2);
1583  nbConstraints += std::min(3, order);
1584  }
1585 
1586  int nbMatrixLine = 3 * (nbConstraints + nbcoef);
1587 
1588  L.reserve(nbMatrixLine * nbMatrixLine / 10);
1589 
1590  Eigen::VectorXd A = Eigen::VectorXd::Zero(nbMatrixLine);
1591  Eigen::VectorXd B = Eigen::VectorXd::Zero(nbMatrixLine);
1592 
1593  // Constraints matrix
1594 
1595  // Base conditions
1596  int line = 3 * nbcoef;
1597  for (int dim = 0; dim < 3; dim++) {
1598  B(line) = m_needle.getBasePose()[dim];
1599  L.push_back(T(line, dim, 1));
1600  L.push_back(T(dim, line, -1));
1601  line++;
1602  }
1603  for (int dim = 0; dim < 3; dim++) {
1604  B(line) = m_needle.getWorldMbase()[dim][2];
1605  L.push_back(T(line, 3 + dim, 1));
1606  L.push_back(T(3 + dim, line, -1));
1607  line++;
1608  }
1609 
1610  int nbSegCoef = 0;
1611  int startIndex = 0;
1612  for (int i = 0; i < nbSegments - 1; i++) {
1613  nbSegCoef = m_needle.accessSegment(i).getOrder() + 1;
1614  int order1 = m_needle.accessSegment(i).getOrder();
1615  int order2 = m_needle.accessSegment(i + 1).getOrder();
1616  int order = std::max(order1, order2);
1617  double segLength = m_needle.accessSegment(i).getParametricLength();
1618 
1619  // Continuity
1620 
1621  double *tmp = new double[nbSegCoef];
1622 
1623  if (order > 0) // Order 0
1624  {
1625  tmp[0] = 1;
1626  for (int j = 1; j < nbSegCoef; j++)
1627  tmp[j] = segLength * tmp[j - 1];
1628 
1629  for (int dim = 0; dim < 3; dim++) {
1630  for (int j = 0; j < nbSegCoef; j++) {
1631  L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1632  L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1633  }
1634  L.push_back(T(line, startIndex + 3 * nbSegCoef + dim, -1));
1635  L.push_back(T(startIndex + 3 * nbSegCoef + dim, line, 1));
1636  line++;
1637  }
1638  }
1639  if (order > 1) // Order 1
1640  {
1641  tmp[0] = 0;
1642  tmp[1] = 1;
1643  for (int j = 2; j < nbSegCoef; j++)
1644  tmp[j] = segLength * tmp[j - 1];
1645  for (int j = 1; j < nbSegCoef; j++)
1646  tmp[j] *= j;
1647 
1648  for (int dim = 0; dim < 3; dim++) {
1649  for (int j = 1; j < nbSegCoef; j++) {
1650  L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1651  L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1652  }
1653  L.push_back(T(line, startIndex + 3 * (nbSegCoef + 1) + dim, -1));
1654  L.push_back(T(startIndex + 3 * (nbSegCoef + 1) + dim, line, 1));
1655  line++;
1656  }
1657  }
1658  if (order > 2) // Order 2
1659  {
1660  tmp[0] = 0;
1661  tmp[1] = 0;
1662  tmp[2] = 1;
1663  for (int j = 3; j < nbSegCoef; j++)
1664  tmp[j] = segLength * tmp[j - 1];
1665  for (int j = 2; j < nbSegCoef; j++)
1666  tmp[j] *= j * (j - 1);
1667 
1668  for (int dim = 0; dim < 3; dim++) {
1669  for (int j = 2; j < nbSegCoef; j++) {
1670  L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1671  L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1672  }
1673  L.push_back(T(line, startIndex + 3 * (nbSegCoef + 2) + dim, -2));
1674  L.push_back(T(startIndex + 3 * (nbSegCoef + 2) + dim, line, 2));
1675  line++;
1676  }
1677  }
1678  delete[] tmp;
1679  startIndex += 3 * nbSegCoef;
1680  }
1681 
1682  // Optimization matrix
1683 
1684  line = 0;
1685 
1686  nbSegCoef = m_needle.accessSegment(0).getOrder() + 1;
1687  int nbSegEq = nbSegCoef;
1688  double segLength = m_needle.accessSegment(0).getParametricLength();
1689 
1690  startIndex = 0;
1691  int restIndex = 0;
1692  double currentRestParam = 0;
1693  int layerIndex = -1;
1694  double currentDepth = -trueFreeLength;
1695  double nextLayerDepth = 0;
1696  for (int i = 0; i < nbSegments; i++) {
1697  nbSegCoef = m_needle.accessSegment(i).getOrder() + 1;
1698  nbSegEq = nbSegCoef;
1699  segLength = m_needle.accessSegment(i).getParametricLength();
1700 
1701  double lseg = 0;
1702  double LsegMin = 0;
1703  double LsegMax = segLength;
1704  while (lseg < segLength) {
1705  double stiffnessPerUnitLength = 0;
1706  if (layerIndex >= 0)
1707  stiffnessPerUnitLength = m_stiffnessPerUnitLength.at(layerIndex);
1708 
1709  if (currentDepth - lseg + segLength > nextLayerDepth && layerIndex + 1 < (int)m_layerLength.size()) {
1710  LsegMax = nextLayerDepth - currentDepth;
1711  }
1712 
1713  for (int j = 0; j < nbSegEq; j++) {
1714  for (int k = 0; k < nbSegCoef; k++) {
1715  double c = 0;
1716  // Bending minimization
1717  if (j > 1 && k > 1)
1718  c += EI * (pow(LsegMax, j + k - 3) - pow(LsegMin, j + k - 3)) * j * (j - 1) * k * (k - 1) / (j + k - 3);
1719  // if(i==0) c*=100;
1720  // Tissue deformation minimization
1721  c += stiffnessPerUnitLength * (pow(LsegMax, j + k + 1) - pow(LsegMin, j + k + 1)) / (j + k + 1);
1722 
1723  for (int dim = 0; dim < 3; dim++)
1724  L.push_back(T(line + 3 * j + dim, startIndex + 3 * k + dim, c));
1725  }
1726  }
1727 
1728  if (layerIndex >= 0) {
1729  double l = LsegMin;
1730  double factor = m_restDilatationFactor.at(i);
1731  while (l < LsegMax) {
1733  currentRestParam,
1734  ((restIndex == m_tissue.accessPath().getNbSegments() - 1) ? currentRestParam : 0) +
1737  int nbRestSegCoef = p.getOrder() + 1;
1738 
1739  double Lmin = l;
1740  double Lmax = 0;
1741  if ((LsegMax - l) < p.getParametricLength() || restIndex == m_tissue.accessPath().getNbSegments() - 1) {
1742  Lmax = LsegMax;
1743  currentRestParam += (LsegMax - l) / factor;
1744  l = LsegMax;
1745  } else {
1746  Lmax = l + p.getParametricLength();
1747  l = Lmax;
1748  currentRestParam = 0;
1749  restIndex++;
1750  }
1751 
1752  vpMatrix coefP = p.getPolynomialCoefficients();
1753  for (int j = 0; j < nbSegEq; j++) {
1754  for (int k = 0; k < nbRestSegCoef; k++) {
1755  double c = stiffnessPerUnitLength * (pow(Lmax, j + k + 1) - pow(Lmin, j + k + 1)) / (j + k + 1);
1756  for (int dim = 0; dim < 3; dim++) {
1757  B(line + 3 * j + dim) += c * coefP[dim][k];
1758  }
1759  }
1760  }
1761  }
1762  }
1763 
1764  if (LsegMax < segLength) {
1765  layerIndex++;
1766  nextLayerDepth += m_layerLength.at(layerIndex);
1767  lseg += LsegMax - LsegMin;
1768  } else
1769  lseg = segLength;
1770 
1771  currentDepth += LsegMax - LsegMin;
1772  LsegMin = LsegMax;
1773  LsegMax = segLength;
1774  }
1775 
1776  line += 3 * nbSegEq;
1777  startIndex += 3 * nbSegCoef;
1778  }
1779 
1780  line -= 3 * (m_needle.accessLastSegment().getOrder() + 1);
1781  startIndex -= 3 * (m_needle.accessLastSegment().getOrder() + 1);
1782 
1783  // Bevel
1784  {
1785  if (layerIndex < 0) {
1786  layerIndex = 0;
1787  currentDepth = 0;
1788  }
1789  vpMatrix I;
1790  I.eye(3);
1791  vpRotationMatrix R(0, 0, 0);
1792 
1793  vpColVector bevelSegment = m_needleTip->getTipPosition() - m_needleTip->getBasePosition();
1794  double bevLength = bevelSegment.frobeniusNorm();
1795  bevelSegment.normalize();
1796  vpColVector p = vpColVector::crossProd(m_needleTip->getBaseAxisZ(), bevelSegment);
1797  R.buildFrom(p[0], p[1], p[2]);
1798 
1799  double segLength = m_needle.accessLastSegment().getParametricLength();
1800  double LbevMin = 0;
1801  if (currentDepth == 0) {
1802  double cosTheta = vpColVector::dotProd(m_tissue.accessSurface().getDirection(), bevelSegment);
1803  if (cosTheta > std::numeric_limits<double>::epsilon())
1804  LbevMin =
1806  cosTheta;
1807  else
1808  LbevMin = bevLength;
1809  }
1810  double lbev = LbevMin;
1811  double LbevMax = bevLength;
1812  while (lbev < bevLength) {
1813  double stiffnessPerUnitLength = m_stiffnessPerUnitLength.at(layerIndex);
1814 
1815  if (currentDepth - lbev + bevLength > nextLayerDepth && layerIndex + 1 < (int)m_layerLength.size()) {
1816  LbevMax = nextLayerDepth - currentDepth;
1817  }
1818 
1819  for (int j = 0; j < nbSegEq; j++) {
1820  for (int k = 0; k < nbSegCoef; k++) {
1821  double c0 = 0;
1822  double c1 = 0;
1823  double c2 = 0;
1824  double c3 = 0;
1825  // Tissue deformation minimization
1826  c0 = pow(segLength, j + k) * (LbevMax - LbevMin);
1827  if (j > 0)
1828  c1 = j * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
1829  if (k > 0)
1830  c2 = k * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
1831  if (j + k > 1)
1832  c3 = (j * k) * pow(segLength, j + k - 2) * (pow(LbevMax, 3) - pow(LbevMin, 3)) / 3;
1833 
1834  vpMatrix coefMat = stiffnessPerUnitLength * (c0 * I + c1 * R.t() + c2 * R + c3 * R.t() * R);
1835 
1836  for (int dimj = 0; dimj < 3; dimj++)
1837  for (int dimk = 0; dimk < 3; dimk++)
1838  L.push_back(T(line + 3 * j + dimj, startIndex + 3 * k + dimk, coefMat[dimj][dimk]));
1839  }
1840  }
1841 
1842  double l = LbevMin;
1843  while (l < LbevMax) {
1845  currentRestParam,
1846  ((restIndex == m_tissue.accessPath().getNbSegments() - 1) ? currentRestParam : 0) +
1849  int nbRestSegCoef = p.getOrder() + 1;
1850 
1851  double Lmin = l;
1852  double Lmax = 0;
1853  if ((LbevMax - l) < p.getParametricLength() || restIndex == m_tissue.accessPath().getNbSegments() - 1) {
1854  Lmax = LbevMax;
1855  currentRestParam += LbevMax - l;
1856  l = LbevMax;
1857  } else {
1858  Lmax = l + p.getParametricLength();
1859  l = Lmax;
1860  currentRestParam = 0;
1861  restIndex++;
1862  }
1863 
1864  vpMatrix coefP = p.getPolynomialCoefficients();
1865  for (int j = 0; j < nbSegEq; j++) {
1866  vpColVector b0(3, 0);
1867  vpColVector b1(3, 0);
1868  for (int k = 0; k < nbRestSegCoef; k++) {
1869  b0 += pow(segLength, j) * (pow(Lmax, k + 1) - pow(Lmin, k + 1)) / (k + 1) * coefP.getCol(k);
1870  }
1871  if (j > 0)
1872  for (int k = 0; k < nbRestSegCoef; k++) {
1873  b1 += j * pow(segLength, j - 1) * (pow(Lmax, k + 2) - pow(Lmin, k + 2)) / (k + 2) * coefP.getCol(k);
1874  }
1875  vpColVector coef = stiffnessPerUnitLength * (b0 + R.t() * b1);
1876 
1877  for (int dim = 0; dim < 3; dim++)
1878  B(line + 3 * j + dim) += coef[dim];
1879  }
1880  }
1881 
1882  if (LbevMax < bevLength) {
1883  layerIndex++;
1884  nextLayerDepth += m_layerLength.at(layerIndex);
1885  lbev += LbevMax - LbevMin;
1886  } else
1887  lbev = bevLength;
1888 
1889  currentDepth += LbevMax - LbevMin;
1890  LbevMin = LbevMax;
1891  LbevMax = bevLength;
1892  }
1893  }
1894 
1895  Eigen::SparseMatrix<double> M(nbMatrixLine, nbMatrixLine);
1896  M.setFromTriplets(L.begin(), L.end());
1897 
1898  Eigen::SparseLU<Eigen::SparseMatrix<double> > solver;
1899  solver.compute(M);
1900 
1901  A = solver.solve(B);
1902 
1903  // Update coefficients
1904  startIndex = 0;
1905  for (int i = 0; i < nbSegments; i++) {
1906  int order = m_needle.accessSegment(i).getOrder();
1907  vpMatrix m(3, order + 1);
1908  for (int j = 0; j < order + 1; j++) {
1909  for (int dim = 0; dim < 3; dim++) {
1910  m[dim][j] = A(startIndex + 3 * j + dim);
1911  }
1912  }
1914  startIndex += 3 * (order + 1);
1915  }
1916 #else
1917  throw vpException(vpException::functionNotImplementedError, "usNeedleInsertionModelRayleighRitzSpline::"
1918  "solveSegmentsParametersFullSparseEigenFixedLength: not "
1919  "implemented without Eigen3");
1920 #endif
1921 }
1922 
1924 {
1925  if (m_tissue.accessPath().getNbSegments() == 0 ||
1926  m_needle.getFullLength() <= std::numeric_limits<double>::epsilon()) // no path present
1927  {
1929  vpMatrix M(3, seg.getOrder() + 1, 0);
1930  for (int dim = 0; dim < 3; dim++) {
1931  M[dim][0] = m_needle.getBasePose()[dim];
1932  M[dim][1] = m_needle.getWorldMbase()[dim][2];
1933  }
1936  m_needle.init();
1937  m_needle.setSegment(0, seg);
1938 
1939  return;
1940  }
1941 
1942  double trueFreeLength = 0;
1943 
1945  double freeLength = -1;
1947  int seg = -1;
1948  double param = 0;
1949  m_needle.getParametersFromLength(freeLength, seg, param);
1950 
1951  for (int i = 0; i < seg; i++) {
1952  trueFreeLength += m_needle.accessSegment(i).getLength();
1953  }
1954  trueFreeLength += m_needle.accessSegment(seg).getSubPolynomialCurve(0, param).getLength();
1955  } else {
1956  vpColVector p(3);
1957  for (int i = 0; i < 3; i++)
1958  p[i] = m_needle.getBasePose()[i];
1959  vpColVector d(3);
1960  for (int i = 0; i < 3; i++)
1961  d[i] = m_needle.getWorldMbase()[i][2];
1962  double cosTheta = vpColVector::dotProd(m_tissue.accessSurface().getDirection(), d);
1963  if (cosTheta > std::numeric_limits<double>::epsilon())
1964  trueFreeLength = fabs(usGeometryTools::getPointPlaneDistance(p, m_tissue.accessSurface())) / cosTheta;
1965  else
1966  trueFreeLength = m_needle.getFullLength();
1967  }
1968 
1970  if (trueFreeLength >= m_needle.getFullLength() && !tipIn) // needle is not inserted
1971  {
1973  vpMatrix M(3, seg.getOrder() + 1, 0);
1974  for (int dim = 0; dim < 3; dim++) {
1975  M[dim][0] = m_needle.getBasePose()[dim];
1976  M[dim][1] = m_needle.getWorldMbase()[dim][2];
1977  }
1980  m_needle.init();
1981  m_needle.setSegment(0, seg);
1982 
1983  return;
1984  }
1985 
1986  double segDefaultLength = 0.01;
1987  int nbSegments = 1 + floor(m_needle.getFullLength() / segDefaultLength);
1988 
1989  while (m_needle.getNbSegments() > nbSegments) {
1991  }
1992  while (m_needle.getNbSegments() < nbSegments) {
1994  }
1996  for (int i = 0; i < nbSegments - 1; i++)
1997  m_needle.accessSegment(i).setParametricLength(segDefaultLength);
1998  if (nbSegments > 1) {
1999  double l = m_needle.getFullLength() - segDefaultLength * (nbSegments - 1);
2000  if (l > std::numeric_limits<double>::epsilon())
2002  else {
2004  nbSegments--;
2005  }
2006  }
2007  int nbcoef = 0;
2008  for (int i = 0; i < nbSegments; i++)
2009  nbcoef += m_needle.accessSegment(i).getOrder() + 1;
2010 
2011  double EI = m_needle.getEI();
2012 
2013  int nbConstraints = 2;
2014  for (int i = 0; i < nbSegments - 1; i++) {
2015  int order1 = m_needle.accessSegment(i).getOrder();
2016  int order2 = m_needle.accessSegment(i + 1).getOrder();
2017  int order = std::max(order1, order2);
2018  nbConstraints += std::min(3, order);
2019  }
2020 
2021  int nbMatrixLine = 3 * (nbConstraints + nbcoef);
2022 
2023  vpMatrix M(nbMatrixLine, nbMatrixLine, 0);
2024 
2025  vpColVector A(nbMatrixLine, 0);
2026  vpColVector B(nbMatrixLine, 0);
2027 
2028  // Constraints matrix
2029 
2030  // Base conditions
2031  int line = 3 * nbcoef;
2032  for (int dim = 0; dim < 3; dim++) {
2033  B[line] = m_needle.getBasePose()[dim];
2034  M[line][dim] = 1;
2035  M[dim][line] = -1;
2036  line++;
2037  }
2038  for (int dim = 0; dim < 3; dim++) {
2039  B[line] = m_needle.getWorldMbase()[dim][2];
2040  M[line][3 + dim] = 1;
2041  M[3 + dim][line] = -1;
2042  line++;
2043  }
2044 
2045  int nbSegCoef = 0;
2046  int startIndex = 0;
2047  for (int i = 0; i < nbSegments - 1; i++) {
2048  nbSegCoef = m_needle.accessSegment(i).getOrder() + 1;
2049  int order1 = m_needle.accessSegment(i).getOrder();
2050  int order2 = m_needle.accessSegment(i + 1).getOrder();
2051  int order = std::max(order1, order2);
2052  double segLength = m_needle.accessSegment(i).getParametricLength();
2053 
2054  // Continuity
2055 
2056  double *tmp = new double[nbSegCoef];
2057  if (order > 0) // Order 0
2058  {
2059  tmp[0] = 1;
2060  for (int j = 1; j < nbSegCoef; j++)
2061  tmp[j] = segLength * tmp[j - 1];
2062 
2063  for (int dim = 0; dim < 3; dim++) {
2064  for (int j = 0; j < nbSegCoef; j++) {
2065  M[line][startIndex + 3 * j + dim] = tmp[j];
2066  M[startIndex + 3 * j + dim][line] = -tmp[j];
2067  }
2068  M[line][startIndex + 3 * nbSegCoef + dim] = -1;
2069  M[startIndex + 3 * nbSegCoef + dim][line] = 1;
2070  line++;
2071  }
2072  }
2073  if (order > 1) // Order 1
2074  {
2075  tmp[0] = 0;
2076  tmp[1] = 1;
2077  for (int j = 2; j < nbSegCoef; j++)
2078  tmp[j] = segLength * tmp[j - 1];
2079  for (int j = 1; j < nbSegCoef; j++)
2080  tmp[j] *= j;
2081 
2082  for (int dim = 0; dim < 3; dim++) {
2083  for (int j = 1; j < nbSegCoef; j++) {
2084  M[line][startIndex + 3 * j + dim] = tmp[j];
2085  M[startIndex + 3 * j + dim][line] = -tmp[j];
2086  }
2087  M[line][startIndex + 3 * (nbSegCoef + 1) + dim] = -1;
2088  M[startIndex + 3 * (nbSegCoef + 1) + dim][line] = 1;
2089  line++;
2090  }
2091  }
2092  if (order > 2) // Order 2
2093  {
2094  tmp[0] = 0;
2095  tmp[1] = 0;
2096  tmp[2] = 1;
2097  for (int j = 3; j < nbSegCoef; j++)
2098  tmp[j] = segLength * tmp[j - 1];
2099  for (int j = 2; j < nbSegCoef; j++)
2100  tmp[j] *= j * (j - 1);
2101 
2102  for (int dim = 0; dim < 3; dim++) {
2103  for (int j = 2; j < nbSegCoef; j++) {
2104  M[line][startIndex + 3 * j + dim] = tmp[j];
2105  M[startIndex + 3 * j + dim][line] = -tmp[j];
2106  }
2107  M[line][startIndex + 3 * (nbSegCoef + 2) + dim] = -2;
2108  M[startIndex + 3 * (nbSegCoef + 2) + dim][line] = 2;
2109  line++;
2110  }
2111  }
2112  delete[] tmp;
2113  startIndex += 3 * nbSegCoef;
2114  }
2115 
2116  // Optimization matrix
2117 
2118  line = 0;
2119 
2120  nbSegCoef = m_needle.accessSegment(0).getOrder() + 1;
2121  int nbSegEq = nbSegCoef;
2122  double segLength = m_needle.accessSegment(0).getParametricLength();
2123 
2124  startIndex = 0;
2125  int restIndex = 0;
2126  double currentRestParam = 0;
2127  int layerIndex = -1;
2128  double currentDepth = -trueFreeLength;
2129  double nextLayerDepth = 0;
2130  for (int i = 0; i < nbSegments; i++) {
2131  nbSegCoef = m_needle.accessSegment(i).getOrder() + 1;
2132  nbSegEq = nbSegCoef;
2133  segLength = m_needle.accessSegment(i).getParametricLength();
2134 
2135  double lseg = 0;
2136  double LsegMin = 0;
2137  double LsegMax = segLength;
2138  while (lseg < segLength) {
2139  double stiffnessPerUnitLength = 0;
2140  if (layerIndex >= 0)
2141  stiffnessPerUnitLength = m_stiffnessPerUnitLength.at(layerIndex);
2142 
2143  if (currentDepth - lseg + segLength > nextLayerDepth && layerIndex + 1 < (int)m_layerLength.size()) {
2144  LsegMax = nextLayerDepth - currentDepth;
2145  }
2146 
2147  for (int j = 0; j < nbSegEq; j++) {
2148  for (int k = 0; k < nbSegCoef; k++) {
2149  double c = 0;
2150  // Bending minimization
2151  if (j > 1 && k > 1)
2152  c += EI * (pow(LsegMax, j + k - 3) - pow(LsegMin, j + k - 3)) * j * (j - 1) * k * (k - 1) / (j + k - 3);
2153  // if(i==0) c*=100;
2154  // Tissue deformation minimization
2155  c += stiffnessPerUnitLength * (pow(LsegMax, j + k + 1) - pow(LsegMin, j + k + 1)) / (j + k + 1);
2156 
2157  for (int dim = 0; dim < 3; dim++)
2158  M[line + 3 * j + dim][startIndex + 3 * k + dim] = c;
2159  }
2160  }
2161 
2162  if (layerIndex >= 0) {
2163  double l = LsegMin;
2164  double factor = m_restDilatationFactor.at(i);
2165  while (l < LsegMax) {
2167  currentRestParam,
2168  ((restIndex == m_tissue.accessPath().getNbSegments() - 1) ? currentRestParam : 0) +
2171  int nbRestSegCoef = p.getOrder() + 1;
2172 
2173  double Lmin = l;
2174  double Lmax = 0;
2175  if ((LsegMax - l) < p.getParametricLength() || restIndex == m_tissue.accessPath().getNbSegments() - 1) {
2176  Lmax = LsegMax;
2177  currentRestParam += (LsegMax - l) / factor;
2178  l = LsegMax;
2179  } else {
2180  Lmax = l + p.getParametricLength();
2181  l = Lmax;
2182  currentRestParam = 0;
2183  restIndex++;
2184  }
2185 
2186  vpMatrix coefP = p.getPolynomialCoefficients();
2187  for (int j = 0; j < nbSegEq; j++) {
2188  for (int k = 0; k < nbRestSegCoef; k++) {
2189  double c = stiffnessPerUnitLength * (pow(Lmax, j + k + 1) - pow(Lmin, j + k + 1)) / (j + k + 1);
2190  for (int dim = 0; dim < 3; dim++) {
2191  B[line + 3 * j + dim] += c * coefP[dim][k];
2192  }
2193  }
2194  }
2195  }
2196  }
2197 
2198  if (LsegMax < segLength) {
2199  layerIndex++;
2200  nextLayerDepth += m_layerLength.at(layerIndex);
2201  lseg += LsegMax - LsegMin;
2202  } else
2203  lseg = segLength;
2204 
2205  currentDepth += LsegMax - LsegMin;
2206  LsegMin = LsegMax;
2207  LsegMax = segLength;
2208  }
2209 
2210  line += 3 * nbSegEq;
2211  startIndex += 3 * nbSegCoef;
2212  }
2213 
2214  line -= 3 * (m_needle.accessLastSegment().getOrder() + 1);
2215  startIndex -= 3 * (m_needle.accessLastSegment().getOrder() + 1);
2216 
2217  // Bevel
2218  {
2219  if (layerIndex < 0) {
2220  layerIndex = 0;
2221  currentDepth = 0;
2222  }
2223  vpMatrix I;
2224  I.eye(3);
2225  vpRotationMatrix R(0, 0, 0);
2226 
2227  vpColVector bevelSegment = m_needleTip->getTipPosition() - m_needleTip->getBasePosition();
2228  double bevLength = bevelSegment.frobeniusNorm();
2229  bevelSegment.normalize();
2230  vpColVector p = vpColVector::crossProd(m_needleTip->getBaseAxisZ(), bevelSegment);
2231  R.buildFrom(p[0], p[1], p[2]);
2232 
2233  double segLength = m_needle.accessLastSegment().getParametricLength();
2234  double LbevMin = 0;
2235  if (currentDepth == 0) {
2236  double cosTheta = vpColVector::dotProd(m_tissue.accessSurface().getDirection(), bevelSegment);
2237  if (cosTheta > std::numeric_limits<double>::epsilon())
2238  LbevMin =
2240  cosTheta;
2241  else
2242  LbevMin = bevLength;
2243  }
2244  double lbev = LbevMin;
2245  double LbevMax = bevLength;
2246  while (lbev < bevLength) {
2247  double stiffnessPerUnitLength = m_stiffnessPerUnitLength.at(layerIndex);
2248 
2249  if (currentDepth - lbev + bevLength > nextLayerDepth && layerIndex + 1 < (int)m_layerLength.size()) {
2250  LbevMax = nextLayerDepth - currentDepth;
2251  }
2252 
2253  for (int j = 0; j < nbSegEq; j++) {
2254  for (int k = 0; k < nbSegCoef; k++) {
2255  double c0 = 0;
2256  double c1 = 0;
2257  double c2 = 0;
2258  double c3 = 0;
2259  // Tissue deformation minimization
2260  c0 = pow(segLength, j + k) * (LbevMax - LbevMin);
2261  if (j > 0)
2262  c1 = j * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
2263  if (k > 0)
2264  c2 = k * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
2265  if (j + k > 1)
2266  c3 = (j * k) * pow(segLength, j + k - 2) * (pow(LbevMax, 3) - pow(LbevMin, 3)) / 3;
2267 
2268  vpMatrix coefMat = stiffnessPerUnitLength * (c0 * I + c1 * R.t() + c2 * R + c3 * R.t() * R);
2269 
2270  for (int dimj = 0; dimj < 3; dimj++)
2271  for (int dimk = 0; dimk < 3; dimk++)
2272  M[line + 3 * j + dimj][startIndex + 3 * k + dimk] += coefMat[dimj][dimk];
2273  }
2274  }
2275 
2276  double l = LbevMin;
2277  while (l < LbevMax) {
2279  currentRestParam,
2280  ((restIndex == m_tissue.accessPath().getNbSegments() - 1) ? currentRestParam : 0) +
2283  int nbRestSegCoef = p.getOrder() + 1;
2284 
2285  double Lmin = l;
2286  double Lmax = 0;
2287  if ((LbevMax - l) < p.getParametricLength() || restIndex == m_tissue.accessPath().getNbSegments() - 1) {
2288  Lmax = LbevMax;
2289  currentRestParam += LbevMax - l;
2290  l = LbevMax;
2291  } else {
2292  Lmax = l + p.getParametricLength();
2293  l = Lmax;
2294  currentRestParam = 0;
2295  restIndex++;
2296  }
2297 
2298  vpMatrix coefP = p.getPolynomialCoefficients();
2299  for (int j = 0; j < nbSegEq; j++) {
2300  vpColVector b0(3, 0);
2301  vpColVector b1(3, 0);
2302  for (int k = 0; k < nbRestSegCoef; k++) {
2303  b0 += pow(segLength, j) * (pow(Lmax, k + 1) - pow(Lmin, k + 1)) / (k + 1) * coefP.getCol(k);
2304  }
2305  if (j > 0)
2306  for (int k = 0; k < nbRestSegCoef; k++) {
2307  b1 += j * pow(segLength, j - 1) * (pow(Lmax, k + 2) - pow(Lmin, k + 2)) / (k + 2) * coefP.getCol(k);
2308  }
2309  vpColVector coef = stiffnessPerUnitLength * (b0 + R.t() * b1);
2310 
2311  for (int dim = 0; dim < 3; dim++)
2312  B[line + 3 * j + dim] += coef[dim];
2313  }
2314  }
2315 
2316  if (LbevMax < bevLength) {
2317  layerIndex++;
2318  nextLayerDepth += m_layerLength.at(layerIndex);
2319  lbev += LbevMax - LbevMin;
2320  } else
2321  lbev = bevLength;
2322 
2323  currentDepth += LbevMax - LbevMin;
2324  LbevMin = LbevMax;
2325  LbevMax = bevLength;
2326  }
2327  }
2328 
2329  A = M.inverseByLU() * B;
2330 
2331  // Update coefficients
2332  startIndex = 0;
2333  for (int i = 0; i < nbSegments; i++) {
2334  int order = m_needle.accessSegment(i).getOrder();
2335  vpMatrix m(3, order + 1);
2336  for (int j = 0; j < order + 1; j++) {
2337  for (int dim = 0; dim < 3; dim++) {
2338  m[dim][j] = A[startIndex + 3 * j + dim];
2339  }
2340  }
2342  startIndex += 3 * (order + 1);
2343  }
2344 }
2345 
2347 {
2348  double l = 0;
2349  double length = m_needle.getFullLength();
2350  int i = 0;
2351  double trueLength = 0;
2352 
2353  while (i < m_needle.getNbSegments() && l < length) {
2354  trueLength = m_needle.accessSegment(i).getLength();
2355 
2356  l += trueLength;
2358 
2359  i++;
2360  }
2361  if (i < m_needle.getNbSegments())
2363 
2364  double lastSegLength = m_needle.getFullLength() - (l - trueLength);
2368 }
2369 
2371 {
2372  vpColVector pt(m_needle.accessLastSegment().getEndPoint());
2373  vpTranslationVector t(pt[0], pt[1], pt[2]);
2374 
2375  vpColVector vect =
2377  double dot =
2379  double theta = atan2(vect.frobeniusNorm(), dot);
2380  vect.normalize();
2381  vect = theta * vect;
2382  vpThetaUVector thetaU(vect[0], vect[1], vect[2]);
2383  vpRotationMatrix R(thetaU);
2384  vpRotationMatrix worldRtip(m_needle.getWorldMbase());
2385  worldRtip = R * worldRtip;
2386 
2387  vpPoseVector tipPose(t, worldRtip);
2388  m_needle.setTipPose(tipPose);
2389  m_needleTip->setBasePose(tipPose);
2390 }
2391 
2393 {
2394 #ifdef VISP_HAVE_EIGEN3
2395  switch (m_solvingMethod) {
2398  break;
2401  break;
2404  break;
2405  }
2406 #else
2408 #endif
2409 }
2410 
2412 {
2413  int loopIndex = 0;
2414  do {
2415  this->solveSegmentsParameters();
2416 
2417  this->fitLength();
2418 
2419  this->updateTipPose();
2420 
2421  if (this->IsNeedleInserted() && m_tissue.accessPath().getNbSegments() > 0) {
2424  double l = this->getInsertionDepth();
2425  double restLength = -1;
2427  &restLength);
2428 
2429  for (unsigned int i = 0; i < m_restDilatationFactor.size(); i++)
2430  m_restDilatationFactor.at(i) = l / restLength;
2431  } else {
2434  double l = -1;
2435  double restLength = m_tissue.accessPath().getParametricLength();
2437  l -= this->getNeedleFreeLength();
2438 
2439  for (unsigned int i = 0; i < m_restDilatationFactor.size(); i++)
2440  m_restDilatationFactor.at(i) = l / restLength;
2441  } else
2442  for (unsigned int i = 0; i < m_restDilatationFactor.size(); i++)
2443  m_restDilatationFactor.at(i) = 1;
2444  }
2445 
2446  this->solveSegmentsParameters();
2447 
2448  this->fitLength();
2449 
2450  this->updateTipPose();
2451  }
2452  loopIndex++;
2453  } while (this->updatePath() && (loopIndex < 2));
2454 
2455  return true;
2456 }
2457 
2459 {
2460  switch (m_pathUpdateType) {
2461  case PathUpdateType::NoUpdate: {
2462  return false;
2463  }
2465  return this->cutPathToPoint(m_needleTip->getTipPosition());
2466  }
2468  vpColVector lastPoint(3);
2469  vpColVector lastDirection(3);
2470  int restIndex = -1;
2471  double restParam = -1;
2472  if (m_tissue.accessPath().getNbSegments() > 0) {
2475  restIndex, restParam);
2477  lastDirection = m_tissue.accessPath().accessLastSegment().getEndTangent();
2479  lastDirection = m_needleTip->getTipDirection();
2480  lastPoint =
2482  } else
2483  return false;
2484 
2485  double insertionStep = 0;
2486 
2487  if (m_tissue.accessPath().getNbSegments() > 0 && restIndex == m_tissue.accessPath().getNbSegments() - 1) {
2488  insertionStep = restParam - m_tissue.accessPath().accessSegment(restIndex).getParametricLength();
2489  } else if (m_tissue.accessPath().getNbSegments() == 0) {
2490  insertionStep = vpColVector::dotProd(m_needleTip->getTipPosition() - lastPoint, lastDirection);
2491  } else
2492  return false;
2493 
2494  if (insertionStep > m_pathUpdateLengthThreshold) {
2495  usPolynomialCurve3D seg(1);
2496  vpMatrix M(3, 2);
2497  M.insert(lastPoint, 0, 0);
2498 
2499  vpColVector u = insertionStep * m_needleTip->getTipDirection();
2500 
2501  M.insert((1 * u).normalize(), 0, 1);
2503  seg.setParametricLength(u.frobeniusNorm());
2505  return true;
2506  } else
2507  return false;
2508  }
2510  vpColVector lastPoint(3);
2511  vpColVector lastDirection(3);
2512  int restIndex = -1;
2513  double restParam = -1;
2514  if (m_tissue.accessPath().getNbSegments() > 0) {
2517  restIndex, restParam);
2519  lastDirection = m_tissue.accessPath().accessLastSegment().getEndTangent();
2521  lastDirection = m_needleTip->getTipDirection();
2522  lastPoint =
2524  } else
2525  return false;
2526 
2527  double insertionStep = 0;
2528 
2529  if (m_tissue.accessPath().getNbSegments() > 0 && restIndex == m_tissue.accessPath().getNbSegments() - 1) {
2530  insertionStep = restParam - m_tissue.accessPath().accessSegment(restIndex).getParametricLength();
2531  } else if (m_tissue.accessPath().getNbSegments() == 0) {
2532  insertionStep = vpColVector::dotProd(m_needleTip->getTipPosition() - lastPoint, lastDirection);
2533  } else
2534  return false;
2535 
2536  if (insertionStep > m_pathUpdateLengthThreshold) {
2537  usPolynomialCurve3D seg(1);
2538  vpMatrix M(3, 2);
2539  M.insert(lastPoint, 0, 0);
2540 
2541  vpColVector newPoint = m_pathUpdateMixCoefficient * (lastPoint + insertionStep * m_needleTip->getTipDirection()) +
2543 
2544  M.insert((newPoint - lastPoint).normalize(), 0, 1);
2546  seg.setParametricLength((newPoint - lastPoint).frobeniusNorm());
2548  return true;
2549  } else
2550  return false;
2551  }
2552  default:
2553  return false;
2554  }
2555 }
2556 
2557 std::ostream &operator<<(std::ostream &s, const usNeedleInsertionModelRayleighRitzSpline &model)
2558 {
2559  s << "usNeedleInsertionModelRayleighRitzSpline\n";
2560 
2561  s << model.m_needle;
2562 
2563  switch (model.m_needleTipType) {
2565  s << 0 << '\n';
2566  s << *dynamic_cast<usNeedleTipActuated *>(model.m_needleTip);
2567  break;
2568  }
2570  s << 1 << '\n';
2571  ;
2572  s << *dynamic_cast<usNeedleTipBeveled *>(model.m_needleTip);
2573  break;
2574  }
2576  s << 2 << '\n';
2577  s << *dynamic_cast<usNeedleTipPrebent *>(model.m_needleTip);
2578  break;
2579  }
2581  s << 3 << '\n';
2582  s << *dynamic_cast<usNeedleTipSymmetric *>(model.m_needleTip);
2583  break;
2584  }
2585  }
2586 
2587  s << model.m_tissue;
2588 
2589  int n = model.m_stiffnessPerUnitLength.size();
2590  s << n << '\n';
2591  for (int i = 0; i < n; i++)
2592  s << model.m_stiffnessPerUnitLength.at(i) << '\n';
2593  for (int i = 0; i < n; i++)
2594  s << model.m_layerLength.at(i) << '\n';
2595 
2596  n = model.m_restDilatationFactor.size();
2597  s << n << '\n';
2598  for (int i = 0; i < n; i++)
2599  s << model.m_restDilatationFactor.at(i) << '\n';
2600 
2601  s.flush();
2602  return s;
2603 }
2604 
2605 std::istream &operator>>(std::istream &s, usNeedleInsertionModelRayleighRitzSpline &model)
2606 {
2607  std::string c;
2608  s >> c;
2609  if (c != "usNeedleInsertionModelRayleighRitzSpline") {
2610  vpException e(vpException::ioError, "Stream does not contain usNeedleInsertionModelRayleighRitzSpline data");
2611  throw e;
2612  }
2613 
2614  s >> model.m_needle;
2615 
2616  int t;
2617  s >> t;
2618  switch (t) {
2619  case 0: {
2621  s >> *dynamic_cast<usNeedleTipActuated *>(model.m_needleTip);
2622  break;
2623  }
2624  case 1: {
2626  s >> *dynamic_cast<usNeedleTipBeveled *>(model.m_needleTip);
2627  break;
2628  }
2629  case 2: {
2631  s >> *dynamic_cast<usNeedleTipPrebent *>(model.m_needleTip);
2632  break;
2633  }
2634  case 3: {
2636  s >> *dynamic_cast<usNeedleTipSymmetric *>(model.m_needleTip);
2637  break;
2638  }
2639  }
2640 
2641  s >> model.m_tissue;
2642  int n;
2643  s >> n;
2644  model.m_stiffnessPerUnitLength.resize(n);
2645  model.m_layerLength.resize(n);
2646  for (int i = 0; i < n; i++)
2647  s >> model.m_stiffnessPerUnitLength.at(i);
2648  for (int i = 0; i < n; i++)
2649  s >> model.m_layerLength.at(i);
2650 
2651  s >> n;
2652  model.m_restDilatationFactor.resize(n);
2653  for (int i = 0; i < n; i++)
2654  s >> model.m_restDilatationFactor.at(i);
2655 
2656  return s;
2657 }
2658 
2659 std::ostream &operator<<=(std::ostream &s, const usNeedleInsertionModelRayleighRitzSpline &model)
2660 {
2661  s.write("usNeedleInsertionModelRayleighRitzSpline", 41);
2662 
2663  s <<= model.m_needle;
2664 
2665  int t;
2666  switch (model.m_needleTipType) {
2668  t = 0;
2669  s.write((char *)&(t), sizeof(int));
2670  s <<= *dynamic_cast<usNeedleTipActuated *>(model.m_needleTip);
2671  break;
2672  }
2674  t = 1;
2675  s.write((char *)&(t), sizeof(int));
2676  s <<= *dynamic_cast<usNeedleTipBeveled *>(model.m_needleTip);
2677  break;
2678  }
2680  t = 2;
2681  s.write((char *)&(t), sizeof(int));
2682  s <<= *dynamic_cast<usNeedleTipPrebent *>(model.m_needleTip);
2683  break;
2684  }
2686  t = 3;
2687  s.write((char *)&(t), sizeof(int));
2688  s <<= *dynamic_cast<usNeedleTipSymmetric *>(model.m_needleTip);
2689  break;
2690  }
2691  }
2692 
2693  s <<= model.m_tissue;
2694 
2695  int n = model.m_stiffnessPerUnitLength.size();
2696  s.write((char *)&(n), sizeof(int));
2697 
2698  for (int i = 0; i < n; i++)
2699  s.write((char *)&(model.m_stiffnessPerUnitLength.at(i)), sizeof(double));
2700  for (int i = 0; i < n; i++)
2701  s.write((char *)&(model.m_layerLength.at(i)), sizeof(double));
2702 
2703  n = model.m_restDilatationFactor.size();
2704  s.write((char *)&(n), sizeof(int));
2705  for (int i = 0; i < n; i++)
2706  s.write((char *)&(model.m_restDilatationFactor.at(i)), sizeof(double));
2707 
2708  s.flush();
2709  return s;
2710 }
2711 
2712 std::istream &operator>>=(std::istream &s, usNeedleInsertionModelRayleighRitzSpline &model)
2713 {
2714  char c[41];
2715  s.read(c, 41);
2716  if (strcmp(c, "usNeedleInsertionModelRayleighRitzSpline")) {
2717  vpException e(vpException::ioError, "Stream does not contain usNeedleInsertionModelRayleighRitzSpline data");
2718  throw e;
2719  }
2720 
2721  s >>= model.m_needle;
2722 
2723  int t;
2724  s.read((char *)&(t), sizeof(int));
2725  switch (t) {
2726  case 0: {
2727  s >>= *dynamic_cast<usNeedleTipActuated *>(model.m_needleTip);
2728  break;
2729  }
2730  case 1: {
2731  s >>= *dynamic_cast<usNeedleTipBeveled *>(model.m_needleTip);
2732  break;
2733  }
2734  case 2: {
2735  s >>= *dynamic_cast<usNeedleTipPrebent *>(model.m_needleTip);
2736  break;
2737  }
2738  case 3: {
2739  s >>= *dynamic_cast<usNeedleTipSymmetric *>(model.m_needleTip);
2740  break;
2741  }
2742  }
2743 
2744  s >>= model.m_tissue;
2745 
2746  int n;
2747  s.read((char *)&(n), sizeof(int));
2748 
2749  model.m_stiffnessPerUnitLength.resize(n);
2750  model.m_layerLength.resize(n);
2751  for (int i = 0; i < n; i++)
2752  s.read((char *)&(model.m_stiffnessPerUnitLength.at(i)), sizeof(double));
2753  for (int i = 0; i < n; i++)
2754  s.read((char *)&(model.m_layerLength.at(i)), sizeof(double));
2755 
2756  s.read((char *)&(n), sizeof(int));
2757  model.m_restDilatationFactor.resize(n);
2758  for (int i = 0; i < n; i++)
2759  s.read((char *)&(model.m_restDilatationFactor.at(i)), sizeof(double));
2760  return s;
2761 }
void setSegment(int i, const usPolynomialCurve3D &poly)
Definition: usBSpline3D.cpp:90
void removeLastSegment()
Definition: usBSpline3D.cpp:92
bool getParametersFromLength(double l, int &index, double &param) const
void removeSegments(int i, int j)
Definition: usBSpline3D.cpp:96
const usPolynomialCurve3D & accessSegment(int i) const
void addSegment(const usPolynomialCurve3D &seg)
Spline definition.
Definition: usBSpline3D.cpp:79
int getNbSegments() const
Parameters setters and getters.
Definition: usBSpline3D.cpp:59
const usPolynomialCurve3D & accessLastSegment() const
vpColVector getPoint(double param) const
Measure curve information.
double getParametricLength() const
Definition: usBSpline3D.cpp:61
void loadPreset(const ModelPreset preset)
Parameters saving and loading.
virtual bool setBasePose(const vpPoseVector &pose)=0
Control of the needle.
double getNeedleFreeLength(int *seg=nullptr, double *param=nullptr) const
const usTissueModelSpline & accessTissue() const
Tissue parameters.
const usNeedleModelSpline & accessNeedle() const
Parameters setters and getters.
bool getCorrespondingPathPoint(double l, int &correspondingRestIndex, double &correspondingRestParam) const
double getTissueDeformationEnergy() const
Measure model information.
const usNeedleInsertionModelRayleighRitzSpline & operator=(const usNeedleInsertionModelRayleighRitzSpline &model)
virtual usNeedleInsertionModelRayleighRitzSpline * clone() const
vpPoseVector getBasePose() const
Parameters setters and getters.
void setBasePose(double tx, double ty, double tz, double thetax, double thetay, double thetaz)
Command of the needle.
vpColVector getTipDirection() const
vpColVector getTipPosition() const
vpHomogeneousMatrix getWorldMbase() const
vpPoseVector getTipPose() const
vpColVector getBasePosition() const
void setTipPose(double tx, double ty, double tz, double thetax, double thetay, double thetaz)
void init()
Spline definition.
double getOuterDiameter() const
void loadPreset(const NeedlePreset preset)
Parameters saving and loading.
void setDiameter(double diameter)
Parameters setters and getters.
void setTipAngleRad(double angle)
void setSteeringAngleRad(double angle)
void setLength(double l)
void setDiameter(double diameter)
Parameters setters and getters.
void setDiameter(double diameter)
Parameters setters and getters.
virtual usNeedleTip * clone() const
Definition: usNeedleTip.cpp:56
vpPoseVector getBasePose() const
Definition: usNeedleTip.cpp:66
vpColVector getTipPosition() const
vpColVector getBasePosition() const
Definition: usNeedleTip.cpp:87
vpColVector getTipDirection() const
vpColVector getBaseAxisZ() const
void setBasePose(const vpPoseVector &pose)
Parameters setters and getters.
Definition: usNeedleTip.cpp:58
vpColVector getDirection() const
void setPose(const vpPoseVector &pose)
Parameters setters and getters.
void setPosition(const vpColVector &P)
vpColVector getStartTangent() const
usPolynomialCurve3D getSubPolynomialCurve(double startParameter, double endParameter) const
double getLength(int nbCountSeg=50) const
unsigned int getOrder() const
vpColVector getPoint(double parameter) const
void setParametricLength(double length)
void setPolynomialCoefficients(const vpMatrix &polynomialCoefficients)
vpColVector getEndPoint() const
vpMatrix getPolynomialCoefficients() const
vpColVector getEndTangent() const
double getParametricLength() const
void changeCoefficientsToFitBoundaries(double startParameter, double endParameter)
vpColVector getStartPoint() const
const usBSpline3D & accessPath() const
const usOrientedPlane3D & accessSurface() const
Parameters setters and getters.
VISP_EXPORT bool IsPointInFrontOfPlane(const vpColVector &point, const usOrientedPlane3D &plane)
VISP_EXPORT vpColVector getPlaneCurveCrossingPoint(const usPolynomialCurve3D &poly, const usOrientedPlane3D &plane, double threshold, double *t=nullptr)
VISP_EXPORT double getPointPlaneDistance(const vpColVector &point, const usOrientedPlane3D &plane)
VISP_EXPORT vpColVector projectPointOnPlane(const vpColVector &point, const usOrientedPlane3D &plane, const vpColVector &direction=vpColVector())
VISP_EXPORT bool DoesSegmentCrossPlaneDirect(const usPolynomialCurve3D &poly, const usOrientedPlane3D &plane)
VISP_EXPORT bool DoesSegmentCrossPlane(const usPolynomialCurve3D &poly, const usOrientedPlane3D &plane)