b80b4151e250a94b2db2ea5f859b7def9ac3292a
[occt.git] / src / Geom2d / Geom2d_BSplineCurve_1.cxx
1 // Created on: 1991-07-05
2 // Created by: JCV
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // 03-02-97 : pmn ->LocateU sur Periodic (PRO6963), 
18 //            bon appel a LocateParameter (PRO6973) et mise en conformite avec
19 //            le cdl de LocateU, lorsque U est un noeud (PRO6988)
20
21 #define No_Standard_OutOfRange
22 #define No_Standard_DimensionError
23
24 #include <Geom2d_BSplineCurve.jxx>
25 #include <BSplCLib.hxx>
26 #include <gp.hxx>
27
28 #include <Geom2d_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
35 #define  POLES    (poles->Array1())
36 #define  KNOTS    (knots->Array1())
37 #define  FKNOTS   (flatknots->Array1())
38 #define  FMULTS   (BSplCLib::NoMults())
39
40 //=======================================================================
41 //function : IsCN
42 //purpose  : 
43 //=======================================================================
44
45 Standard_Boolean Geom2d_BSplineCurve::IsCN ( const Standard_Integer N) const
46 {
47   Standard_RangeError_Raise_if
48     (N < 0, "Geom2d_BSplineCurve::IsCN");
49
50   switch (smooth) {
51   case GeomAbs_CN : return Standard_True;
52   case GeomAbs_C0 : return N <= 0;
53   case GeomAbs_G1 : return N <= 0;
54   case GeomAbs_C1 : return N <= 1;
55   case GeomAbs_G2 : return N <= 1;
56   case GeomAbs_C2 : return N <= 2;
57   case GeomAbs_C3 : 
58     return N <= 3 ? Standard_True :
59            N <= deg - BSplCLib::MaxKnotMult (mults->Array1(), mults->Lower() + 1, mults->Upper() - 1);
60   default:
61     return Standard_False;
62   }
63 }
64 //=======================================================================
65 //function : IsG1
66 //purpose  : 
67 //=======================================================================
68
69 Standard_Boolean Geom2d_BSplineCurve::IsG1 ( const Standard_Real theTf,
70                                            const Standard_Real theTl,
71                                            const Standard_Real theAngTol) const
72 {
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_Pnt2d aP1, aP2;
96     gp_Vec2d 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_Pnt2d aP;
128   gp_Vec2d 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
142   return Standard_True;
143
144 }
145
146 //=======================================================================
147 //function : IsClosed
148 //purpose  : 
149 //=======================================================================
150
151 Standard_Boolean Geom2d_BSplineCurve::IsClosed () const
152 { return (StartPoint().Distance (EndPoint())) <= gp::Resolution (); }
153
154
155
156 //=======================================================================
157 //function : IsPeriodic
158 //purpose  : 
159 //=======================================================================
160
161 Standard_Boolean Geom2d_BSplineCurve::IsPeriodic () const
162 { return periodic; }
163
164 //=======================================================================
165 //function : Continuity
166 //purpose  : 
167 //=======================================================================
168
169 GeomAbs_Shape Geom2d_BSplineCurve::Continuity () const
170 { return smooth; }
171
172 //=======================================================================
173 //function : Degree
174 //purpose  : 
175 //=======================================================================
176
177 Standard_Integer Geom2d_BSplineCurve::Degree () const
178 { return deg; }
179
180
181 //=======================================================================
182 //function : D0
183 //purpose  : 
184 //=======================================================================
185
186 void Geom2d_BSplineCurve::D0 ( const Standard_Real U, 
187                               gp_Pnt2d& P) const
188 {
189   Standard_Real NewU(U);
190   PeriodicNormalization(NewU);
191
192   Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
193   Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
194
195   if (!IsCacheValid(NewU))
196     MyCurve->ValidateCache(NewU);
197   
198   if(rational)
199   {
200     BSplCLib::CacheD0(NewU,
201                       deg,
202                       parametercache,
203                       spanlenghtcache,
204                       (cachepoles->Array1()),
205                       cacheweights->Array1(),
206                       P) ;
207   }
208   else {
209     BSplCLib::CacheD0(NewU,
210                       deg,
211                       parametercache,
212                       spanlenghtcache,
213                       (cachepoles->Array1()),
214                       BSplCLib::NoWeights(),
215                       P) ;
216   }
217 }
218
219
220 //=======================================================================
221 //function : D1
222 //purpose  : 
223 //=======================================================================
224
225 void Geom2d_BSplineCurve::D1 (const Standard_Real U,
226                               gp_Pnt2d& P,
227                               gp_Vec2d& V1) const
228 {
229   Standard_Real NewU(U);
230   PeriodicNormalization(NewU);
231
232   Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
233   Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
234
235   if (!IsCacheValid(NewU))
236     MyCurve->ValidateCache(NewU);
237   
238   if(rational)
239   {
240     BSplCLib::CacheD1(NewU,
241                       deg,
242                       parametercache,
243                       spanlenghtcache,
244                       (cachepoles->Array1()),
245                       cacheweights->Array1(),
246                       P,
247                       V1) ;
248   }
249   else {
250     BSplCLib::CacheD1(NewU,
251                       deg,
252                       parametercache,
253                       spanlenghtcache,
254                       (cachepoles->Array1()),
255                       BSplCLib::NoWeights(),
256                       P,
257                       V1) ;
258   }
259 }
260
261 //=======================================================================
262 //function : D2
263 //purpose  : 
264 //=======================================================================
265
266 void Geom2d_BSplineCurve::D2 (const Standard_Real U ,
267                               gp_Pnt2d& P ,
268                               gp_Vec2d& V1,
269                               gp_Vec2d& V2 ) const
270 {
271   Standard_Real NewU(U);
272   PeriodicNormalization(NewU);
273
274   Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
275   Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
276
277   if (!IsCacheValid(NewU))
278     MyCurve->ValidateCache(NewU);
279   
280   if(rational)
281   {
282     BSplCLib::CacheD2(NewU,
283                       deg,
284                       parametercache,
285                       spanlenghtcache,
286                       (cachepoles->Array1()),
287                       cacheweights->Array1(),
288                       P,
289                       V1,
290                       V2) ;
291   }
292   else {
293     BSplCLib::CacheD2(NewU,
294                       deg,
295                       parametercache,
296                       spanlenghtcache,
297                       (cachepoles->Array1()),
298                       BSplCLib::NoWeights(),
299                       P,
300                       V1,
301                       V2) ;
302   }
303 }
304
305 //=======================================================================
306 //function : D3
307 //purpose  : 
308 //=======================================================================
309
310 void Geom2d_BSplineCurve::D3  (const Standard_Real U ,
311                                gp_Pnt2d& P ,
312                                gp_Vec2d& V1,
313                                gp_Vec2d& V2,
314                                gp_Vec2d& V3 ) const
315 {
316   Standard_Real NewU(U);
317   PeriodicNormalization(NewU);
318
319   Geom2d_BSplineCurve* MyCurve = (Geom2d_BSplineCurve *) this;
320   Standard_Mutex::Sentry aSentry(MyCurve->myMutex);
321
322   if (!IsCacheValid(NewU))
323     MyCurve->ValidateCache(NewU);
324   
325   if(rational)
326   {
327     BSplCLib::CacheD3(NewU,
328                       deg,
329                       parametercache,
330                       spanlenghtcache,
331                       (cachepoles->Array1()),
332                       cacheweights->Array1(),
333                       P,
334                       V1,
335                       V2,
336                       V3) ;
337   }
338   else {
339     BSplCLib::CacheD3(NewU,
340                       deg,
341                       parametercache,
342                       spanlenghtcache,
343                       (cachepoles->Array1()),
344                       BSplCLib::NoWeights(),
345                       P,
346                       V1,
347                       V2,
348                       V3) ;
349   }
350 }
351
352 //=======================================================================
353 //function : DN
354 //purpose  : 
355 //=======================================================================
356
357 gp_Vec2d Geom2d_BSplineCurve::DN  (const Standard_Real    U,
358                                    const Standard_Integer N ) const
359 {
360   gp_Vec2d V;
361
362   if ( rational ) {
363     BSplCLib::DN(U,N,0,deg,periodic,POLES,
364                  weights->Array1(),
365                  FKNOTS,FMULTS,V);
366   }
367   else {  
368     BSplCLib::DN(U,N,0,deg,periodic,POLES,
369                  *((TColStd_Array1OfReal*) NULL),
370                  FKNOTS,FMULTS,V);
371   }
372   return V;
373 }
374
375 //=======================================================================
376 //function : EndPoint
377 //purpose  : 
378 //=======================================================================
379
380 gp_Pnt2d Geom2d_BSplineCurve::EndPoint () const
381
382   if (mults->Value (knots->Upper ()) == deg + 1) 
383     return poles->Value (poles->Upper());
384   else
385     return Value(LastParameter());
386 }
387
388 //=======================================================================
389 //function : FirstUKnotIndex
390 //purpose  : 
391 //=======================================================================
392
393 Standard_Integer Geom2d_BSplineCurve::FirstUKnotIndex () const
394
395   if (periodic) return 1;
396   else return BSplCLib::FirstUKnotIndex (deg, mults->Array1()); 
397 }
398
399 //=======================================================================
400 //function : FirstParameter
401 //purpose  : 
402 //=======================================================================
403
404 Standard_Real Geom2d_BSplineCurve::FirstParameter () const
405 {
406   return flatknots->Value (deg+1); 
407 }
408
409 //=======================================================================
410 //function : Knot
411 //purpose  : 
412 //=======================================================================
413
414 Standard_Real Geom2d_BSplineCurve::Knot (const Standard_Integer Index) const
415 {
416   Standard_OutOfRange_Raise_if
417     (Index < 1 || Index > knots->Length(), "Geom2d_BSplineCurve::Knot");
418   return knots->Value (Index);
419 }
420
421 //=======================================================================
422 //function : KnotDistribution
423 //purpose  : 
424 //=======================================================================
425
426 GeomAbs_BSplKnotDistribution Geom2d_BSplineCurve::KnotDistribution () const
427
428   return knotSet; 
429 }
430
431 //=======================================================================
432 //function : Knots
433 //purpose  : 
434 //=======================================================================
435
436 void Geom2d_BSplineCurve::Knots (TColStd_Array1OfReal& K) const
437 {
438   Standard_DimensionError_Raise_if
439     (K.Length() != knots->Length(), "Geom2d_BSplineCurve::Knots");
440   K = knots->Array1();
441 }
442
443 //=======================================================================
444 //function : KnotSequence
445 //purpose  : 
446 //=======================================================================
447
448 void Geom2d_BSplineCurve::KnotSequence (TColStd_Array1OfReal& K) const
449 {
450   Standard_DimensionError_Raise_if
451     (K.Length() != flatknots->Length(), "Geom2d_BSplineCurve::KnotSequence");
452   K = flatknots->Array1();
453 }
454
455 //=======================================================================
456 //function : LastUKnotIndex
457 //purpose  : 
458 //=======================================================================
459
460 Standard_Integer Geom2d_BSplineCurve::LastUKnotIndex() const
461 {
462   if (periodic) return knots->Length();
463   else return BSplCLib::LastUKnotIndex (deg, mults->Array1()); 
464 }
465
466 //=======================================================================
467 //function : LastParameter
468 //purpose  : 
469 //=======================================================================
470
471 Standard_Real Geom2d_BSplineCurve::LastParameter () const
472 {
473   return flatknots->Value (flatknots->Upper()-deg); 
474 }
475
476 //=======================================================================
477 //function : LocalValue
478 //purpose  : 
479 //=======================================================================
480
481 gp_Pnt2d Geom2d_BSplineCurve::LocalValue
482 (const Standard_Real    U,
483  const Standard_Integer FromK1,
484  const Standard_Integer ToK2)   const
485 {
486   gp_Pnt2d P;
487   LocalD0(U,FromK1,ToK2,P);
488   return P;
489 }
490
491 //=======================================================================
492 //function : LocalD0
493 //purpose  : 
494 //=======================================================================
495
496 void  Geom2d_BSplineCurve::LocalD0
497 (const Standard_Real    U,
498  const Standard_Integer FromK1,
499  const Standard_Integer ToK2,
500  gp_Pnt2d& P)   const
501 {
502   Standard_DomainError_Raise_if (FromK1 == ToK2,
503                                  "Geom2d_BSplineCurve::LocalValue");
504
505   Standard_Real u = U;
506   Standard_Integer index = 0;
507   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
508   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
509
510   if ( rational ) {
511     BSplCLib::D0(u,index,deg,periodic,POLES,
512                  weights->Array1(),
513                  FKNOTS,FMULTS,P);
514   }
515   else {
516     BSplCLib::D0(u,index,deg,periodic,POLES,
517                  *((TColStd_Array1OfReal*) NULL),
518                  FKNOTS,FMULTS,P);
519   }
520 }
521
522 //=======================================================================
523 //function : LocalD1
524 //purpose  : 
525 //=======================================================================
526
527 void Geom2d_BSplineCurve::LocalD1 (const Standard_Real    U,
528                                    const Standard_Integer FromK1,
529                                    const Standard_Integer ToK2,
530                                    gp_Pnt2d&    P, 
531                                    gp_Vec2d&    V1)    const
532 {
533   Standard_DomainError_Raise_if (FromK1 == ToK2,
534                                  "Geom2d_BSplineCurve::LocalD1");
535   
536   Standard_Real u = U;
537   Standard_Integer index = 0;
538   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
539   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
540   
541   if (rational) {
542     BSplCLib::D1(u,index,deg,periodic,POLES,
543                  weights->Array1(),
544                  FKNOTS,FMULTS,P,V1);
545   }
546   else {
547     BSplCLib::D1(u,index,deg,periodic,POLES,
548                  *((TColStd_Array1OfReal*) NULL),
549                  FKNOTS,FMULTS,P,V1);
550   }
551 }
552
553 //=======================================================================
554 //function : LocalD2
555 //purpose  : 
556 //=======================================================================
557
558 void Geom2d_BSplineCurve::LocalD2
559 (const Standard_Real    U,
560  const Standard_Integer FromK1,
561  const Standard_Integer ToK2, 
562  gp_Pnt2d&    P,
563  gp_Vec2d&    V1,
564  gp_Vec2d&    V2) const
565 {
566   Standard_DomainError_Raise_if (FromK1 == ToK2,
567                                  "Geom2d_BSplineCurve::LocalD2");
568   
569   Standard_Real u = U;
570   Standard_Integer index = 0;
571   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
572   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
573   
574   if ( rational ) {
575     BSplCLib::D2(u,index,deg,periodic,POLES,
576                  weights->Array1(),
577                  FKNOTS,FMULTS,P,V1,V2);
578   }
579   else {
580     BSplCLib::D2(u,index,deg,periodic,POLES,
581                  *((TColStd_Array1OfReal*) NULL),
582                  FKNOTS,FMULTS,P,V1,V2);
583   }
584 }
585
586 //=======================================================================
587 //function : LocalD3
588 //purpose  : 
589 //=======================================================================
590
591 void Geom2d_BSplineCurve::LocalD3
592 (const Standard_Real    U,
593  const Standard_Integer FromK1,
594  const Standard_Integer ToK2, 
595  gp_Pnt2d&    P,
596  gp_Vec2d&    V1,
597  gp_Vec2d&    V2,
598  gp_Vec2d&    V3) const
599 {
600   Standard_DomainError_Raise_if (FromK1 == ToK2,
601                                  "Geom2d_BSplineCurve::LocalD3");
602   
603   Standard_Real u = U;
604   Standard_Integer index = 0;
605   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
606   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
607   
608   if ( rational ) {
609     BSplCLib::D3(u,index,deg,periodic,POLES,
610                  weights->Array1(),
611                  FKNOTS,FMULTS,P,V1,V2,V3);
612   }
613   else {
614     BSplCLib::D3(u,index,deg,periodic,POLES,
615                  *((TColStd_Array1OfReal*) NULL),
616                  FKNOTS,FMULTS,P,V1,V2,V3);
617   }
618 }
619
620 //=======================================================================
621 //function : LocalDN
622 //purpose  : 
623 //=======================================================================
624
625 gp_Vec2d Geom2d_BSplineCurve::LocalDN
626 (const Standard_Real    U,
627  const Standard_Integer FromK1,
628  const Standard_Integer ToK2,
629  const Standard_Integer N      ) const
630 {
631   Standard_DomainError_Raise_if (FromK1 == ToK2,
632                                  "Geom2d_BSplineCurve::LocalD3");
633   
634   Standard_Real u = U;
635   Standard_Integer index = 0;
636   BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
637   index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
638   
639   gp_Vec2d V;
640
641   if ( rational ) {
642     BSplCLib::DN(u,N,index,deg,periodic,POLES,
643                  weights->Array1(),
644                  FKNOTS,FMULTS,V);
645   }
646   else {
647     BSplCLib::DN(u,N,index,deg,periodic,POLES,
648                  *((TColStd_Array1OfReal*) NULL),
649                  FKNOTS,FMULTS,V);
650   }
651   return V;
652 }
653
654 //=======================================================================
655 //function : Multiplicity
656 //purpose  : 
657 //=======================================================================
658
659 Standard_Integer Geom2d_BSplineCurve::Multiplicity 
660 (const Standard_Integer Index) const
661 {
662   Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
663                                 "Geom2d_BSplineCurve::Multiplicity");
664   return mults->Value (Index);
665 }
666
667 //=======================================================================
668 //function : Multiplicities
669 //purpose  : 
670 //=======================================================================
671
672 void Geom2d_BSplineCurve::Multiplicities (TColStd_Array1OfInteger& M) const
673 {
674   Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
675                                     "Geom2d_BSplineCurve::Multiplicities");
676   M = mults->Array1();
677 }
678
679 //=======================================================================
680 //function : NbKnots
681 //purpose  : 
682 //=======================================================================
683
684 Standard_Integer Geom2d_BSplineCurve::NbKnots () const
685 { return knots->Length(); }
686
687 //=======================================================================
688 //function : NbPoles
689 //purpose  : 
690 //=======================================================================
691
692 Standard_Integer Geom2d_BSplineCurve::NbPoles () const
693 { return poles->Length(); }
694
695 //=======================================================================
696 //function : Pole
697 //purpose  : 
698 //=======================================================================
699
700 gp_Pnt2d Geom2d_BSplineCurve::Pole (const Standard_Integer Index) const
701 {
702   Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
703                                 "Geom2d_BSplineCurve::Pole");
704   return poles->Value (Index);      
705 }
706
707 //=======================================================================
708 //function : Poles
709 //purpose  : 
710 //=======================================================================
711
712 void Geom2d_BSplineCurve::Poles (TColgp_Array1OfPnt2d& P) const
713 {
714   Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
715                                     "Geom2d_BSplineCurve::Poles");
716   P = poles->Array1();
717 }
718
719 //=======================================================================
720 //function : StartPoint
721 //purpose  : 
722 //=======================================================================
723
724 gp_Pnt2d Geom2d_BSplineCurve::StartPoint () const
725 {
726   if (mults->Value (1) == deg + 1)  
727     return poles->Value (1);
728   else 
729     return Value(FirstParameter());
730 }
731
732 //=======================================================================
733 //function : Weight
734 //purpose  : 
735 //=======================================================================
736
737 Standard_Real Geom2d_BSplineCurve::Weight
738 (const Standard_Integer Index) const
739 {
740   Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
741                                 "Geom2d_BSplineCurve::Weight");
742   if (IsRational())
743     return weights->Value (Index);
744   else
745     return 1.;
746 }
747
748 //=======================================================================
749 //function : Weights
750 //purpose  : 
751 //=======================================================================
752
753 void Geom2d_BSplineCurve::Weights
754 (TColStd_Array1OfReal& W) const
755 {
756   Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
757                                     "Geom2d_BSplineCurve::Weights");
758   if (IsRational())
759     W = weights->Array1();
760   else {
761     Standard_Integer i;
762     for (i = W.Lower(); i <= W.Upper(); i++)
763       W(i) = 1.;
764   }
765 }
766
767 //=======================================================================
768 //function : IsRational
769 //purpose  : 
770 //=======================================================================
771
772 Standard_Boolean Geom2d_BSplineCurve::IsRational () const
773
774   return !weights.IsNull(); 
775
776
777 //=======================================================================
778 //function : Transform
779 //purpose  : 
780 //=======================================================================
781
782 void Geom2d_BSplineCurve::Transform
783 (const gp_Trsf2d& T)
784 {
785   TColgp_Array1OfPnt2d & CPoles = poles->ChangeArray1();
786   for (Standard_Integer I = 1; I <= CPoles.Length(); I++)  
787     CPoles (I).Transform (T);
788
789   InvalidateCache();
790   //  maxderivinvok = 0;
791 }
792
793 //=======================================================================
794 //function : LocateU
795 //purpose  : 
796 //=======================================================================
797
798 void Geom2d_BSplineCurve::LocateU
799 (const Standard_Real    U, 
800  const Standard_Real    ParametricTolerance, 
801  Standard_Integer&      I1,
802  Standard_Integer&      I2,
803  const Standard_Boolean WithKnotRepetition) const
804 {
805   Standard_Real NewU = U;
806   Handle(TColStd_HArray1OfReal) TheKnots;
807   if (WithKnotRepetition)  TheKnots = flatknots;
808   else                     TheKnots = knots;
809   
810   const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
811
812   PeriodicNormalization(NewU); //Attention a la periode
813   Standard_Real UFirst = CKnots (1);
814   Standard_Real ULast  = CKnots (CKnots.Length());
815   Standard_Real PParametricTolerance = Abs(ParametricTolerance);
816   if (Abs (NewU - UFirst) <= PParametricTolerance) { I1 = I2 = 1; }
817   else if (Abs (NewU - ULast) <= PParametricTolerance) { 
818     I1 = I2 = CKnots.Length();
819   }
820   else if (NewU < UFirst) {
821     I2 = 1;
822     I1 = 0;
823   }
824   else if (NewU > ULast) {
825     I1 = CKnots.Length();
826     I2 = I1 + 1;
827   }
828   else {
829     I1 = 1;
830     BSplCLib::Hunt (CKnots, NewU, I1);
831     while ( Abs( CKnots(I1+1) - NewU) <= PParametricTolerance) I1++;
832     if ( Abs( CKnots(I1) - NewU) <= PParametricTolerance) {
833       I2 = I1;
834     }
835     else {
836       I2 = I1 + 1;
837     }
838   }
839 }
840
841 //=======================================================================
842 //function : Resolution
843 //purpose  : 
844 //=======================================================================
845
846 void Geom2d_BSplineCurve::Resolution(const Standard_Real ToleranceUV,
847                                      Standard_Real &     UTolerance) 
848 {
849   Standard_Integer ii ;  
850   if(!maxderivinvok){
851     if ( periodic) {
852       Standard_Integer NbKnots, NbPoles;
853       BSplCLib::PrepareUnperiodize( deg, 
854                                    mults->Array1(),
855                                    NbKnots,
856                                    NbPoles);
857       TColgp_Array1OfPnt2d    new_poles(1,NbPoles) ;
858       TColStd_Array1OfReal  new_weights(1,NbPoles) ;
859       for(ii = 1 ; ii <= NbPoles ; ii++) {
860         new_poles(ii) = poles->Array1()(((ii-1) % poles->Length()) + 1) ;
861       }
862       if (rational) {
863         for(ii = 1 ; ii <= NbPoles ; ii++) {
864           new_weights(ii) = weights->Array1()(((ii-1) % poles->Length()) + 1) ;
865         }
866         BSplCLib::Resolution(new_poles,
867                              new_weights,
868                              new_poles.Length(),
869                              flatknots->Array1(),
870                              deg,
871                              1.,
872                              maxderivinv) ;
873       }
874       else {
875         BSplCLib::Resolution(new_poles,
876                              *((TColStd_Array1OfReal*) NULL),
877                              new_poles.Length(),
878                              flatknots->Array1(),
879                              deg,
880                              1.,
881                              maxderivinv) ;
882       }
883     }
884     else {
885       if (rational) {
886         BSplCLib::Resolution(poles->Array1(),
887                              weights->Array1(),
888                              poles->Length(),
889                              flatknots->Array1(),
890                              deg,
891                              1.,
892                              maxderivinv) ;
893       }
894       else {
895         BSplCLib::Resolution(poles->Array1(),
896                              *((TColStd_Array1OfReal*) NULL),
897                              poles->Length(),
898                              flatknots->Array1(),
899                              deg,
900                              1.,
901                              maxderivinv) ;
902       }
903     }
904     maxderivinvok = 1;
905   } 
906   UTolerance = ToleranceUV * maxderivinv; 
907 }
908