KratosMultiphysics
KRATOS Multiphysics (Kratos) is a framework for building parallel, multi-disciplinary simulation software, aiming at modularity, extensibility, and high performance. Kratos is written in C++, and counts with an extensive Python interface.
spline_curve_utilities.hpp
Go to the documentation of this file.
1 //
2 // Project Name: KratosContactMechanicsApplication $
3 // Created by: $Author: JMCarbonell $
4 // Last modified by: $Co-Author: $
5 // Date: $Date: December 2016 $
6 // Revision: $Revision: 0.0 $
7 //
8 //
9 
10 #if !defined(KRATOS_SPLINE_CURVE_UTILITIES_H_INCLUDED )
11 #define KRATOS_SPLINE_CURVE_UTILITIES_H_INCLUDED
12 
13 
14 // System includes
15 #include <cmath>
16 #include <set>
17 
18 #ifdef _OPENMP
19 #include <omp.h>
20 #endif
21 
22 // External includes
23 #include "boost/smart_ptr.hpp"
24 #include "utilities/timer.h"
25 
26 // Project includes
27 #include "includes/define.h"
28 #include "includes/variables.h"
29 #include "includes/model_part.h"
30 #include "utilities/openmp_utils.h"
31 #include "utilities/math_utils.h"
34 
35 namespace Kratos
36 {
37 
39 
44  {
45  public:
46 
49 
51 
52  //definitions for spatial search
54  typedef Node NodeType;
55  typedef NodeType::Pointer NodePointerType;
56  typedef std::vector<NodePointerType> NodePointerTypeVector;
57  typedef std::vector<NodeType> NodeTypeVector;
58  typedef NodePointerTypeVector::iterator NodePointerIterator;
59  typedef std::vector<double> DistanceVector;
60  typedef std::vector<double>::iterator DistanceIterator;
63 
64  //structure for a spline segment type
65  typedef struct
66  {
67  int id; // Spline Knot number
68  PointType P0; // First auxiliar point
69  PointType P1; // First curve point
70  PointType P2; // Second curve point
71  PointType P3; // Second auxiliar point
72 
73  } SplineType;
74 
78 
80  SplineCurveUtilities(){ mEchoLevel = 0; mParallel = true; };
81 
82  SplineCurveUtilities(bool Parallel){ mEchoLevel = 0; mParallel = Parallel; };
83 
86 
87 
91 
92 
96 
97  //************************************************************************************
98  //************************************************************************************
99 
100  // Create Arch Length Parametrized Spline Curve with m cubic segments
101  void CreateParametrizedCurve(NodePointerTypeVector& rGeneratrixPoints, NodePointerTypeVector& rKnotsList, int m)
102  {
103 
104  //Definition of the Spline Curve Q(t): (Spline with rGeneratrixPoints.size() cubic segments with the different arch length)
105 
106  //the numeration and order of the GeneratrixPoints is very important for the interpolation
107  unsigned int id = 0; //start with 0;
108 
109  //Set auxiliary control points (knots) using reflection at the begining ( 1 extra knot )
110  NodesContainerType::iterator nodes_begin = rGeneratrixPoints.begin();
111 
112  double X = 2.0 * nodes_begin->X() - (nodes_begin + 1)->X();
113  double Y = 2.0 * nodes_begin->Y() - (nodes_begin + 1)->Y();
114  double Z = 2.0 * nodes_begin->Z() - (nodes_begin + 1)->Z();
115 
116  NodePointerType KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
117  rKnotsList.push_back( KnotPoint );
118  id+=1;
119 
120  //Set generatrix control points (knots) from the initial control stations
121  for(NodePointerTypeVector::iterator in = rGeneratrixPoints.begin(); in!=rGeneratrixPoints.end(); in++)
122  {
123  KnotPoint = NodePointerType( new NodeType(id,(*in)->X(),(*in)->Y(),(*in)->Z()) );
124  rKnotsList.push_back( KnotPoint );
125  id++;
126  }
127 
128 
129  //Set auxiliary control points (knots) using reflection at the end ( 1 extra knots )
130  NodesContainerType::iterator nodes_end = rGeneratrixPoints.end()-1;
131 
132  X = 2.0 * (nodes_end)->X() - (nodes_end - 1)->X();
133  Y = 2.0 * (nodes_end)->Y() - (nodes_end - 1)->Y();
134  Z = 2.0 * (nodes_end)->Z() - (nodes_end - 1)->Z();
135 
136  KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
137  rKnotsList.push_back( KnotPoint );
138 
139 
140  //Definition of the Parametrized Spline Curve Q(s):
141 
142  //Compute an approximate Arch-Length Parametrized Curve
143 
144  double TotalLength = 0;
145  std::vector<double> SegmentArchLengths;
146 
147  SplineType Spline;
148  double S = 0;
149  int size = rKnotsList.size()-2;
150 
151  //std::cout<<" knots "<<size<<std::endl;
152 
153  for(int i=1; i<size; i++)
154  {
155 
156  SetSpline(Spline, rKnotsList, i);
157 
158  //Get Segment Arch-Length by the adaptative gaussian integration method
159  S = AdaptiveIntegration(Spline);
160 
161  //std::cout<<" SegmentArchLength "<<S<<std::endl;
162 
163  //Set Segment Length
164  SegmentArchLengths.push_back(S);
165 
166  //Add Segment to the Total Arch Length
167  TotalLength += S;
168 
169  }
170 
171  int n_segments = SegmentArchLengths.size();
172  //std::cout<<" TotalArchLength "<<TotalLength<<" Segments "<<n_segments<<std::endl;
173 
174 
175  //Find m+1 equally spaced points along Q(s)
176  double Length = TotalLength / double(m);
177 
178  NodePointerTypeVector NewKnotsList;
179 
180  nodes_begin = rKnotsList.begin();
181 
182  id = 0;
183  X = nodes_begin->X();
184  Y = nodes_begin->Y();
185  Z = nodes_begin->Z();
186 
187  KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
188  NewKnotsList.push_back( KnotPoint ); //reserve space for the initial auxiliar node
189 
190  id+=1;
191  X = (nodes_begin + 1)->X();
192  Y = (nodes_begin + 1)->Y();
193  Z = (nodes_begin + 1)->Z();
194 
195  KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
196  NewKnotsList.push_back( KnotPoint ); //first node
197 
198  id+=1; //start with 2;
199  for(int i=1; i < m; i++)
200  {
201 
202  //Find the spline segment indexed by j [tj, tj+1] which satisfies the current segment length (i*Length)
203  S = 0;
204  int j = 0;
205  for(int k = 0; k < n_segments; k++)
206  {
207  S += SegmentArchLengths[k];
208  //std::cout<<" k "<<k<<std::endl;
209  if( S >= i*Length ){
210  j = k+1;
211  S -= SegmentArchLengths[k];
212  break;
213  }
214 
215  }
216 
217  if( (i*Length - S) < 0 )
218  std::cout<<" Something is wrong in the index search KNOT["<<j<<"]: length "<<i*Length<<" S "<<S<<std::endl;
219 
220 
221  //std::cout<<" KNOT ["<<j<<"]"<<std::endl;
222 
223 
224  //Compute new knot using the Bisection method
225 
226  int max_iters = 500;
227  double tolerance = (i*Length - S) * 1e-3;
228  double error = tolerance * 10;
229 
230  SplineType FirstHalfSpline;
231  SplineType SecondHalfSpline;
232 
233  // Start with the segment found previously
234  SetSpline(Spline, rKnotsList, j);
235 
236  double DeltaS = 0;
237  int iters = 0;
238 
239  double rj = 0;
240  double left = 0;
241  double right = 1;
242  double middle = 0.5;
243 
244  //std::cout<<" Tolerance "<<tolerance<<std::endl;
245 
246  //std::cout<<" LENGTH "<<Length<<" S "<<S<<" i "<<i<<" diff "<<(i*Length - S)<<std::endl;
247 
248  while ( fabs(error) > tolerance && iters < max_iters )
249  {
250  middle = 0.5 * (left + right);
251 
252  //Get Segment Arch-Length by the numerical integration method
253  DeltaS = ArchLengthGeometricIntegration(Spline, rj, middle);
254 
255  //std::cout<<" ["<<left<<", "<<middle<<"]: "<<(i*Length - S)<<"("<<DeltaS<<") :: ";
256 
257  if( (DeltaS) < (i*Length - S) ){ //solution in the second half
258  left = middle;
259  }
260  else{//solution in the first half
261  right = middle;
262  }
263 
264  error = (DeltaS) - (i*Length - S);
265 
266  //std::cout<<DeltaS<<" :: "<<error<<std::endl;
267  //std::cout<<DeltaS<<std::endl;
268 
269  if( left == middle )
270 
271  iters++;
272  }
273 
274  if( fabs(error) > tolerance || iters == max_iters )
275  std::cout<<" max iters reached in Bisection "<<iters<<" error: "<<error<<" ["<<tolerance<<"]"<<std::endl;
276 
278  Point = PointOnCurve(Point,Spline,middle);
279 
280  //std::cout<<" Knot Point "<<Point<<" middle "<<middle<<std::endl;
281 
282  X = Point[0];
283  Y = Point[1];
284  Z = Point[2];
285 
286  KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
287  NewKnotsList.push_back( KnotPoint );
288 
289 
290  //std::cout<<" X "<<X<<" Y "<<Y<<" Z "<<Z<<std::endl;
291 
292  id++;
293 
294  }
295 
296  //last knot end
297  nodes_end = rKnotsList.end()-2;
298 
299  X = (nodes_end)->X();
300  Y = (nodes_end)->Y();
301  Z = (nodes_end)->Z();
302 
303  // std::cout<<"Last knot end: "<<id<<" X "<<X<<" Y "<<Y<<" Z "<<Z<<std::endl;
304 
305  KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
306  NewKnotsList.push_back( KnotPoint );
307 
308  //reflection at the end ( 1 extra knots )
309  id += 1;
310  nodes_end = NewKnotsList.end()-1;
311 
312  X = 2.0 * (nodes_end)->X() - (nodes_end - 1)->X();
313  Y = 2.0 * (nodes_end)->Y() - (nodes_end - 1)->Y();
314  Z = 2.0 * (nodes_end)->Z() - (nodes_end - 1)->Z();
315 
316  // std::cout<<"Last knot reflection 1: "<<id<<" X "<<X<<" Y "<<Y<<" Z "<<Z<<std::endl;
317 
318  KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
319  NewKnotsList.push_back( KnotPoint );
320 
321  //reflection at the end ( 2 extra knots ) :: needed for the tube surface mesh
322  id += 1;
323  nodes_end = NewKnotsList.end()-1;
324 
325  X = 2.0 * (nodes_end)->X() - (nodes_end - 1)->X();
326  Y = 2.0 * (nodes_end)->Y() - (nodes_end - 1)->Y();
327  Z = 2.0 * (nodes_end)->Z() - (nodes_end - 1)->Z();
328 
329  // std::cout<<"Last knot reflection 2: "<<id<<" X "<<X<<" Y "<<Y<<" Z "<<Z<<std::endl;
330 
331  KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
332  NewKnotsList.push_back( KnotPoint );
333 
334  //first knot //reflection at the begining ( 1 extra knot )
335  nodes_begin = NewKnotsList.begin() + 1;
336 
337  X = 2.0 * nodes_begin->X() - (nodes_begin + 1)->X();
338  Y = 2.0 * nodes_begin->Y() - (nodes_begin + 1)->Y();
339  Z = 2.0 * nodes_begin->Z() - (nodes_begin + 1)->Z();
340 
341  // std::cout<<"First Node Reflection: X "<<X<<" Y "<<Y<<" Z "<<Z<<std::endl;
342  // std::cout<<"Second Node Reflection: X "<<nodes_begin->X()<<" Y "<<nodes_begin->Y()<<" Z "<<nodes_begin->Z()<<std::endl;
343  // std::cout<<"Third Node Reflection: X "<<(nodes_begin + 1)->X()<<" Y "<<(nodes_begin + 1)->Y()<<" Z "<<(nodes_begin + 1)->Z()<<std::endl;
344 
345  id = 0;
346  KnotPoint = NodePointerType( new NodeType(id,X,Y,Z) );
347  NewKnotsList.front() = KnotPoint;
348  //NewKnotsList[0] = KnotPoint;
349 
350  // nodes_begin = NewKnotsList.begin() + 3;
351  // std::cout<<"Forth Node Reflection: X "<<nodes_begin->X()<<" Y "<<nodes_begin->Y()<<" Z "<<nodes_begin->Z()<<std::endl;
352  // std::cout<<"Fifth Node Reflection: X "<<(nodes_begin + 1)->X()<<" Y "<<(nodes_begin + 1)->Y()<<" Z "<<(nodes_begin + 1)->Z()<<std::endl;
353 
354  //Define the knots of Q(s) using the m+1 equally spaced points (Spline with m cubic segments with the same arch length)
355  rKnotsList.swap(NewKnotsList);
356  // rKnotsList.resize(0);
357  // rKnotsList.clear();
358  // for(int i=0; i<NewKnotsList.size(); i++)
359  // rKnotsList.push_back(NewKnotsList[i]);
360 
361  //Set correct Ids
362  for(unsigned int i=0; i<rKnotsList.size(); i++){
363  rKnotsList[i]->SetId(i);
364  //std::cout<<" rKnotsList[i] "<<i<<": "<<rKnotsList[i]->Coordinates()<<std::endl;
365  }
366 
367  }
368 
369  //************************************************************************************
370  //************************************************************************************
372  {
373 
374  //Compute the numerical integration of the arch length for the Spline segment or interval (rSpline)
375  double S = 0;
376  S = IntegrateSubInterval(rSpline);
377 
378  //std::cout<<" Initial Arch Length "<<S<<std::endl;
379 
380  //Start adaptative sub interval integration
381  int max_iters = 40;
382  double tolerance = S * 1e-2;
383  double error = tolerance * 10;
384 
385  double Sk = 0;
386  int iters = 1;
387 
388  std::vector<SplineType> Intervals;
389  Intervals.push_back(rSpline);
390 
391  while( fabs(error) > tolerance && iters < max_iters )
392  {
393  Sk = 0;
394 
395  //Compute SubIntervals arch length Sk and store SubIntervals Splines
396  Sk = IntegrateSubInterval(rSpline, iters+1);
397 
398  //Compute error
399  error = Sk - S;
400 
401  //std::cout<<" SubInterval Arch Length "<<Sk<<" error "<<error<<" tol "<<tolerance<<std::endl;
402 
403  //Update Total arch length S = Sk
404  S = Sk;
405 
406  iters++;
407 
408  }
409 
410  if( fabs(error) > tolerance || iters == max_iters )
411  std::cout<<" max iters reached in Adaptive Integration "<<iters<<" error: "<<error<<" ["<<tolerance<<"]"<<std::endl;
412 
413 
414  return S;
415  }
416 
417 
418 
419  //************************************************************************************
420  //************************************************************************************
421 
422  //Divide the interval in n sub-intervals (two halves) and compute the arch-lengths sum
423 
424  double IntegrateSubInterval(SplineType& rSpline, int n = 0)
425  {
426 
427  double t = 1.0 / double(n + 1.0) ;
428 
429  double S = 0;
430  double a = 0;
431  double b = t;
432 
433  for(int i=0; i<n+1; i++)
434  {
435  S += ArchLengthGeometricIntegration(rSpline, a, b);
436  //std::cout<<" S "<<S<<" a "<<a<<" b "<<b<<std::endl;
437  a += t;
438  b += t;
439  }
440 
441  return S;
442 
443  }
444 
445 
446  //************************************************************************************
447  //************************************************************************************
448  double ArchLengthGeometricIntegration(SplineType& rSpline, double& a, double& b)
449  {
450  //apply numerical integration:: gaussian quadrature
451  //return GaussianQuadratureIntegration(rSpline); //not implemented yet
452 
453  //apply numerical integration:: simpson rule
454  return SimpsonRuleIntegration(rSpline, a, b, 7);
455 
456  }
457 
458  //************************************************************************************
459  //************************************************************************************
460 
461  //(Simpson's 3/8 rule :: Cubic Interpolation)
462  //Approximates the definite integral of f(t) (rSpline) from a to b by
463  //the composite Simpson's rule, using n subintervals (n even number)
464  double SimpsonRuleIntegration(SplineType& rSpline, double& a, double& b, double n = 1)
465  {
466 
467  double IntegralValue = 0;
468 
469  double h = (b - a) / n;
470 
471  double s = SplineGeometricLength(rSpline, a) + SplineGeometricLength(rSpline, b);
472 
473  double t = 0;
474  for(int i=1; i<n; i+=2)
475  {
476  t = (a + i * h);
477  s += 4 * SplineGeometricLength(rSpline, t);
478  }
479 
480 
481  for(int i=2; i<n-1; i+=2)
482  {
483  t = (a + i * h);
484  s += 2 * SplineGeometricLength(rSpline, t);
485  }
486 
487 
488  IntegralValue = (s * h / 3.0);
489 
490  return IntegralValue;
491 
492  }
493 
494  //************************************************************************************
495  //************************************************************************************
496  double SplineGeometricLength(SplineType& rSpline, double& t)
497  {
498 
499  PointType PointA = ZeroVector(3);
500  PointA = PointOnCurveFirstDerivative(rSpline, t);
501 
502  return (norm_2(PointA));
503  }
504 
505 
506 
507  //************************************************************************************
508  //************************************************************************************
509  inline void SetSpline(SplineType& rOutputSpline,const SplineType& rInputSpline)
510  {
511 
512  rOutputSpline.id = rInputSpline.id;
513 
514  rOutputSpline.P0 = rInputSpline.P0;
515  rOutputSpline.P1 = rInputSpline.P1;
516  rOutputSpline.P2 = rInputSpline.P2;
517  rOutputSpline.P3 = rInputSpline.P3;
518 
519  }
520 
521  //************************************************************************************
522  //************************************************************************************
523  inline void SetSpline(SplineType& rSpline,const PointType& P0,const PointType& P1,const PointType& P2,const PointType& P3)
524  {
525 
526  rSpline.id = 0;
527 
528  rSpline.P0 = P0;
529  rSpline.P1 = P1;
530  rSpline.P2 = P2;
531  rSpline.P3 = P3;
532 
533  }
534 
535  //************************************************************************************
536  //************************************************************************************
537  inline void SetSpline(SplineType& rSpline, const NodePointerTypeVector& rKnotsList, int& id)
538  {
539 
540  rSpline.id = id;
541 
542  rSpline.P0 = ZeroVector(3);
543  rSpline.P0[0] = rKnotsList[id-1]->X();
544  rSpline.P0[1] = rKnotsList[id-1]->Y();
545  rSpline.P0[2] = rKnotsList[id-1]->Z();
546 
547  rSpline.P1 = ZeroVector(3);
548  rSpline.P1[0] = rKnotsList[id]->X();
549  rSpline.P1[1] = rKnotsList[id]->Y();
550  rSpline.P1[2] = rKnotsList[id]->Z();
551 
552  rSpline.P2 = ZeroVector(3);
553  rSpline.P2[0] = rKnotsList[id+1]->X();
554  rSpline.P2[1] = rKnotsList[id+1]->Y();
555  rSpline.P2[2] = rKnotsList[id+1]->Z();
556 
557  rSpline.P3 = ZeroVector(3);
558  rSpline.P3[0] = rKnotsList[id+2]->X();
559  rSpline.P3[1] = rKnotsList[id+2]->Y();
560  rSpline.P3[2] = rKnotsList[id+2]->Z();
561 
562  }
563 
564  //************************************************************************************
565  //************************************************************************************
566 
567  PointType& CalculatePointProjection(const PointType& rPoint, KdtreeType& rKnotsKdtree, const NodePointerTypeVector& rKnotsList, PointType& rPointProjection )
568  {
569  KRATOS_TRY
570 
571  //1.- Find the closest generatrix knot of the spline curve
572  double PointDistance = 0;
573 
574  int id = rKnotsList.front()->Id(); // starting with the first Knot
575 
576  id = GetClosestKnotId( rPoint, rKnotsKdtree, PointDistance ); //starting with the closest Knot
577 
578  SplineType Spline;
579 
580  SetSpline(Spline, rKnotsList, id);
581 
582  //2.- Find the closest point on a spline curve: (Sk := NormalizedArchLength)
583  double Sk = CombinedMethod(rPoint, rKnotsList, Spline);
584 
585  //2.1-Projected Point:
586  rPointProjection = PointOnCurve(rPointProjection,Spline,Sk);
587 
588  //std::cout<<"CD: KnotPoint "<<Spline.P1<<" ProjectedPoint "<<rPointProjection<<" BeamPoint "<<rPoint<<std::endl;
589 
590  return rPointProjection;
591 
592  KRATOS_CATCH( "" )
593  }
594 
595 
596  //************************************************************************************
597  //************************************************************************************
598  int GetClosestKnotId(const PointType& rPoint, KdtreeType& rKnotsKdtree, double& rPointDistance)
599  {
600 
601  NodeType WorkPoint(0,rPoint[0],rPoint[1],rPoint[2]);
602  rPointDistance = 0;
603 
604  NodePointerType NearestPoint = rKnotsKdtree.SearchNearestPoint(WorkPoint, rPointDistance);
605 
606  // get the id of the closest point i
607  return NearestPoint->Id();
608 
609  }
610 
611  //************************************************************************************
612  //************************************************************************************
613 
614  double CombinedMethod(const PointType& rPoint, const NodePointerTypeVector& rKnotsList, SplineType& rSpline, double s = 0.5)
615  {
616  //1.2.- Combined Method:
617  int iters = 4;
618 
619  //1.2.1- Apply Quadratic Minimization Method
620  double Sk = QuadraticMinimizationMethod(rPoint, rKnotsList, rSpline, iters);
621 
622  //std::cout<<" First prediction Sk "<<Sk<<std::endl;
623 
624  iters = 20;
625 
626  //1.2.2- Apply Newton's Method
627  Sk = NewtonsMethod(rPoint, rKnotsList, rSpline, Sk, iters);
628 
629 
630 
631  return Sk;
632 
633  }
634 
635 
636  //************************************************************************************
637  //************************************************************************************
638 
639  double NewtonsMethod(const PointType& rPoint, const NodePointerTypeVector& rKnotsList, SplineType& rSpline, double Spredict = 0, double iters = 20, double s = 0.5)
640  {
641 
642  //Initial normalized estimate on the selected spline
643  double Sk = Spredict;
644  int max_iters = iters;
645  int dist_iters = 25;
646 
647  int iter = 0;
648  int segment_iter = 0;
649  while( ((Sk < -0.1 || Sk >1) && segment_iter<max_iters) || segment_iter == 0 )
650  {
651 
652  if( Sk<0 ){ //previous adjacent segment
653 
654  int new_id = rSpline.id - 1;
655 
656  if(new_id <= 0)
657  new_id = 1;
658 
659  //std::cout<<" NewId R "<<new_id<<std::endl;
660 
661  Sk = 1 - Sk;
662 
663  SetSpline(rSpline, rKnotsList, new_id);
664 
665  }
666 
667  if( Sk>1 ){ //posterior adjacent segment
668 
669  int new_id = rSpline.id + 1;
670 
671  if( new_id > (int)rKnotsList.size()-3 )
672  new_id = rKnotsList.size()-3;
673 
674  //std::cout<<" NewId I "<<new_id<<std::endl;
675 
676  Sk = Sk - 1;
677 
678  SetSpline(rSpline, rKnotsList, new_id);
679 
680  }
681 
682  //std::cout<<" SPLINE ID "<<rSpline.id<<std::endl;
683 
684  //Iterative Parameters
685  double tolerance = 1e-7; //1e-8
686 
687  iter = 0;
688  double distance = tolerance*10;
689 
690  while( iter<dist_iters && distance>=tolerance )
691  {
692 
693  distance = FirstDerivativeSquareDistancePointToSpline(rPoint,rSpline, Sk);
694  distance /= SecondDerivativeSquareDistancePointToSpline(rPoint,rSpline, Sk);
695 
696  Sk -= distance;
697 
698  //std::cout<<" Sk newton "<<Sk<<" distance "<<distance<<std::endl;
699 
700  distance = fabs(distance);
701 
702  iter++;
703  }
704 
705 
706  // std::cout<<" iters "<<iter<<" distance "<<distance<<std::endl;
707 
708  if( distance > tolerance ){
709  std::cout<<"BBX Tube Contact Search [Point:"<<rPoint<<",Distance:"<<distance<<",Tol:"<<tolerance<<"] ERROR"<<std::endl;
710  if( distance > 1e3*tolerance )
711  KRATOS_THROW_ERROR( std::logic_error," TUBE BBX::NewmarksMethod HAS NOT REACHED CONVERGENCE ", 0)
712  //std::cout<<" TUBE BBX::NewmarksMethod HAS NOT REACHED CONVERGENCE "<<std::endl;
713  }
714  else{
715  //std::cout<<" converged "<<Sk<<std::endl;
716  }
717 
718  segment_iter++;
719  }
720 
721  //std::cout<<" segment_iter "<<segment_iter<<" newtons iters "<<iter<<std::endl;
722 
723  if( Sk < 0 && Sk > -0.1)
724  Sk = 0;
725 
726  return Sk;
727 
728  }
729 
730  //************************************************************************************
731  //************************************************************************************
732 
733  double QuadraticMinimizationMethod(const PointType& rPoint, const NodePointerTypeVector& rKnotsList, SplineType& rSpline, double iters, double s = 0.5)
734  {
735 
736  int max_iters = iters;
737  double Skj = 0; //to start with the iteration
738 
739  int segment_iter = 0;
740  while( ((Skj < 0 || Skj >1) && segment_iter<max_iters) || segment_iter == 0 )
741  {
742 
743  if( Skj<0 ){ //previous adjacent segment
744 
745  int new_id = rSpline.id - 1;
746 
747  if(new_id <= 0)
748  new_id = 1;
749 
750  SetSpline(rSpline, rKnotsList, new_id);
751 
752  }
753 
754  if( Skj>1 ){ //posterior adjacent segment
755 
756  int new_id = rSpline.id + 1;
757 
758  if( new_id > (int)rKnotsList.size()-3 )
759  new_id = rKnotsList.size()-3;
760 
761  SetSpline(rSpline, rKnotsList, new_id);
762 
763  }
764 
765  //std::cout<<" Q SPLINE ID "<<rSpline.id<<std::endl;
766 
767  //Initial Segment estimate :: rSpline
768 
769  //Initial three estimates for a normalized segment
770  Vector Estimates = ZeroVector(3);
771  Estimates[0] = 0.0; //S1
772  Estimates[1] = 0.5; //S2
773  Estimates[2] = 1.0; //S3
774 
775  //1:
776  //Arch Length difference between the estimates splines
777  Vector Difference = ZeroVector(3);
778 
779  //Arch Length square difference between the estimates splines
780  Vector SquareDifference = ZeroVector(3);
781 
782  //2:
783  //Square Distances to the estimates splines
784  Vector Function = ZeroVector(3);
785 
786  //Polynomial for distance interpolation
787  Vector InterpolatedDistance = ZeroVector(4);
788 
789 
790  //Iterative Parameters
791  double tolerance = 1e-7; //1e-8;
792  double distance = tolerance * 10;
793 
794  int iter = 0;
795  double Ski = 0;
796 
797  while( iter < max_iters && distance >= tolerance )
798  {
799 
800  //Store previous Sk
801  Ski = Skj;
802 
803  //Arch Length difference between the estimates splines
804  Difference = CalculateArchLengthDifferences(Difference,Estimates);
805 
806  //Arch Length square difference between the estimates splines
807  SquareDifference = CalculateSquareArchLengthDifferences(SquareDifference,Estimates);
808 
809  //Square Distances to the estimates splines
810  Function[0] = SquareDistancePointToSpline(rPoint, rSpline, Estimates[0]);
811  Function[1] = SquareDistancePointToSpline(rPoint, rSpline, Estimates[1]);
812  Function[2] = SquareDistancePointToSpline(rPoint, rSpline, Estimates[2]);
813 
814  Skj = 0.5 * (SquareDifference[1]*Function[0] + SquareDifference[2]*Function[1] + SquareDifference[0]*Function[2]);
815  Skj /= (Difference[1]*Function[0] + Difference[2]*Function[1] + Difference[0]*Function[2]);
816 
817  InterpolatedDistance[0] = EvaluateDistancePolynomial(Function, Estimates, Estimates[0]);
818  InterpolatedDistance[1] = EvaluateDistancePolynomial(Function, Estimates, Estimates[1]);
819  InterpolatedDistance[2] = EvaluateDistancePolynomial(Function, Estimates, Estimates[2]);
820 
821  distance = EvaluateDistancePolynomial(Function, Estimates, Skj);
822 
823  double larger_distance = fabs(InterpolatedDistance[0]);
824 
825  int largest = 0;
826  for( unsigned int i=1; i<3; i++)
827  {
828  if(larger_distance<fabs(InterpolatedDistance[i])){
829  larger_distance = fabs(InterpolatedDistance[i]);
830  largest = i;
831  }
832  }
833 
834  if(fabs(InterpolatedDistance[largest])>distance)
835  {
836  Estimates[largest] = Skj;
837  }
838 
839 
840  //tolerance
841  distance = fabs(Skj-Ski);
842 
843  iter++;
844  }
845 
846  //std::cout<<" iters "<<iter<<" Skj "<<Skj<<std::endl;
847 
848  // if( distance > tolerance )
849  // std::cout<<" TUBE BBX::QuadraticMinimizationMethod HAS NOT REACHED CONVERGENCE "<<std::endl;
850 
851  segment_iter++;
852  }
853 
854 
855  return Skj;
856 
857  //Projected Point:
858  //PointType ProjectedPoint;
859  //ProjectedPoint = PointOnCurve(ProjectedPoint,rSpline,Sk)
860 
861 
862  }
863 
864  //************************************************************************************
865  //************************************************************************************
866 
867  double EvaluateDistancePolynomial(const Vector& rFunction,const Vector& rEstimates, double& Sk)
868  {
869  //Polynomial to interpolate D(S) coefficients:
870  Vector PolynomialBasis = ZeroVector(3);
871 
872  //S1, S2, S3
873  PolynomialBasis = CalculateDistancePolynomialBasis(PolynomialBasis, rEstimates, Sk);
874  double PolynomialValue = PolynomialBasis[0]*rFunction[0] + PolynomialBasis[1]*rFunction[1] + PolynomialBasis[2]*rFunction[2];
875 
876  return PolynomialValue;
877  }
878 
879  //************************************************************************************
880  //************************************************************************************
881 
882  Vector& CalculateArchLengthDifferences(Vector& rDifference, const Vector& rEstimates)
883  {
884  rDifference[0] = rEstimates[0]-rEstimates[1]; //12 (1-2)
885  rDifference[1] = rEstimates[1]-rEstimates[2]; //23 (2-3)
886  rDifference[2] = rEstimates[2]-rEstimates[0]; //31 (3-1)
887 
888  return rDifference;
889  }
890 
891  //************************************************************************************
892  //************************************************************************************
893 
894  Vector& CalculateSquareArchLengthDifferences(Vector& rSquareDifference, const Vector& rEstimates)
895  {
896  rSquareDifference[0] = rEstimates[0] * rEstimates[0] - rEstimates[1] * rEstimates[1]; //12 (1-2)
897  rSquareDifference[1] = rEstimates[1] * rEstimates[1] - rEstimates[2] * rEstimates[2]; //23 (2-3)
898  rSquareDifference[2] = rEstimates[2] * rEstimates[2] - rEstimates[0] * rEstimates[0]; //31 (3-1)
899 
900  return rSquareDifference;
901  }
902 
903  //************************************************************************************
904  //************************************************************************************
905 
906  // Values of the coefficients for the polynomial that interpolates the square distance function
907 
908  Vector& CalculateDistancePolynomialBasis(Vector& rPolynomialBasis, const Vector& rEstimates, double& rValue)
909  {
910  rPolynomialBasis[0] = (rValue-rEstimates[1]) * (rValue-rEstimates[2]) / ((rEstimates[0]-rEstimates[1]) * (rEstimates[0]-rEstimates[2]));
911  rPolynomialBasis[1] = (rValue-rEstimates[0]) * (rValue-rEstimates[2]) / ((rEstimates[1]-rEstimates[0]) * (rEstimates[1]-rEstimates[2]));
912  rPolynomialBasis[2] = (rValue-rEstimates[0]) * (rValue-rEstimates[1]) / ((rEstimates[2]-rEstimates[0]) * (rEstimates[2]-rEstimates[1]));
913 
914  return rPolynomialBasis;
915  }
916 
917 
918  //************************************************************************************
919  //************************************************************************************
920 
921 
922  double SquareDistancePointToSpline(const PointType& rPoint,const SplineType& rSpline, double& t)
923  {
924  //compute spline on t, normalized distance
925  PointType SplinePoint = ZeroVector(3);
926  SplinePoint = PointOnCurve(SplinePoint, rSpline, t);
927 
928  //compute square distance
929  SplinePoint -= rPoint;
930  double Distance = inner_prod(SplinePoint,SplinePoint);
931 
932  return Distance;
933  }
934 
935  //************************************************************************************
936  //************************************************************************************
937 
938  double FirstDerivativeSquareDistancePointToSpline(const PointType& rPoint,const SplineType& rSpline, double& t)
939  {
940  //compute spline on t, normalized distance
941  PointType SplinePoint = ZeroVector(3);
942  SplinePoint = PointOnCurve(SplinePoint, rSpline, t);
943 
944  SplinePoint -= rPoint;
945 
946  //compute spline first derivative on t, normalized distance
947  PointType SplinePointFirstDerivative = PointOnCurveFirstDerivative(rSpline, t);
948 
949  double Distance = 2.0 * inner_prod(SplinePoint,SplinePointFirstDerivative);
950 
951  return Distance;
952  }
953 
954 
955  //************************************************************************************
956  //************************************************************************************
957 
958  double SecondDerivativeSquareDistancePointToSpline(const PointType& rPoint,const SplineType& rSpline, double& t)
959  {
960  //compute spline on t, normalized distance
961  PointType SplinePoint = ZeroVector(3);
962  SplinePoint = PointOnCurve(SplinePoint, rSpline, t);
963 
964  SplinePoint -= rPoint;
965 
966  //compute spline first derivative on t, normalized distance
967  PointType SplinePointFirstDerivative = PointOnCurveFirstDerivative(rSpline, t);
968 
969  //compute spline second derivative on t, normalized distance
970  PointType SplinePointSecondDerivative = PointOnCurveSecondDerivative(rSpline, t);
971 
972  double Distance = inner_prod(SplinePointFirstDerivative,SplinePointFirstDerivative);
973  Distance += inner_prod(SplinePoint,SplinePointSecondDerivative);
974  Distance *= 2.0;
975 
976  return Distance;
977  }
978 
979 
980 
981  //************************************************************************************
982  //************************************************************************************
983 
986 
987  inline PointType& PointOnCurve(PointType& rPoint, const SplineType& rSpline, double& t, double s = 0.5)
988  {
989  Vector Basis = ZeroVector(4);
990 
991  Basis = SplineBasis( Basis, t, s );
992 
993  rPoint = Basis[0] * rSpline.P0 + Basis[1] * rSpline.P1 + Basis[2] * rSpline.P2 + Basis[3] * rSpline.P3;
994 
995  return rPoint;
996  }
997 
998 
999 
1000  //************************************************************************************
1001  //************************************************************************************
1002 
1005 
1006  PointType PointOnCurveFirstDerivative(const SplineType& rSpline, double& t, double s = 0.5)
1007  {
1008  Vector Basis = ZeroVector(4);
1009 
1010  Basis = FirstDerivativeSplineBasis( Basis, t, s );
1011 
1012  PointType Result = Basis[0] * rSpline.P0 + Basis[1] * rSpline.P1 + Basis[2] * rSpline.P2 + Basis[3] * rSpline.P3;
1013 
1014  return Result;
1015  }
1016 
1017 
1018  //************************************************************************************
1019  //************************************************************************************
1020 
1023 
1024  PointType PointOnCurveSecondDerivative(const SplineType& rSpline, double& t, double s = 0.5)
1025  {
1026  Vector Basis = ZeroVector(4);
1027 
1028  Basis = SecondDerivativeSplineBasis( Basis, t, s );
1029 
1030  PointType Result = Basis[0] * rSpline.P0 + Basis[1] * rSpline.P1 + Basis[2] * rSpline.P2 + Basis[3] * rSpline.P3;
1031 
1032  return Result;
1033  }
1034 
1035 
1036  //************************************************************************************
1037  //************************************************************************************
1038 
1041 
1042  static inline std::vector<Vector>& SplineCoefficients(const SplineType& rSpline, std::vector<Vector>& rCoefficients, double s = 0.5)
1043  {
1044  if( rCoefficients.size() != 4 )
1045  rCoefficients.resize(4);
1046 
1047  rCoefficients[0] = (rSpline.P2 - rSpline.P0) * s + rSpline.P1 * (2.0 - s) + rSpline.P1 * (s - 2.0);
1048  rCoefficients[1] = (2.0 * rSpline.P0 - rSpline.P2) * s + rSpline.P1 * (s - 3.0) + rSpline.P1 * (3.0 - 2.0 * s);
1049  rCoefficients[2] = (rSpline.P1 - rSpline.P0) * s;
1050  rCoefficients[3] = rSpline.P0;
1051 
1052  return rCoefficients;
1053  }
1054 
1055 
1056  //************************************************************************************
1057  //************************************************************************************
1058 
1061 
1062  static inline Vector& SplineBasis(Vector& Basis, double& t, double s = 0.5)
1063  {
1064  if( Basis.size() != 4 )
1065  Basis.resize(4,false);
1066 
1067  Basis[0] = ((-t + 2.0) * t - 1.0) * t * s;
1068  Basis[1] = ((((2.0/s - 1.0) * t + (1.0 - 3.0/s)) * t) * t + 1.0/s) * s;
1069  Basis[2] = (((1.0 - 2.0/s) * t + (3.0/s - 2.0)) * t + 1.0) * t * s;
1070  Basis[3] = ((t - 1.0) * t * t) * s;
1071 
1072  return Basis;
1073  }
1074 
1075 
1076  //************************************************************************************
1077  //************************************************************************************
1078 
1081 
1082  static inline Vector& FirstDerivativeSplineBasis(Vector& Basis, double& t, double s = 0.5)
1083  {
1084  if( Basis.size() != 4 )
1085  Basis.resize(4,false);
1086 
1087  Basis[0] = ((-3.0 * t + 4.0) * t - 1.0) * s;
1088  Basis[1] = (((6.0/s - 3.0) * t + (2.0 - 6.0/s)) * t) * s;
1089  Basis[2] = (((3.0 - 6.0/s) * t + (6.0/s - 4.0)) * t + 1.0) * s;
1090  Basis[3] = (3.0 * t - 2.0) * t * s;
1091 
1092  return Basis;
1093  }
1094 
1095  //************************************************************************************
1096  //************************************************************************************
1097 
1100 
1101  static inline Vector& SecondDerivativeSplineBasis(Vector& Basis, double& t, double s = 0.5)
1102  {
1103  if( Basis.size() != 4 )
1104  Basis.resize(4,false);
1105 
1106  Basis[0] = (-6.0 * t + 4.0) * s;
1107  Basis[1] = ((12.0/s - 6.0) * t + (2.0 - 6.0/s)) * s;
1108  Basis[2] = ((6.0 - 12.0/s) * t + (6.0/s - 4.0)) * s;
1109  Basis[3] = (6.0 * t - 2.0) * s;
1110 
1111  return Basis;
1112  }
1113 
1114 
1118 
1119 
1123 
1124 
1128 
1132 
1133 
1135 
1136 
1137  protected:
1140 
1141 
1145 
1146 
1150 
1151 
1155 
1156 
1160 
1161 
1165 
1166 
1170 
1171 
1173  private:
1176 
1177 
1181 
1182  int mEchoLevel;
1183 
1184  bool mParallel;
1185 
1189 
1193 
1194 
1198 
1199 
1203 
1204 
1208 
1210 
1211 
1212  }; // Class SplineCurveUtilities
1213 
1217 
1218 
1222 
1224 
1225 } // namespace Kratos.
1226 
1227 #endif // KRATOS_SPLINE_CURVE_UTILITIES_H_INCLUDED defined
1228 
1229 
Short class definition.
Definition: bucket.h:57
void resize(std::size_t NewSize1, std::size_t NewSize2, bool preserve=0)
Definition: amatrix_interface.h:224
MeshType::NodesContainerType NodesContainerType
Nodes container. Which is a vector set of nodes with their Id's as key.
Definition: model_part.h:128
This class defines the node.
Definition: node.h:65
Point class.
Definition: point.h:59
Short class definition.
Definition: spline_curve_utilities.hpp:44
double SquareDistancePointToSpline(const PointType &rPoint, const SplineType &rSpline, double &t)
Definition: spline_curve_utilities.hpp:922
Tree< KDTreePartition< BucketType > > KdtreeType
Definition: spline_curve_utilities.hpp:62
double ArchLengthGeometricIntegration(SplineType &rSpline, double &a, double &b)
Definition: spline_curve_utilities.hpp:448
double QuadraticMinimizationMethod(const PointType &rPoint, const NodePointerTypeVector &rKnotsList, SplineType &rSpline, double iters, double s=0.5)
Definition: spline_curve_utilities.hpp:733
std::vector< double >::iterator DistanceIterator
Definition: spline_curve_utilities.hpp:60
PointType PointOnCurveFirstDerivative(const SplineType &rSpline, double &t, double s=0.5)
Definition: spline_curve_utilities.hpp:1006
static Vector & SplineBasis(Vector &Basis, double &t, double s=0.5)
Definition: spline_curve_utilities.hpp:1062
void SetSpline(SplineType &rOutputSpline, const SplineType &rInputSpline)
Definition: spline_curve_utilities.hpp:509
ModelPart::NodesContainerType NodesContainerType
Definition: spline_curve_utilities.hpp:50
void SetSpline(SplineType &rSpline, const PointType &P0, const PointType &P1, const PointType &P2, const PointType &P3)
Definition: spline_curve_utilities.hpp:523
NodePointerTypeVector::iterator NodePointerIterator
Definition: spline_curve_utilities.hpp:58
static std::vector< Vector > & SplineCoefficients(const SplineType &rSpline, std::vector< Vector > &rCoefficients, double s=0.5)
Definition: spline_curve_utilities.hpp:1042
PointType PointOnCurveSecondDerivative(const SplineType &rSpline, double &t, double s=0.5)
Definition: spline_curve_utilities.hpp:1024
NodeType::Pointer NodePointerType
Definition: spline_curve_utilities.hpp:55
PointType & CalculatePointProjection(const PointType &rPoint, KdtreeType &rKnotsKdtree, const NodePointerTypeVector &rKnotsList, PointType &rPointProjection)
Definition: spline_curve_utilities.hpp:567
double IntegrateSubInterval(SplineType &rSpline, int n=0)
Definition: spline_curve_utilities.hpp:424
PointType & PointOnCurve(PointType &rPoint, const SplineType &rSpline, double &t, double s=0.5)
Definition: spline_curve_utilities.hpp:987
double SecondDerivativeSquareDistancePointToSpline(const PointType &rPoint, const SplineType &rSpline, double &t)
Definition: spline_curve_utilities.hpp:958
SplineCurveUtilities()
Default constructor.
Definition: spline_curve_utilities.hpp:80
void SetSpline(SplineType &rSpline, const NodePointerTypeVector &rKnotsList, int &id)
Definition: spline_curve_utilities.hpp:537
SplineCurveUtilities(bool Parallel)
Definition: spline_curve_utilities.hpp:82
double SimpsonRuleIntegration(SplineType &rSpline, double &a, double &b, double n=1)
Definition: spline_curve_utilities.hpp:464
double AdaptiveIntegration(SplineType &rSpline)
Definition: spline_curve_utilities.hpp:371
~SplineCurveUtilities()
Destructor.
Definition: spline_curve_utilities.hpp:85
std::vector< double > DistanceVector
Definition: spline_curve_utilities.hpp:59
std::vector< NodePointerType > NodePointerTypeVector
Definition: spline_curve_utilities.hpp:56
double FirstDerivativeSquareDistancePointToSpline(const PointType &rPoint, const SplineType &rSpline, double &t)
Definition: spline_curve_utilities.hpp:938
static Vector & FirstDerivativeSplineBasis(Vector &Basis, double &t, double s=0.5)
Definition: spline_curve_utilities.hpp:1082
Vector & CalculateSquareArchLengthDifferences(Vector &rSquareDifference, const Vector &rEstimates)
Definition: spline_curve_utilities.hpp:894
Bucket< 3, NodeType, NodePointerTypeVector, NodePointerType, NodePointerIterator, DistanceIterator > BucketType
Definition: spline_curve_utilities.hpp:61
void CreateParametrizedCurve(NodePointerTypeVector &rGeneratrixPoints, NodePointerTypeVector &rKnotsList, int m)
Definition: spline_curve_utilities.hpp:101
double EvaluateDistancePolynomial(const Vector &rFunction, const Vector &rEstimates, double &Sk)
Definition: spline_curve_utilities.hpp:867
array_1d< double, 3 > PointType
Definition: spline_curve_utilities.hpp:53
Node NodeType
Definition: spline_curve_utilities.hpp:54
double NewtonsMethod(const PointType &rPoint, const NodePointerTypeVector &rKnotsList, SplineType &rSpline, double Spredict=0, double iters=20, double s=0.5)
Definition: spline_curve_utilities.hpp:639
Vector & CalculateArchLengthDifferences(Vector &rDifference, const Vector &rEstimates)
Definition: spline_curve_utilities.hpp:882
double CombinedMethod(const PointType &rPoint, const NodePointerTypeVector &rKnotsList, SplineType &rSpline, double s=0.5)
Definition: spline_curve_utilities.hpp:614
static Vector & SecondDerivativeSplineBasis(Vector &Basis, double &t, double s=0.5)
Definition: spline_curve_utilities.hpp:1101
int GetClosestKnotId(const PointType &rPoint, KdtreeType &rKnotsKdtree, double &rPointDistance)
Definition: spline_curve_utilities.hpp:598
Vector & CalculateDistancePolynomialBasis(Vector &rPolynomialBasis, const Vector &rEstimates, double &rValue)
Definition: spline_curve_utilities.hpp:908
std::vector< NodeType > NodeTypeVector
Definition: spline_curve_utilities.hpp:57
double SplineGeometricLength(SplineType &rSpline, double &t)
Definition: spline_curve_utilities.hpp:496
A generic tree data structure for spatial partitioning.
Definition: tree.h:190
PointerType SearchNearestPoint(PointType const &ThisPoint, CoordinateType &rResultDistance)
Search for the nearest point to a given point.
Definition: tree.h:391
#define KRATOS_THROW_ERROR(ExceptionType, ErrorMessage, MoreInfo)
Definition: define.h:77
#define KRATOS_CATCH(MoreInfo)
Definition: define.h:110
#define KRATOS_TRY
Definition: define.h:109
REF: G. R. Cowper, GAUSSIAN QUADRATURE FORMULAS FOR TRIANGLES.
Definition: mesh_condition.cpp:21
KratosZeroVector< double > ZeroVector
Definition: amatrix_interface.h:561
TExpressionType::data_type norm_2(AMatrix::MatrixExpression< TExpressionType, TCategory > const &TheExpression)
Definition: amatrix_interface.h:625
TExpression1Type::data_type inner_prod(AMatrix::MatrixExpression< TExpression1Type, TCategory1 > const &First, AMatrix::MatrixExpression< TExpression2Type, TCategory2 > const &Second)
Definition: amatrix_interface.h:592
TABLE_NUMBER_ANGULAR_VELOCITY TABLE_NUMBER_MOMENT I33 BEAM_INERTIA_ROT_UNIT_LENGHT_Y KRATOS_DEFINE_APPLICATION_VARIABLE(DEM_APPLICATION, double, BEAM_INERTIA_ROT_UNIT_LENGHT_Z) typedef std double
Definition: DEM_application_variables.h:182
float error
Definition: PecletTest.py:102
left
Definition: exact_hinsberg_test.py:140
h
Definition: generate_droplet_dynamics.py:91
a
Definition: generate_stokes_twofluid_element.py:77
S
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:39
b
Definition: generate_total_lagrangian_mixed_volumetric_strain_element.py:31
int t
Definition: ode_solve.py:392
int n
manufactured solution and derivatives (u=0 at z=0 dudz=0 at z=domain_height)
Definition: ode_solve.py:402
int k
Definition: quadrature.py:595
int j
Definition: quadrature.py:648
int m
Definition: run_marine_rain_substepping.py:8
integer i
Definition: TensorModule.f:17
e
Definition: run_cpp_mpi_tests.py:31
Definition: spline_curve_utilities.hpp:66
PointType P0
Definition: spline_curve_utilities.hpp:68
PointType P1
Definition: spline_curve_utilities.hpp:69
int id
Definition: spline_curve_utilities.hpp:67
PointType P3
Definition: spline_curve_utilities.hpp:71
PointType P2
Definition: spline_curve_utilities.hpp:70