96f214e08a9ca2201f810877bb0d055b1ff722a7
[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       *((TColStd_Array1OfReal*) NULL),
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       *((TColStd_Array1OfReal*) NULL),
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       *((TColStd_Array1OfReal*) NULL),
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       *((TColStd_Array1OfReal*) NULL),
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       *((TColStd_Array1OfReal*) NULL),
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_DimensionError_Raise_if
393     (K.Length() != knots->Length(), "Geom_BSplineCurve::Knots");
394   K = knots->Array1();
395 }
396
397 const TColStd_Array1OfReal& Geom_BSplineCurve::Knots() const
398 {
399   return knots->Array1();
400 }
401
402 //=======================================================================
403 //function : KnotSequence
404 //purpose  : 
405 //=======================================================================
406
407 void Geom_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
408 {
409   Standard_DimensionError_Raise_if
410     (K.Length() != flatknots->Length(), "Geom_BSplineCurve::KnotSequence");
411   K = flatknots->Array1();
412 }
413
414 const TColStd_Array1OfReal& Geom_BSplineCurve::KnotSequence() const
415 {
416   return flatknots->Array1();
417 }
418
419 //=======================================================================
420 //function : LastUKnotIndex
421 //purpose  : 
422 //=======================================================================
423
424 Standard_Integer Geom_BSplineCurve::LastUKnotIndex() const
425 {
426   if (periodic) return knots->Length();
427   else return BSplCLib::LastUKnotIndex (deg, mults->Array1()); 
428 }
429
430 //=======================================================================
431 //function : LastParameter
432 //purpose  : 
433 //=======================================================================
434
435 Standard_Real Geom_BSplineCurve::LastParameter () const
436 {
437   return flatknots->Value (flatknots->Upper()-deg); 
438 }
439
440 //=======================================================================
441 //function : LocalValue
442 //purpose  : 
443 //=======================================================================
444
445 gp_Pnt Geom_BSplineCurve::LocalValue
446   (const Standard_Real    U,
447    const Standard_Integer FromK1,
448    const Standard_Integer ToK2)   const
449 {
450   gp_Pnt P;
451   LocalD0(U,FromK1,ToK2,P);
452   return P;
453 }
454
455 //=======================================================================
456 //function : LocalD0
457 //purpose  : 
458 //=======================================================================
459
460 void  Geom_BSplineCurve::LocalD0
461   (const Standard_Real    U,
462    const Standard_Integer FromK1,
463    const Standard_Integer ToK2,
464    gp_Pnt& P)   const
465 {
466   Standard_DomainError_Raise_if (FromK1 == ToK2,
467                                  "Geom_BSplineCurve::LocalValue");
468
469   Standard_Real u = U;
470   Standard_Integer index = 0;
471   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
472   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
473   if (rational) {
474     BSplCLib::D0(u,index,deg,periodic,POLES,
475                  weights->Array1(),
476                  FKNOTS,FMULTS,P);
477   }
478   else {
479     BSplCLib::D0(u,index,deg,periodic,POLES,
480                  *((TColStd_Array1OfReal*) NULL),
481                  FKNOTS,FMULTS,P);
482   }
483 }
484
485 //=======================================================================
486 //function : LocalD1
487 //purpose  : 
488 //=======================================================================
489
490 void Geom_BSplineCurve::LocalD1 (const Standard_Real    U,
491                                  const Standard_Integer FromK1,
492                                  const Standard_Integer ToK2,
493                                  gp_Pnt&    P, 
494                                  gp_Vec&    V1)    const
495 {
496   Standard_DomainError_Raise_if (FromK1 == ToK2,
497                                  "Geom_BSplineCurve::LocalD1");
498   
499   Standard_Real u = U;
500   Standard_Integer index = 0;
501   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
502   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
503   if (rational) {
504     BSplCLib::D1(u,index,deg,periodic,POLES,
505                  weights->Array1(),
506                  FKNOTS,FMULTS,P,V1);
507   }
508   else {
509     BSplCLib::D1(u,index,deg,periodic,POLES,
510                  *((TColStd_Array1OfReal*) NULL),
511                  FKNOTS,FMULTS,P,V1);
512   }
513 }
514
515 //=======================================================================
516 //function : LocalD2
517 //purpose  : 
518 //=======================================================================
519
520 void Geom_BSplineCurve::LocalD2
521   (const Standard_Real    U,
522    const Standard_Integer FromK1,
523    const Standard_Integer ToK2, 
524    gp_Pnt&    P,
525    gp_Vec&    V1,
526    gp_Vec&    V2) const
527 {
528   Standard_DomainError_Raise_if (FromK1 == ToK2,
529                                  "Geom_BSplineCurve::LocalD2");
530   
531   Standard_Real u = U;
532   Standard_Integer index = 0;
533   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
534   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
535   if (rational) {
536     BSplCLib::D2(u,index,deg,periodic,POLES,
537                  weights->Array1(),
538                  FKNOTS,FMULTS,P,V1,V2);
539   }
540   else {
541     BSplCLib::D2(u,index,deg,periodic,POLES,
542                  *((TColStd_Array1OfReal*) NULL),
543                  FKNOTS,FMULTS,P,V1,V2);
544   }
545 }
546
547 //=======================================================================
548 //function : LocalD3
549 //purpose  : 
550 //=======================================================================
551
552 void Geom_BSplineCurve::LocalD3
553   (const Standard_Real    U,
554    const Standard_Integer FromK1,
555    const Standard_Integer ToK2, 
556    gp_Pnt&    P,
557    gp_Vec&    V1,
558    gp_Vec&    V2,
559    gp_Vec&    V3) const
560 {
561   Standard_DomainError_Raise_if (FromK1 == ToK2,
562                                  "Geom_BSplineCurve::LocalD3");
563   
564   Standard_Real u = U;
565   Standard_Integer index = 0;
566   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
567   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
568   if (rational) {
569     BSplCLib::D3(u,index,deg,periodic,POLES,
570                  weights->Array1(),
571                  FKNOTS,FMULTS,P,V1,V2,V3);
572   }
573   else {
574     BSplCLib::D3(u,index,deg,periodic,POLES,
575                  *((TColStd_Array1OfReal*) NULL),
576                  FKNOTS,FMULTS,P,V1,V2,V3);
577   }
578 }
579
580 //=======================================================================
581 //function : LocalDN
582 //purpose  : 
583 //=======================================================================
584
585 gp_Vec Geom_BSplineCurve::LocalDN
586   (const Standard_Real    U,
587    const Standard_Integer FromK1,
588    const Standard_Integer ToK2,
589    const Standard_Integer N      ) const
590 {
591   Standard_DomainError_Raise_if (FromK1 == ToK2,
592                                  "Geom_BSplineCurve::LocalD3");
593   
594   Standard_Real u = U;
595   Standard_Integer index = 0;
596   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
597   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
598   
599   gp_Vec V;
600   if (rational) {
601     BSplCLib::DN(u,N,index,deg,periodic,POLES,
602                  weights->Array1(),
603                  FKNOTS,FMULTS,V);
604   }
605   else {
606     BSplCLib::DN(u,N,index,deg,periodic,POLES,
607                  *((TColStd_Array1OfReal*) NULL),
608                  FKNOTS,FMULTS,V);
609   }
610   return V;
611 }
612
613 //=======================================================================
614 //function : Multiplicity
615 //purpose  : 
616 //=======================================================================
617
618 Standard_Integer Geom_BSplineCurve::Multiplicity 
619   (const Standard_Integer Index) const
620 {
621   Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
622                                 "Geom_BSplineCurve::Multiplicity");
623   return mults->Value (Index);
624 }
625
626 //=======================================================================
627 //function : Multiplicities
628 //purpose  : 
629 //=======================================================================
630
631 void Geom_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
632 {
633   Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
634                                     "Geom_BSplineCurve::Multiplicities");
635   M = mults->Array1();
636 }
637
638 const TColStd_Array1OfInteger& Geom_BSplineCurve::Multiplicities() const
639 {
640   return mults->Array1();
641 }
642
643 //=======================================================================
644 //function : NbKnots
645 //purpose  : 
646 //=======================================================================
647
648 Standard_Integer Geom_BSplineCurve::NbKnots () const
649 { return knots->Length(); }
650
651 //=======================================================================
652 //function : NbPoles
653 //purpose  : 
654 //=======================================================================
655
656 Standard_Integer Geom_BSplineCurve::NbPoles () const
657 { return poles->Length(); }
658
659 //=======================================================================
660 //function : Pole
661 //purpose  : 
662 //=======================================================================
663
664 gp_Pnt Geom_BSplineCurve::Pole (const Standard_Integer Index) const
665 {
666   Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
667                                 "Geom_BSplineCurve::Pole");
668   return poles->Value (Index);      
669 }
670
671 //=======================================================================
672 //function : Poles
673 //purpose  : 
674 //=======================================================================
675
676 void Geom_BSplineCurve::Poles (TColgp_Array1OfPnt& P) const
677 {
678   Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
679                                     "Geom_BSplineCurve::Poles");
680   P = poles->Array1();
681 }
682
683 const TColgp_Array1OfPnt& Geom_BSplineCurve::Poles() const
684 {
685   return poles->Array1();
686 }
687
688 //=======================================================================
689 //function : StartPoint
690 //purpose  : 
691 //=======================================================================
692
693 gp_Pnt Geom_BSplineCurve::StartPoint () const
694 {
695   if (mults->Value (1) == deg + 1)  
696     return poles->Value (1);
697   else 
698     return Value(FirstParameter());
699 }
700
701 //=======================================================================
702 //function : Weight
703 //purpose  : 
704 //=======================================================================
705
706 Standard_Real Geom_BSplineCurve::Weight
707   (const Standard_Integer Index) const
708 {
709   Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
710                                 "Geom_BSplineCurve::Weight");
711   if (IsRational())
712     return weights->Value (Index);
713   else
714     return 1.;
715 }
716
717 //=======================================================================
718 //function : Weights
719 //purpose  : 
720 //=======================================================================
721
722 void Geom_BSplineCurve::Weights
723   (TColStd_Array1OfReal& W) const
724 {
725   Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
726                                     "Geom_BSplineCurve::Weights");
727   if (IsRational())
728     W = weights->Array1();
729   else {
730     Standard_Integer i;
731
732     for (i = W.Lower(); i <= W.Upper(); i++)
733       W(i) = 1.;
734   }
735 }
736
737 const TColStd_Array1OfReal& Geom_BSplineCurve::Weights() const
738 {
739   if (IsRational())
740     return weights->Array1();
741   return BSplCLib::NoWeights();
742 }
743
744 //=======================================================================
745 //function : IsRational
746 //purpose  : 
747 //=======================================================================
748
749 Standard_Boolean Geom_BSplineCurve::IsRational () const
750
751   return !weights.IsNull(); 
752
753
754 //=======================================================================
755 //function : Transform
756 //purpose  : 
757 //=======================================================================
758
759 void Geom_BSplineCurve::Transform
760   (const gp_Trsf& T)
761 {
762   TColgp_Array1OfPnt & CPoles = poles->ChangeArray1();
763   for (Standard_Integer I = 1; I <= CPoles.Length(); I++)  
764     CPoles (I).Transform (T);
765   maxderivinvok = 0;
766 }
767
768 //=======================================================================
769 //function : LocateU
770 //purpose  : 
771 // pmn : 30/01/97 mise en conformite avec le cdl, lorsque U est un noeud
772 // (PRO6988)
773 //=======================================================================
774
775 void Geom_BSplineCurve::LocateU
776   (const Standard_Real    U, 
777    const Standard_Real    ParametricTolerance, 
778    Standard_Integer&      I1,
779    Standard_Integer&      I2,
780    const Standard_Boolean WithKnotRepetition) const
781 {
782   Standard_Real NewU = U;
783   Handle(TColStd_HArray1OfReal) TheKnots;
784   if (WithKnotRepetition)  TheKnots = flatknots;
785   else                     TheKnots = knots;
786   const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
787
788   PeriodicNormalization(NewU); //Attention a la periode
789   
790   Standard_Real UFirst = CKnots (1);
791   Standard_Real ULast  = CKnots (CKnots.Length());
792   Standard_Real PParametricTolerance = Abs(ParametricTolerance);
793   if (Abs (NewU - UFirst) <= PParametricTolerance) { I1 = I2 = 1; }
794   else if (Abs (NewU - ULast) <= PParametricTolerance) { 
795     I1 = I2 = CKnots.Length();
796   }
797   else if (NewU < UFirst) {
798     I2 = 1;
799     I1 = 0;
800   }
801   else if (NewU > ULast) {
802     I1 = CKnots.Length();
803     I2 = I1 + 1;
804   }
805   else {
806     I1 = 1;
807     BSplCLib::Hunt (CKnots, NewU, I1);
808     while ( Abs( CKnots(I1+1) - NewU) <= PParametricTolerance) I1++;
809     if ( Abs( CKnots(I1) - NewU) <= PParametricTolerance) {
810       I2 = I1;
811     }
812     else {
813       I2 = I1 + 1;
814     }
815   }
816 }
817
818 //=======================================================================
819 //function : Resolution
820 //purpose  : 
821 //=======================================================================
822
823 void Geom_BSplineCurve::Resolution(const Standard_Real Tolerance3D,
824                                    Standard_Real &     UTolerance) 
825 {
826   Standard_Integer ii;  
827   if(!maxderivinvok){
828     if ( periodic) {
829       Standard_Integer NbKnots, NbPoles;
830       BSplCLib::PrepareUnperiodize( deg, 
831                                     mults->Array1(),
832                                     NbKnots,
833                                     NbPoles);
834       TColgp_Array1OfPnt    new_poles(1,NbPoles) ;
835       TColStd_Array1OfReal  new_weights(1,NbPoles) ;
836       for(ii = 1 ; ii <= NbPoles ; ii++) {
837         new_poles(ii) = poles->Array1()((ii-1) % poles->Length() + 1) ;
838       }
839       if (rational) {
840         for(ii = 1 ; ii <= NbPoles ; ii++) {
841           new_weights(ii) = weights->Array1()((ii-1) % poles->Length() + 1) ;
842         }
843         BSplCLib::Resolution(new_poles,
844                              new_weights,
845                              new_poles.Length(),
846                              flatknots->Array1(),
847                              deg,
848                              1.,
849                              maxderivinv) ;
850       }
851       else {
852         BSplCLib::Resolution(new_poles,
853                              *((TColStd_Array1OfReal*) NULL),
854                              new_poles.Length(),
855                              flatknots->Array1(),
856                              deg,
857                              1.,
858                              maxderivinv) ;
859       }
860       
861     }
862     else {
863       if (rational) {
864         BSplCLib::Resolution(poles->Array1(),
865                              weights->Array1(),
866                              poles->Length(),
867                              flatknots->Array1(),
868                              deg,
869                              1.,
870                              maxderivinv) ;
871       }
872       else {
873         BSplCLib::Resolution(poles->Array1(),
874                              *((TColStd_Array1OfReal*) NULL),
875                              poles->Length(),
876                              flatknots->Array1(),
877                              deg,
878                              1.,
879                              maxderivinv) ;
880       }
881     }
882     maxderivinvok = 1;
883   }
884   UTolerance = Tolerance3D * maxderivinv;
885 }
886
887 //=======================================================================
888 //function : IsEqual
889 //purpose  : 
890 //=======================================================================
891
892 Standard_Boolean Geom_BSplineCurve::IsEqual(const Handle(Geom_BSplineCurve)& theOther,
893                                             const Standard_Real thePreci) const
894 {
895   if(  knots.IsNull() || poles.IsNull() || mults.IsNull() )
896     return Standard_False;
897   if( deg != theOther->Degree())
898     return Standard_False;
899   if( knots->Length() != theOther->NbKnots() ||
900     poles->Length() !=  theOther->NbPoles())
901     return Standard_False;
902
903   Standard_Integer i = 1;
904    for( i = 1 ; i <= poles->Length(); i++ )
905   {
906     const gp_Pnt& aPole1 = poles->Value(i);
907     const gp_Pnt& aPole2 =theOther->Pole(i);
908     if( fabs( aPole1.X() - aPole2.X() ) > thePreci ||
909       fabs( aPole1.Y() - aPole2.Y() ) > thePreci ||
910       fabs( aPole1.Z() - aPole2.Z() ) > thePreci )
911       return Standard_False;
912   }
913
914   for( ; i <= knots->Length(); i++ )
915   {
916     if( fabs(knots->Value(i) - theOther->Knot(i)) > Precision::Parametric(thePreci) )
917       return Standard_False;
918   }
919   
920   for( i = 1 ; i <= mults->Length(); i++ )
921   {
922     if( mults->Value(i) != theOther->Multiplicity(i) )
923       return Standard_False;
924   }
925
926   if( rational != theOther->IsRational())
927     return Standard_False;
928
929   if(!rational)
930     return Standard_True;
931
932   for( i = 1 ; i <= weights->Length(); i++ )
933   {
934     if( fabs( Standard_Real(weights->Value(i) - theOther->Weight(i))) > Epsilon(weights->Value(i)) )
935       return Standard_False;
936   }
937   return Standard_True;
938 }