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