0023024: Update headers of OCCT files
[occt.git] / src / GeomAdaptor / GeomAdaptor_Curve.cxx
1 // Created on: 1993-04-29
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 // 20/02/97 : PMN -> Positionement local sur BSpline (PRO6902)
23 // 10/07/97 : PMN -> Pas de calcul de resolution dans Nb(Intervals)(PRO9248)
24 // 20/10/97 : RBV -> traitement des offset curves
25
26 #define No_Standard_RangeError
27 #define No_Standard_OutOfRange
28
29 #include <GeomAdaptor_Curve.ixx>
30
31 #include <GeomAdaptor_HCurve.hxx>
32 #include <Adaptor3d_HCurve.hxx>
33 #include <BSplCLib.hxx>
34 #include <GeomAbs_Shape.hxx>
35 #include <TColgp_Array1OfPnt.hxx>
36 #include <TColStd_Array1OfReal.hxx>
37 #include <TColStd_Array1OfInteger.hxx>
38 #include <TColStd_HArray1OfInteger.hxx>
39 #include <Precision.hxx>
40 #include <Geom_TrimmedCurve.hxx>
41 #include <Geom_Circle.hxx>
42 #include <Geom_Line.hxx>
43 #include <Geom_TrimmedCurve.hxx>
44 #include <Geom_BezierCurve.hxx>
45 #include <Geom_BSplineCurve.hxx>
46 #include <Geom_Ellipse.hxx>
47 #include <Geom_Parabola.hxx>
48 #include <Geom_Hyperbola.hxx>
49 //#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
50
51 #include <Standard_OutOfRange.hxx>
52 #include <Standard_NoSuchObject.hxx>
53 #include <Standard_NullObject.hxx>
54 #include <Standard_NotImplemented.hxx>
55 #include <Geom_OffsetCurve.hxx>
56
57 #define myBspl (*((Handle(Geom_BSplineCurve)*)&myCurve))
58 #define PosTol Precision::PConfusion()/2
59
60 //=======================================================================
61 //function : LocalContinuity
62 //purpose  : Computes the Continuity of a BSplineCurve 
63 //           between the parameters U1 and U2
64 //           The continuity is C(d-m) 
65 //             with   d = degree, 
66 //                    m = max multiplicity of the Knots between U1 and U2
67 //=======================================================================
68
69 GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1, 
70                                                  const Standard_Real U2) 
71      const 
72 {
73   Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
74   Standard_Integer Nb = myBspl->NbKnots();
75   Standard_Integer Index1 = 0;
76   Standard_Integer Index2 = 0;
77   Standard_Real newFirst, newLast;
78   TColStd_Array1OfReal    TK(1,Nb);
79   TColStd_Array1OfInteger TM(1,Nb);
80   myBspl->Knots(TK);
81   myBspl->Multiplicities(TM);
82   BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U1,myBspl->IsPeriodic(),
83                             1,Nb,Index1,newFirst);
84   BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U2,myBspl->IsPeriodic(),
85                             1,Nb,Index2,newLast);
86   if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) { 
87     if (Index1 < Nb) Index1++;
88   }
89   if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
90     Index2--;
91   Standard_Integer MultMax;
92   // attention aux courbes peridiques.
93   if ( (myBspl->IsPeriodic()) && (Index1 == Nb) )
94     Index1 = 1;
95
96   if ( Index2 - Index1 <= 0) {
97     MultMax = 100;  // CN entre 2 Noeuds consecutifs
98   }
99   else {
100     MultMax = TM(Index1+1);
101     for(Standard_Integer i = Index1+1;i<=Index2;i++) {
102       if ( TM(i)>MultMax) MultMax=TM(i);
103     }
104     MultMax = myBspl->Degree() - MultMax;
105   }
106   if ( MultMax <= 0) {
107     return GeomAbs_C0;
108   }
109   else if ( MultMax == 1) {
110     return GeomAbs_C1;
111   } 
112   else if ( MultMax == 2) {
113     return GeomAbs_C2;
114   }
115   else if ( MultMax == 3) {
116     return GeomAbs_C3;
117   }
118   else { 
119     return GeomAbs_CN;
120   }
121 }
122
123
124 //=======================================================================
125 //function : Load
126 //purpose  : 
127 //=======================================================================
128
129 void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
130                              const Standard_Real UFirst,
131                              const Standard_Real ULast)
132 {
133   myFirst = UFirst;
134   myLast  = ULast;
135
136   if ( myCurve != C) {
137     myCurve = C;
138     
139     const Handle(Standard_Type)& TheType = C->DynamicType();
140     if ( TheType == STANDARD_TYPE(Geom_TrimmedCurve)) {
141       Load((*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve(),UFirst,ULast);
142     }
143     else if ( TheType ==  STANDARD_TYPE(Geom_Circle)) {
144       myTypeCurve = GeomAbs_Circle;
145     }
146     else if ( TheType ==STANDARD_TYPE(Geom_Line)) {
147       myTypeCurve = GeomAbs_Line;
148     }
149     else if ( TheType == STANDARD_TYPE(Geom_Ellipse)) {
150       myTypeCurve = GeomAbs_Ellipse;
151     }
152     else if ( TheType == STANDARD_TYPE(Geom_Parabola)) {
153       myTypeCurve = GeomAbs_Parabola;
154     }
155     else if ( TheType == STANDARD_TYPE(Geom_Hyperbola)) {
156       myTypeCurve = GeomAbs_Hyperbola;
157     }
158     else if ( TheType == STANDARD_TYPE(Geom_BezierCurve)) {
159       myTypeCurve = GeomAbs_BezierCurve;
160     }
161     else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
162       myTypeCurve = GeomAbs_BSplineCurve;
163     }
164     else {
165       myTypeCurve = GeomAbs_OtherCurve;
166     }
167   }
168 }  
169
170 //    --
171 //    --     Global methods - Apply to the whole curve.
172 //    --     
173
174 //=======================================================================
175 //function : Continuity
176 //purpose  : 
177 //=======================================================================
178
179 GeomAbs_Shape GeomAdaptor_Curve::Continuity() const 
180 {
181   if (myTypeCurve == GeomAbs_BSplineCurve)
182     return LocalContinuity(myFirst, myLast);
183
184   if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
185   {
186     const GeomAbs_Shape S =
187       (*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve()->Continuity();
188     switch(S)
189     {
190       case GeomAbs_CN: return GeomAbs_CN;
191       case GeomAbs_C3: return GeomAbs_C2;
192       case GeomAbs_C2: return GeomAbs_C1;
193       case GeomAbs_C1: return GeomAbs_C0;  
194       default:
195       Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Continuity");
196     }
197   }
198   else if (myTypeCurve == GeomAbs_OtherCurve) {
199     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Contunuity");
200   }
201
202   return GeomAbs_CN;
203 }
204
205 //=======================================================================
206 //function : NbIntervals
207 //purpose  : 
208 //=======================================================================
209
210 Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) 
211 {
212   Standard_Integer myNbIntervals = 1;
213   Standard_Integer NbSplit;
214   if (myTypeCurve == GeomAbs_BSplineCurve) {
215     Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
216     Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
217     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
218     if ( S > Continuity()) {
219       Standard_Integer Cont;
220       switch ( S) {
221       case GeomAbs_G1:
222       case GeomAbs_G2:
223         Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
224         break;
225       case GeomAbs_C0:
226         myNbIntervals = 1;
227         break;
228       case GeomAbs_C1:
229       case GeomAbs_C2:
230       case GeomAbs_C3: 
231       case GeomAbs_CN: 
232         {
233           if      ( S == GeomAbs_C1) Cont = 1;
234           else if ( S == GeomAbs_C2) Cont = 2;
235           else if ( S == GeomAbs_C3) Cont = 3;
236           else                       Cont = myBspl->Degree();
237           Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
238           Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
239           Standard_Integer Degree = myBspl->Degree();
240           Standard_Integer NbKnots = myBspl->NbKnots();
241           TColStd_Array1OfInteger Mults (1, NbKnots);
242           myBspl->Multiplicities (Mults);
243           NbSplit = 1;
244           Standard_Integer Index   = FirstIndex;
245           Inter (NbSplit) = Index;
246           Index++;
247           NbSplit++;
248           while (Index < LastIndex) 
249             {
250               if (Degree - Mults (Index) < Cont) 
251                 {
252                   Inter (NbSplit) = Index;
253                   NbSplit++;
254                 }
255               Index++;
256             }
257           Inter (NbSplit) = Index;
258
259           Standard_Integer NbInt = NbSplit-1;
260           
261           Standard_Integer Nb = myBspl->NbKnots();
262           Standard_Integer Index1 = 0;
263           Standard_Integer Index2 = 0;
264           Standard_Real newFirst, newLast;
265           TColStd_Array1OfReal    TK(1,Nb);
266           TColStd_Array1OfInteger TM(1,Nb);
267           myBspl->Knots(TK);
268           myBspl->Multiplicities(TM);
269           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
270                                     myBspl->IsPeriodic(),
271                                     1,Nb,Index1,newFirst);
272           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
273                                     myBspl->IsPeriodic(),
274                                     1,Nb,Index2,newLast);
275
276           // On decale eventuellement les indices  
277           // On utilise une "petite" tolerance, la resolution ne doit 
278           // servir que pour les tres longue courbes....(PRO9248)
279           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
280                                   Precision::PConfusion()); 
281           if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
282           if ( newLast-TK(Index2)> Eps) Index2++;
283           
284           myNbIntervals = 1;
285           for ( Standard_Integer i=1; i<=NbInt; i++)
286             if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
287         }
288         break;
289       }
290     }
291   }
292   
293   else if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))){
294     GeomAbs_Shape BaseS=GeomAbs_C0;
295     switch(S){
296     case GeomAbs_G1:
297     case GeomAbs_G2:
298       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
299       break;
300     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
301     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
302     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
303     default: BaseS = GeomAbs_CN;
304     }
305     GeomAdaptor_Curve C
306       ((*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve());
307     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
308     //                    the number of intervals obtained from the basis to
309     //              vvv   reflect parameter bounds
310     Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
311     if (iNbBasisInt>1)
312     {
313       TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
314       C.Intervals(rdfInter,BaseS);
315       for (iInt=1; iInt<=iNbBasisInt; iInt++)
316         if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
317           myNbIntervals++;
318     }
319     // akm 05/04/02 ^^^
320   }
321   return myNbIntervals;
322 }
323
324 //=======================================================================
325 //function : Intervals
326 //purpose  : 
327 //=======================================================================
328
329 void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
330                                   const GeomAbs_Shape S   )  
331 {
332   Standard_Integer myNbIntervals = 1;
333   Standard_Integer NbSplit;
334
335   if (myTypeCurve == GeomAbs_BSplineCurve) 
336     {
337       Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
338       Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
339       TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
340       
341       if ( S > Continuity()) {
342         Standard_Integer Cont;
343         switch ( S) {
344         case GeomAbs_G1:
345         case GeomAbs_G2:
346           Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
347           break;
348         case GeomAbs_C0:
349           myNbIntervals = 1;
350           break;
351         case GeomAbs_C1:
352         case GeomAbs_C2:
353         case GeomAbs_C3: 
354         case GeomAbs_CN: 
355           {
356             if      ( S == GeomAbs_C1) Cont = 1;
357             else if ( S == GeomAbs_C2) Cont = 2;
358             else if ( S == GeomAbs_C3) Cont = 3;
359             else                       Cont = myBspl->Degree();
360             Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
361             Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
362             Standard_Integer Degree = myBspl->Degree();
363             Standard_Integer NbKnots = myBspl->NbKnots();
364             TColStd_Array1OfInteger Mults (1, NbKnots);
365             myBspl->Multiplicities (Mults);
366             NbSplit = 1;
367             Standard_Integer Index   = FirstIndex;
368             Inter (NbSplit) = Index;
369             Index++;
370             NbSplit++;
371             while (Index < LastIndex) 
372               {
373                 if (Degree - Mults (Index) < Cont) 
374                   {
375                     Inter (NbSplit) = Index;
376                     NbSplit++;
377                   }
378                 Index++;
379               }
380             Inter (NbSplit) = Index;
381             Standard_Integer NbInt = NbSplit-1;
382             //        GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
383             //        Standard_Integer NbInt = Convector.NbSplits()-1;
384             //        TColStd_Array1OfInteger Inter(1,NbInt+1);
385             //        Convector.Splitting( Inter);
386             
387             Standard_Integer Nb = myBspl->NbKnots();
388             Standard_Integer Index1 = 0;
389             Standard_Integer Index2 = 0;
390             Standard_Real newFirst, newLast;
391             TColStd_Array1OfReal    TK(1,Nb);
392             TColStd_Array1OfInteger TM(1,Nb);
393             myBspl->Knots(TK);
394             myBspl->Multiplicities(TM);
395             BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
396                                       myBspl->IsPeriodic(),
397                                       1,Nb,Index1,newFirst);
398             BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
399                                       myBspl->IsPeriodic(),
400                                       1,Nb,Index2,newLast);
401             // On decale eventuellement les indices  
402             // On utilise une "petite" tolerance, la resolution ne doit 
403             // servir que pour les tres longue courbes....(PRO9248)
404             Standard_Real Eps = Min(Resolution(Precision::Confusion()),
405                                     Precision::PConfusion()); 
406             if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
407             if ( newLast-TK(Index2)> Eps) Index2++;
408             
409             Inter( 1) = Index1;
410             myNbIntervals = 1;
411             for ( Standard_Integer i=1; i<=NbInt; i++) {
412               if (Inter(i) > Index1 && Inter(i)<Index2 ) {
413                 myNbIntervals++;
414                 Inter(myNbIntervals) = Inter(i);
415               }
416             }
417             Inter(myNbIntervals+1) = Index2;
418             
419             for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
420               T(I) = TK(Inter(I));
421             }
422           }
423           break;
424         }
425       }
426     }
427
428   else if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))){
429     GeomAbs_Shape BaseS=GeomAbs_C0;
430     switch(S){
431     case GeomAbs_G1:
432     case GeomAbs_G2:
433       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
434       break;
435     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
436     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
437     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
438     default: BaseS = GeomAbs_CN;
439     }
440     GeomAdaptor_Curve C
441       ((*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve());
442     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
443     //                    the array of intervals obtained from the basis to
444     //              vvv   reflect parameter bounds
445     Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
446     if (iNbBasisInt>1)
447     {
448       TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
449       C.Intervals(rdfInter,BaseS);
450       for (iInt=1; iInt<=iNbBasisInt; iInt++)
451         if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
452           T(++myNbIntervals)=rdfInter(iInt);
453     }
454     // old - myNbIntervals = C.NbIntervals(BaseS);
455     // old - C.Intervals(T, BaseS);
456     // akm 05/04/02 ^^^
457   }
458   
459   T( T.Lower() ) = myFirst;
460   T( T.Lower() + myNbIntervals ) = myLast;
461 }
462
463 //=======================================================================
464 //function : Trim
465 //purpose  : 
466 //=======================================================================
467
468 Handle(Adaptor3d_HCurve) GeomAdaptor_Curve::Trim(const Standard_Real First,
469                                                  const Standard_Real Last,
470                                                  const Standard_Real /*Tol*/) const
471 {
472   return Handle(GeomAdaptor_HCurve)(new GeomAdaptor_HCurve(myCurve,First,Last));
473 }
474
475
476 //=======================================================================
477 //function : IsClosed
478 //purpose  : 
479 //=======================================================================
480
481 Standard_Boolean GeomAdaptor_Curve::IsClosed() const
482 {
483   if (!Precision::IsPositiveInfinite(myLast) &&
484       !Precision::IsNegativeInfinite(myFirst))
485   {
486     const gp_Pnt Pd = Value(myFirst);
487     const gp_Pnt Pf = Value(myLast);
488     return (Pd.Distance(Pf) <= Precision::Confusion());
489   }
490   return Standard_False;
491 }
492
493 //=======================================================================
494 //function : IsPeriodic
495 //purpose  : 
496 //=======================================================================
497
498 Standard_Boolean GeomAdaptor_Curve::IsPeriodic() const 
499 {
500   return (myCurve->IsPeriodic()? IsClosed() : Standard_False);
501 }
502
503 //=======================================================================
504 //function : Period
505 //purpose  : 
506 //=======================================================================
507
508 Standard_Real GeomAdaptor_Curve::Period() const 
509 {
510   return myCurve->LastParameter() - myCurve->FirstParameter();
511 }
512
513 //=======================================================================
514 //function : Value
515 //purpose  : 
516 //=======================================================================
517
518 gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
519 {
520   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
521       (U==myFirst || U==myLast) ) {
522     Standard_Integer Ideb, Ifin;
523     if (U==myFirst) {
524       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
525       if (Ideb<1) Ideb=1;
526       if (Ideb>=Ifin) Ifin = Ideb+1;
527     }
528     if (U==myLast) {
529       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
530       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
531       if (Ideb>=Ifin) Ideb = Ifin-1;
532     }
533     return myBspl->LocalValue(U, Ideb, Ifin);
534   }
535   return myCurve->Value(U);
536 }
537
538 //=======================================================================
539 //function : D0
540 //purpose  : 
541 //=======================================================================
542
543 void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
544 {
545   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
546       (U==myFirst || U==myLast) ) {
547     Standard_Integer Ideb, Ifin;
548     if (U==myFirst) {
549       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
550       if (Ideb<1) Ideb=1;
551       if (Ideb>=Ifin) Ifin = Ideb+1;
552     }
553     if (U==myLast) {
554       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
555       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
556       if (Ideb>=Ifin) Ideb = Ifin-1;
557     }
558     myBspl->LocalD0( U, Ideb, Ifin, P);
559   }
560   else {
561     myCurve->D0(U, P);
562   } 
563 }
564
565 //=======================================================================
566 //function : D1
567 //purpose  : 
568 //=======================================================================
569
570 void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const 
571 {
572   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
573       (U==myFirst || U==myLast) ) {
574     Standard_Integer Ideb, Ifin;
575     if (U==myFirst) {
576       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
577       if (Ideb<1) Ideb=1;
578       if (Ideb>=Ifin) Ifin = Ideb+1;
579     }
580     if (U==myLast) {
581       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
582       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
583       if (Ideb>=Ifin) Ideb = Ifin-1;
584     }
585     myBspl->LocalD1( U, Ideb, Ifin, P, V); 
586   } 
587   else {
588     myCurve->D1( U, P, V);
589   }
590 }
591
592 //=======================================================================
593 //function : D2
594 //purpose  : 
595 //=======================================================================
596
597 void GeomAdaptor_Curve::D2(const Standard_Real U, 
598                            gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const 
599 {
600   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
601       (U==myFirst || U==myLast) ) {
602     Standard_Integer Ideb, Ifin;
603     if (U==myFirst) {
604       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
605       if (Ideb<1) Ideb=1;
606       if (Ideb>=Ifin) Ifin = Ideb+1;
607     }
608     if (U==myLast) {
609       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
610       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
611       if (Ideb>=Ifin) Ideb = Ifin-1;
612     }
613     myBspl->LocalD2( U, Ideb, Ifin, P, V1, V2);         
614   }
615   else {
616     myCurve->D2( U, P, V1, V2);
617   }
618 }
619
620 //=======================================================================
621 //function : D3
622 //purpose  : 
623 //=======================================================================
624
625 void GeomAdaptor_Curve::D3(const Standard_Real U, 
626                            gp_Pnt& P, gp_Vec& V1, 
627                            gp_Vec& V2, gp_Vec& V3) const 
628 {
629   if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
630       (U==myFirst || U==myLast) ) {
631     Standard_Integer Ideb, Ifin;
632     if (U==myFirst) {
633       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
634       if (Ideb<1) Ideb=1;
635       if (Ideb>=Ifin) Ifin = Ideb+1;
636     }
637     if (U==myLast) {
638       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
639       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
640       if (Ideb>=Ifin) Ideb = Ifin-1;
641     }
642     myBspl->LocalD3( U, Ideb, Ifin, P, V1, V2, V3);  
643   }
644   else {
645     myCurve->D3( U, P, V1, V2, V3);
646   }
647 }
648
649 //=======================================================================
650 //function : DN
651 //purpose  : 
652 //=======================================================================
653
654 gp_Vec GeomAdaptor_Curve::DN(const Standard_Real    U, 
655                              const Standard_Integer N) const 
656 {
657   if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
658       (U==myFirst || U==myLast) ) {
659     Standard_Integer Ideb, Ifin;
660     if (U==myFirst) {
661       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
662       if (Ideb<1) Ideb=1;
663       if (Ideb>=Ifin) Ifin = Ideb+1;
664     }
665     if (U==myLast) {
666       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
667       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
668       if (Ideb>=Ifin) Ideb = Ifin-1;
669     } 
670     return myBspl->LocalDN( U, Ideb, Ifin, N);
671   }  
672   else {
673     return myCurve->DN( U, N);
674   }
675 }
676
677 //=======================================================================
678 //function : Resolution
679 //purpose  : 
680 //=======================================================================
681
682 Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
683 {
684   switch ( myTypeCurve) {
685   case GeomAbs_Line :
686     return R3D;
687   case GeomAbs_Circle: {
688     Standard_Real R = (*((Handle(Geom_Circle)*)&myCurve))->Circ().Radius();
689     if ( R > R3D/2. )
690       return 2*ASin(R3D/(2*R));
691     else
692       return 2*M_PI;
693   }
694   case GeomAbs_Ellipse: {
695     return R3D / (*((Handle(Geom_Ellipse)*)&myCurve))->MajorRadius();
696   }
697   case GeomAbs_BezierCurve: {
698     Standard_Real res;
699     (*((Handle(Geom_BezierCurve)*)&myCurve))->Resolution(R3D,res);
700     return res;
701   }
702   case GeomAbs_BSplineCurve: {
703     Standard_Real res;
704     (*((Handle(Geom_BSplineCurve)*)&myCurve))->Resolution(R3D,res);
705     return res;
706   }
707   default:
708     return Precision::Parametric(R3D);
709   }  
710 }
711
712
713 //    --
714 //    --     The following methods must  be called when GetType returned
715 //    --     the corresponding type.
716 //    --     
717
718 //=======================================================================
719 //function : Line
720 //purpose  : 
721 //=======================================================================
722
723 gp_Lin GeomAdaptor_Curve::Line() const 
724 {
725   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
726   return (*((Handle(Geom_Line)*)&myCurve))->Lin();  
727 }
728
729 //=======================================================================
730 //function : Circle
731 //purpose  : 
732 //=======================================================================
733
734 gp_Circ  GeomAdaptor_Curve::Circle() const 
735 {
736   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
737   return (*((Handle(Geom_Circle)*)&myCurve))->Circ();
738 }
739
740 //=======================================================================
741 //function : Ellipse
742 //purpose  : 
743 //=======================================================================
744
745 gp_Elips GeomAdaptor_Curve::Ellipse() const 
746 {
747   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
748   return (*((Handle(Geom_Ellipse)*)&myCurve))->Elips();
749 }
750
751 //=======================================================================
752 //function : Hyperbola
753 //purpose  : 
754 //=======================================================================
755
756 gp_Hypr GeomAdaptor_Curve::Hyperbola() const 
757 {
758   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
759   return (*((Handle(Geom_Hyperbola)*)&myCurve))->Hypr();  
760 }
761
762 //=======================================================================
763 //function : Parabola
764 //purpose  : 
765 //=======================================================================
766
767 gp_Parab GeomAdaptor_Curve::Parabola() const 
768 {
769   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
770   return (*((Handle(Geom_Parabola)*)&myCurve))->Parab();
771 }
772
773 //=======================================================================
774 //function : Degree
775 //purpose  : 
776 //=======================================================================
777
778 Standard_Integer GeomAdaptor_Curve::Degree() const
779 {
780   if (myTypeCurve == GeomAbs_BezierCurve)
781     return (*((Handle(Geom_BezierCurve)*)&myCurve))->Degree();
782   else if (myTypeCurve == GeomAbs_BSplineCurve)
783     return (*((Handle(Geom_BSplineCurve)*)&myCurve))->Degree();
784   else
785     Standard_NoSuchObject::Raise();
786   // portage WNT 
787   return 0;
788 }
789
790 //=======================================================================
791 //function : IsRational
792 //purpose  : 
793 //=======================================================================
794
795 Standard_Boolean GeomAdaptor_Curve::IsRational() const {
796   switch( myTypeCurve) {
797   case GeomAbs_BSplineCurve:
798     return (*((Handle(Geom_BSplineCurve)*)&myCurve))->IsRational();
799   case GeomAbs_BezierCurve:
800     return (*((Handle(Geom_BezierCurve)*)&myCurve))->IsRational();
801   default:
802     return Standard_False;
803   }
804 }
805
806 //=======================================================================
807 //function : NbPoles
808 //purpose  : 
809 //=======================================================================
810
811 Standard_Integer GeomAdaptor_Curve::NbPoles() const
812 {
813   if (myTypeCurve == GeomAbs_BezierCurve)
814     return (*((Handle(Geom_BezierCurve)*)&myCurve))->NbPoles();
815   else if (myTypeCurve == GeomAbs_BSplineCurve)
816     return (*((Handle(Geom_BSplineCurve)*)&myCurve))->NbPoles();
817   else
818     Standard_NoSuchObject::Raise();
819   // portage WNT
820   return 0;
821 }
822
823 //=======================================================================
824 //function : NbKnots
825 //purpose  : 
826 //=======================================================================
827
828 Standard_Integer GeomAdaptor_Curve::NbKnots() const
829 {
830   if ( myTypeCurve != GeomAbs_BSplineCurve)
831     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::NbKnots");
832   return (*((Handle(Geom_BSplineCurve)*)&myCurve))->NbKnots();
833 }
834
835 //=======================================================================
836 //function : Bezier
837 //purpose  : 
838 //=======================================================================
839
840 Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const 
841 {
842  if ( myTypeCurve != GeomAbs_BezierCurve)
843     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Bezier");
844   return *((Handle(Geom_BezierCurve)*)&myCurve);
845 }
846
847 //=======================================================================
848 //function : BSpline
849 //purpose  : 
850 //=======================================================================
851
852 Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const 
853 {
854  if ( myTypeCurve != GeomAbs_BSplineCurve)
855     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::BSpline");
856
857   return *((Handle(Geom_BSplineCurve)*)&myCurve);
858 }
859