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