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