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