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