0024624: Lost word in license statement in source files
[occt.git] / src / Geom2d / Geom2d_BSplineCurve_1.cxx
1 // Created on: 1991-07-05
2 // Created by: JCV
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // 03-02-97 : pmn ->LocateU sur Periodic (PRO6963), 
18 //            bon appel a LocateParameter (PRO6973) et mise en conformite avec
19 //            le cdl de LocateU, lorsque U est un noeud (PRO6988)
20
21 #define No_Standard_OutOfRange
22 #define No_Standard_DimensionError
23
24 #include <Geom2d_BSplineCurve.jxx>
25 #include <BSplCLib.hxx>
26 #include <gp.hxx>
27
28 #include <Geom2d_UndefinedDerivative.hxx>
29 #include <Standard_DimensionError.hxx>
30 #include <Standard_OutOfRange.hxx>
31 #include <Standard_DomainError.hxx>
32 #include <Standard_RangeError.hxx>
33 #include <Standard_Mutex.hxx>
34
35 #define  POLES    (poles->Array1())
36 #define  KNOTS    (knots->Array1())
37 #define  FKNOTS   (flatknots->Array1())
38 #define  FMULTS   (BSplCLib::NoMults())
39
40 //=======================================================================
41 //function : IsCN
42 //purpose  : 
43 //=======================================================================
44
45 Standard_Boolean Geom2d_BSplineCurve::IsCN ( const Standard_Integer N) const
46 {
47   Standard_RangeError_Raise_if
48     (N < 0, "Geom2d_BSplineCurve::IsCN");
49
50   switch (smooth) {
51   case GeomAbs_CN : return Standard_True;
52   case GeomAbs_C0 : return N <= 0;
53   case GeomAbs_G1 : return N <= 0;
54   case GeomAbs_C1 : return N <= 1;
55   case GeomAbs_G2 : return N <= 1;
56   case GeomAbs_C2 : return N <= 2;
57   case GeomAbs_C3 : 
58     return N <= 3 ? Standard_True :
59            N <= deg - BSplCLib::MaxKnotMult (mults->Array1(), mults->Lower() + 1, mults->Upper() - 1);
60   default:
61     return Standard_False;
62   }
63 }
64
65 //=======================================================================
66 //function : IsClosed
67 //purpose  : 
68 //=======================================================================
69
70 Standard_Boolean Geom2d_BSplineCurve::IsClosed () const
71 { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); }
72
73
74
75 //=======================================================================
76 //function : IsPeriodic
77 //purpose  : 
78 //=======================================================================
79
80 Standard_Boolean Geom2d_BSplineCurve::IsPeriodic () const
81 { return periodic; }
82
83 //=======================================================================
84 //function : Continuity
85 //purpose  : 
86 //=======================================================================
87
88 GeomAbs_Shape Geom2d_BSplineCurve::Continuity () const
89 { return smooth; }
90
91 //=======================================================================
92 //function : Degree
93 //purpose  : 
94 //=======================================================================
95
96 Standard_Integer Geom2d_BSplineCurve::Degree () const
97 { return deg; }
98
99
100 //=======================================================================
101 //function : D0
102 //purpose  : 
103 //=======================================================================
104
105 void Geom2d_BSplineCurve::D0 ( const Standard_Real U, 
106                               gp_Pnt2d& P) const
107 {
108   Standard_Real NewU(U);
109   PeriodicNormalization(NewU);
110
111   Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
112   Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
113
114   if (!IsCacheValid(NewU))
115     MyCurve->ValidateCache(NewU);
116   
117   if(rational)
118   {
119     BSplCLib::CacheD0(NewU,
120                       deg,
121                       parametercache,
122                       spanlenghtcache,
123                       (cachepoles->Array1()),
124                       cacheweights->Array1(),
125                       P) ;
126   }
127   else {
128     BSplCLib::CacheD0(NewU,
129                       deg,
130                       parametercache,
131                       spanlenghtcache,
132                       (cachepoles->Array1()),
133                       BSplCLib::NoWeights(),
134                       P) ;
135   }
136 }
137
138
139 //=======================================================================
140 //function : D1
141 //purpose  : 
142 //=======================================================================
143
144 void Geom2d_BSplineCurve::D1 (const Standard_Real U,
145                               gp_Pnt2d& P,
146                               gp_Vec2d& V1) const
147 {
148   Standard_Real NewU(U);
149   PeriodicNormalization(NewU);
150
151   Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
152   Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
153
154   if (!IsCacheValid(NewU))
155     MyCurve->ValidateCache(NewU);
156   
157   if(rational)
158   {
159     BSplCLib::CacheD1(NewU,
160                       deg,
161                       parametercache,
162                       spanlenghtcache,
163                       (cachepoles->Array1()),
164                       cacheweights->Array1(),
165                       P,
166                       V1) ;
167   }
168   else {
169     BSplCLib::CacheD1(NewU,
170                       deg,
171                       parametercache,
172                       spanlenghtcache,
173                       (cachepoles->Array1()),
174                       BSplCLib::NoWeights(),
175                       P,
176                       V1) ;
177   }
178 }
179
180 //=======================================================================
181 //function : D2
182 //purpose  : 
183 //=======================================================================
184
185 void Geom2d_BSplineCurve::D2 (const Standard_Real U ,
186                               gp_Pnt2d& P ,
187                               gp_Vec2d& V1,
188                               gp_Vec2d& V2 ) const
189 {
190   Standard_Real NewU(U);
191   PeriodicNormalization(NewU);
192
193   Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
194   Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
195
196   if (!IsCacheValid(NewU))
197     MyCurve->ValidateCache(NewU);
198   
199   if(rational)
200   {
201     BSplCLib::CacheD2(NewU,
202                       deg,
203                       parametercache,
204                       spanlenghtcache,
205                       (cachepoles->Array1()),
206                       cacheweights->Array1(),
207                       P,
208                       V1,
209                       V2) ;
210   }
211   else {
212     BSplCLib::CacheD2(NewU,
213                       deg,
214                       parametercache,
215                       spanlenghtcache,
216                       (cachepoles->Array1()),
217                       BSplCLib::NoWeights(),
218                       P,
219                       V1,
220                       V2) ;
221   }
222 }
223
224 //=======================================================================
225 //function : D3
226 //purpose  : 
227 //=======================================================================
228
229 void Geom2d_BSplineCurve::D3  (const Standard_Real U ,
230                                gp_Pnt2d& P ,
231                                gp_Vec2d& V1,
232                                gp_Vec2d& V2,
233                                gp_Vec2d& V3 ) const
234 {
235   Standard_Real NewU(U);
236   PeriodicNormalization(NewU);
237
238   Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
239   Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
240
241   if (!IsCacheValid(NewU))
242     MyCurve->ValidateCache(NewU);
243   
244   if(rational)
245   {
246     BSplCLib::CacheD3(NewU,
247                       deg,
248                       parametercache,
249                       spanlenghtcache,
250                       (cachepoles->Array1()),
251                       cacheweights->Array1(),
252                       P,
253                       V1,
254                       V2,
255                       V3) ;
256   }
257   else {
258     BSplCLib::CacheD3(NewU,
259                       deg,
260                       parametercache,
261                       spanlenghtcache,
262                       (cachepoles->Array1()),
263                       BSplCLib::NoWeights(),
264                       P,
265                       V1,
266                       V2,
267                       V3) ;
268   }
269 }
270
271 //=======================================================================
272 //function : DN
273 //purpose  : 
274 //=======================================================================
275
276 gp_Vec2d Geom2d_BSplineCurve::DN  (const Standard_Real    U,
277                                    const Standard_Integer N ) const
278 {
279   gp_Vec2d V;
280
281   if ( rational ) {
282     BSplCLib::DN(U,N,0,deg,periodic,POLES,
283                  weights->Array1(),
284                  FKNOTS,FMULTS,V);
285   }
286   else {  
287     BSplCLib::DN(U,N,0,deg,periodic,POLES,
288                  *((TColStd_Array1OfReal*) NULL),
289                  FKNOTS,FMULTS,V);
290   }
291   return V;
292 }
293
294 //=======================================================================
295 //function : EndPoint
296 //purpose  : 
297 //=======================================================================
298
299 gp_Pnt2d Geom2d_BSplineCurve::EndPoint () const
300
301   if (mults->Value (knots->Upper ()) == deg + 1) 
302     return poles->Value (poles->Upper());
303   else
304     return Value(LastParameter());
305 }
306
307 //=======================================================================
308 //function : FirstUKnotIndex
309 //purpose  : 
310 //=======================================================================
311
312 Standard_Integer Geom2d_BSplineCurve::FirstUKnotIndex () const
313
314   if (periodic) return 1;
315   else return BSplCLib::FirstUKnotIndex (deg, mults->Array1()); 
316 }
317
318 //=======================================================================
319 //function : FirstParameter
320 //purpose  : 
321 //=======================================================================
322
323 Standard_Real Geom2d_BSplineCurve::FirstParameter () const
324 {
325   return flatknots->Value (deg+1); 
326 }
327
328 //=======================================================================
329 //function : Knot
330 //purpose  : 
331 //=======================================================================
332
333 Standard_Real Geom2d_BSplineCurve::Knot (const Standard_Integer Index) const
334 {
335   Standard_OutOfRange_Raise_if
336     (Index < 1 || Index > knots->Length(), "Geom2d_BSplineCurve::Knot");
337   return knots->Value (Index);
338 }
339
340 //=======================================================================
341 //function : KnotDistribution
342 //purpose  : 
343 //=======================================================================
344
345 GeomAbs_BSplKnotDistribution Geom2d_BSplineCurve::KnotDistribution () const
346
347   return knotSet; 
348 }
349
350 //=======================================================================
351 //function : Knots
352 //purpose  : 
353 //=======================================================================
354
355 void Geom2d_BSplineCurve::Knots (TColStd_Array1OfReal& K) const
356 {
357   Standard_DimensionError_Raise_if
358     (K.Length() != knots->Length(), "Geom2d_BSplineCurve::Knots");
359   K = knots->Array1();
360 }
361
362 //=======================================================================
363 //function : KnotSequence
364 //purpose  : 
365 //=======================================================================
366
367 void Geom2d_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
368 {
369   Standard_DimensionError_Raise_if
370     (K.Length() != flatknots->Length(), "Geom2d_BSplineCurve::KnotSequence");
371   K = flatknots->Array1();
372 }
373
374 //=======================================================================
375 //function : LastUKnotIndex
376 //purpose  : 
377 //=======================================================================
378
379 Standard_Integer Geom2d_BSplineCurve::LastUKnotIndex() const
380 {
381   if (periodic) return knots->Length();
382   else return BSplCLib::LastUKnotIndex (deg, mults->Array1()); 
383 }
384
385 //=======================================================================
386 //function : LastParameter
387 //purpose  : 
388 //=======================================================================
389
390 Standard_Real Geom2d_BSplineCurve::LastParameter () const
391 {
392   return flatknots->Value (flatknots->Upper()-deg); 
393 }
394
395 //=======================================================================
396 //function : LocalValue
397 //purpose  : 
398 //=======================================================================
399
400 gp_Pnt2d Geom2d_BSplineCurve::LocalValue
401 (const Standard_Real    U,
402  const Standard_Integer FromK1,
403  const Standard_Integer ToK2)   const
404 {
405   gp_Pnt2d P;
406   LocalD0(U,FromK1,ToK2,P);
407   return P;
408 }
409
410 //=======================================================================
411 //function : LocalD0
412 //purpose  : 
413 //=======================================================================
414
415 void  Geom2d_BSplineCurve::LocalD0
416 (const Standard_Real    U,
417  const Standard_Integer FromK1,
418  const Standard_Integer ToK2,
419  gp_Pnt2d& P)   const
420 {
421   Standard_DomainError_Raise_if (FromK1 == ToK2,
422                                  "Geom2d_BSplineCurve::LocalValue");
423
424   Standard_Real u = U;
425   Standard_Integer index = 0;
426   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
427   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
428
429   if ( rational ) {
430     BSplCLib::D0(u,index,deg,periodic,POLES,
431                  weights->Array1(),
432                  FKNOTS,FMULTS,P);
433   }
434   else {
435     BSplCLib::D0(u,index,deg,periodic,POLES,
436                  *((TColStd_Array1OfReal*) NULL),
437                  FKNOTS,FMULTS,P);
438   }
439 }
440
441 //=======================================================================
442 //function : LocalD1
443 //purpose  : 
444 //=======================================================================
445
446 void Geom2d_BSplineCurve::LocalD1 (const Standard_Real    U,
447                                    const Standard_Integer FromK1,
448                                    const Standard_Integer ToK2,
449                                    gp_Pnt2d&    P, 
450                                    gp_Vec2d&    V1)    const
451 {
452   Standard_DomainError_Raise_if (FromK1 == ToK2,
453                                  "Geom2d_BSplineCurve::LocalD1");
454   
455   Standard_Real u = U;
456   Standard_Integer index = 0;
457   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
458   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
459   
460   if (rational) {
461     BSplCLib::D1(u,index,deg,periodic,POLES,
462                  weights->Array1(),
463                  FKNOTS,FMULTS,P,V1);
464   }
465   else {
466     BSplCLib::D1(u,index,deg,periodic,POLES,
467                  *((TColStd_Array1OfReal*) NULL),
468                  FKNOTS,FMULTS,P,V1);
469   }
470 }
471
472 //=======================================================================
473 //function : LocalD2
474 //purpose  : 
475 //=======================================================================
476
477 void Geom2d_BSplineCurve::LocalD2
478 (const Standard_Real    U,
479  const Standard_Integer FromK1,
480  const Standard_Integer ToK2, 
481  gp_Pnt2d&    P,
482  gp_Vec2d&    V1,
483  gp_Vec2d&    V2) const
484 {
485   Standard_DomainError_Raise_if (FromK1 == ToK2,
486                                  "Geom2d_BSplineCurve::LocalD2");
487   
488   Standard_Real u = U;
489   Standard_Integer index = 0;
490   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
491   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
492   
493   if ( rational ) {
494     BSplCLib::D2(u,index,deg,periodic,POLES,
495                  weights->Array1(),
496                  FKNOTS,FMULTS,P,V1,V2);
497   }
498   else {
499     BSplCLib::D2(u,index,deg,periodic,POLES,
500                  *((TColStd_Array1OfReal*) NULL),
501                  FKNOTS,FMULTS,P,V1,V2);
502   }
503 }
504
505 //=======================================================================
506 //function : LocalD3
507 //purpose  : 
508 //=======================================================================
509
510 void Geom2d_BSplineCurve::LocalD3
511 (const Standard_Real    U,
512  const Standard_Integer FromK1,
513  const Standard_Integer ToK2, 
514  gp_Pnt2d&    P,
515  gp_Vec2d&    V1,
516  gp_Vec2d&    V2,
517  gp_Vec2d&    V3) const
518 {
519   Standard_DomainError_Raise_if (FromK1 == ToK2,
520                                  "Geom2d_BSplineCurve::LocalD3");
521   
522   Standard_Real u = U;
523   Standard_Integer index = 0;
524   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
525   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
526   
527   if ( rational ) {
528     BSplCLib::D3(u,index,deg,periodic,POLES,
529                  weights->Array1(),
530                  FKNOTS,FMULTS,P,V1,V2,V3);
531   }
532   else {
533     BSplCLib::D3(u,index,deg,periodic,POLES,
534                  *((TColStd_Array1OfReal*) NULL),
535                  FKNOTS,FMULTS,P,V1,V2,V3);
536   }
537 }
538
539 //=======================================================================
540 //function : LocalDN
541 //purpose  : 
542 //=======================================================================
543
544 gp_Vec2d Geom2d_BSplineCurve::LocalDN
545 (const Standard_Real    U,
546  const Standard_Integer FromK1,
547  const Standard_Integer ToK2,
548  const Standard_Integer N      ) const
549 {
550   Standard_DomainError_Raise_if (FromK1 == ToK2,
551                                  "Geom2d_BSplineCurve::LocalD3");
552   
553   Standard_Real u = U;
554   Standard_Integer index = 0;
555   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
556   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
557   
558   gp_Vec2d V;
559
560   if ( rational ) {
561     BSplCLib::DN(u,N,index,deg,periodic,POLES,
562                  weights->Array1(),
563                  FKNOTS,FMULTS,V);
564   }
565   else {
566     BSplCLib::DN(u,N,index,deg,periodic,POLES,
567                  *((TColStd_Array1OfReal*) NULL),
568                  FKNOTS,FMULTS,V);
569   }
570   return V;
571 }
572
573 //=======================================================================
574 //function : Multiplicity
575 //purpose  : 
576 //=======================================================================
577
578 Standard_Integer Geom2d_BSplineCurve::Multiplicity 
579 (const Standard_Integer Index) const
580 {
581   Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
582                                 "Geom2d_BSplineCurve::Multiplicity");
583   return mults->Value (Index);
584 }
585
586 //=======================================================================
587 //function : Multiplicities
588 //purpose  : 
589 //=======================================================================
590
591 void Geom2d_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
592 {
593   Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
594                                     "Geom2d_BSplineCurve::Multiplicities");
595   M = mults->Array1();
596 }
597
598 //=======================================================================
599 //function : NbKnots
600 //purpose  : 
601 //=======================================================================
602
603 Standard_Integer Geom2d_BSplineCurve::NbKnots () const
604 { return knots->Length(); }
605
606 //=======================================================================
607 //function : NbPoles
608 //purpose  : 
609 //=======================================================================
610
611 Standard_Integer Geom2d_BSplineCurve::NbPoles () const
612 { return poles->Length(); }
613
614 //=======================================================================
615 //function : Pole
616 //purpose  : 
617 //=======================================================================
618
619 gp_Pnt2d Geom2d_BSplineCurve::Pole (const Standard_Integer Index) const
620 {
621   Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
622                                 "Geom2d_BSplineCurve::Pole");
623   return poles->Value (Index);      
624 }
625
626 //=======================================================================
627 //function : Poles
628 //purpose  : 
629 //=======================================================================
630
631 void Geom2d_BSplineCurve::Poles (TColgp_Array1OfPnt2d& P) const
632 {
633   Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
634                                     "Geom2d_BSplineCurve::Poles");
635   P = poles->Array1();
636 }
637
638 //=======================================================================
639 //function : StartPoint
640 //purpose  : 
641 //=======================================================================
642
643 gp_Pnt2d Geom2d_BSplineCurve::StartPoint () const
644 {
645   if (mults->Value (1) == deg + 1)  
646     return poles->Value (1);
647   else 
648     return Value(FirstParameter());
649 }
650
651 //=======================================================================
652 //function : Weight
653 //purpose  : 
654 //=======================================================================
655
656 Standard_Real Geom2d_BSplineCurve::Weight
657 (const Standard_Integer Index) const
658 {
659   Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
660                                 "Geom2d_BSplineCurve::Weight");
661   if (IsRational())
662     return weights->Value (Index);
663   else
664     return 1.;
665 }
666
667 //=======================================================================
668 //function : Weights
669 //purpose  : 
670 //=======================================================================
671
672 void Geom2d_BSplineCurve::Weights
673 (TColStd_Array1OfReal& W) const
674 {
675   Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
676                                     "Geom2d_BSplineCurve::Weights");
677   if (IsRational())
678     W = weights->Array1();
679   else {
680     Standard_Integer i;
681     for (i = W.Lower(); i <= W.Upper(); i++)
682       W(i) = 1.;
683   }
684 }
685
686 //=======================================================================
687 //function : IsRational
688 //purpose  : 
689 //=======================================================================
690
691 Standard_Boolean Geom2d_BSplineCurve::IsRational () const
692
693   return !weights.IsNull(); 
694
695
696 //=======================================================================
697 //function : Transform
698 //purpose  : 
699 //=======================================================================
700
701 void Geom2d_BSplineCurve::Transform
702 (const gp_Trsf2d& T)
703 {
704   TColgp_Array1OfPnt2d & CPoles = poles->ChangeArray1();
705   for (Standard_Integer I = 1; I <= CPoles.Length(); I++)  
706     CPoles (I).Transform (T);
707
708   InvalidateCache();
709   //  maxderivinvok = 0;
710 }
711
712 //=======================================================================
713 //function : LocateU
714 //purpose  : 
715 //=======================================================================
716
717 void Geom2d_BSplineCurve::LocateU
718 (const Standard_Real    U, 
719  const Standard_Real    ParametricTolerance, 
720  Standard_Integer&      I1,
721  Standard_Integer&      I2,
722  const Standard_Boolean WithKnotRepetition) const
723 {
724   Standard_Real NewU = U;
725   Handle(TColStd_HArray1OfReal) TheKnots;
726   if (WithKnotRepetition)  TheKnots = flatknots;
727   else                     TheKnots = knots;
728   
729   const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
730
731   PeriodicNormalization(NewU); //Attention a la periode
732   Standard_Real UFirst = CKnots (1);
733   Standard_Real ULast  = CKnots (CKnots.Length());
734   Standard_Real PParametricTolerance = Abs(ParametricTolerance);
735   if (Abs (NewU - UFirst) <= PParametricTolerance) { I1 = I2 = 1; }
736   else if (Abs (NewU - ULast) <= PParametricTolerance) { 
737     I1 = I2 = CKnots.Length();
738   }
739   else if (NewU < UFirst) {
740     I2 = 1;
741     I1 = 0;
742   }
743   else if (NewU > ULast) {
744     I1 = CKnots.Length();
745     I2 = I1 + 1;
746   }
747   else {
748     I1 = 1;
749     BSplCLib::Hunt (CKnots, NewU, I1);
750     while ( Abs( CKnots(I1+1) - NewU) <= PParametricTolerance) I1++;
751     if ( Abs( CKnots(I1) - NewU) <= PParametricTolerance) {
752       I2 = I1;
753     }
754     else {
755       I2 = I1 + 1;
756     }
757   }
758 }
759
760 //=======================================================================
761 //function : Resolution
762 //purpose  : 
763 //=======================================================================
764
765 void Geom2d_BSplineCurve::Resolution(const Standard_Real ToleranceUV,
766                                      Standard_Real &     UTolerance) 
767 {
768   Standard_Integer ii ;  
769   if(!maxderivinvok){
770     if ( periodic) {
771       Standard_Integer NbKnots, NbPoles;
772       BSplCLib::PrepareUnperiodize( deg, 
773                                    mults->Array1(),
774                                    NbKnots,
775                                    NbPoles);
776       TColgp_Array1OfPnt2d    new_poles(1,NbPoles) ;
777       TColStd_Array1OfReal  new_weights(1,NbPoles) ;
778       for(ii = 1 ; ii <= NbPoles ; ii++) {
779         new_poles(ii) = poles->Array1()(((ii-1) % poles->Length()) + 1) ;
780       }
781       if (rational) {
782         for(ii = 1 ; ii <= NbPoles ; ii++) {
783           new_weights(ii) = weights->Array1()(((ii-1) % poles->Length()) + 1) ;
784         }
785         BSplCLib::Resolution(new_poles,
786                              new_weights,
787                              new_poles.Length(),
788                              flatknots->Array1(),
789                              deg,
790                              1.,
791                              maxderivinv) ;
792       }
793       else {
794         BSplCLib::Resolution(new_poles,
795                              *((TColStd_Array1OfReal*) NULL),
796                              new_poles.Length(),
797                              flatknots->Array1(),
798                              deg,
799                              1.,
800                              maxderivinv) ;
801       }
802     }
803     else {
804       if (rational) {
805         BSplCLib::Resolution(poles->Array1(),
806                              weights->Array1(),
807                              poles->Length(),
808                              flatknots->Array1(),
809                              deg,
810                              1.,
811                              maxderivinv) ;
812       }
813       else {
814         BSplCLib::Resolution(poles->Array1(),
815                              *((TColStd_Array1OfReal*) NULL),
816                              poles->Length(),
817                              flatknots->Array1(),
818                              deg,
819                              1.,
820                              maxderivinv) ;
821       }
822     }
823     maxderivinvok = 1;
824   } 
825   UTolerance = ToleranceUV * maxderivinv; 
826 }
827