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