0025124: [Feature request] Removal of continuity checks for offset geometries
[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-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 // 20/02/97 : PMN -> Positionement local sur BSpline (PRO6902)
18 // 10/07/97 : PMN -> Pas de calcul de resolution dans Nb(Intervals)(PRO9248)
19 // 20/10/97 : RBV -> traitement des offset curves
20
21 #define No_Standard_RangeError
22 #define No_Standard_OutOfRange
23
24 #include <GeomAdaptor_Curve.ixx>
25
26 #include <GeomAdaptor_HCurve.hxx>
27 #include <Adaptor3d_HCurve.hxx>
28 #include <BSplCLib.hxx>
29 #include <GeomAbs_Shape.hxx>
30 #include <TColgp_Array1OfPnt.hxx>
31 #include <TColStd_Array1OfReal.hxx>
32 #include <TColStd_Array1OfInteger.hxx>
33 #include <TColStd_HArray1OfInteger.hxx>
34 #include <Precision.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <Geom_Circle.hxx>
37 #include <Geom_Line.hxx>
38 #include <Geom_TrimmedCurve.hxx>
39 #include <Geom_BezierCurve.hxx>
40 #include <Geom_BSplineCurve.hxx>
41 #include <Geom_Ellipse.hxx>
42 #include <Geom_Parabola.hxx>
43 #include <Geom_Hyperbola.hxx>
44 //#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
45
46 #include <Standard_OutOfRange.hxx>
47 #include <Standard_NoSuchObject.hxx>
48 #include <Standard_NullObject.hxx>
49 #include <Standard_NotImplemented.hxx>
50 #include <Geom_OffsetCurve.hxx>
51
52 #define myBspl (*((Handle(Geom_BSplineCurve)*)&myCurve))
53 #define PosTol Precision::PConfusion()/2
54
55 //=======================================================================
56 //function : LocalContinuity
57 //purpose  : Computes the Continuity of a BSplineCurve 
58 //           between the parameters U1 and U2
59 //           The continuity is C(d-m) 
60 //             with   d = degree, 
61 //                    m = max multiplicity of the Knots between U1 and U2
62 //=======================================================================
63
64 GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1, 
65                                                  const Standard_Real U2) 
66      const 
67 {
68   Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
69   Standard_Integer Nb = myBspl->NbKnots();
70   Standard_Integer Index1 = 0;
71   Standard_Integer Index2 = 0;
72   Standard_Real newFirst, newLast;
73   TColStd_Array1OfReal    TK(1,Nb);
74   TColStd_Array1OfInteger TM(1,Nb);
75   myBspl->Knots(TK);
76   myBspl->Multiplicities(TM);
77   BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U1,myBspl->IsPeriodic(),
78                             1,Nb,Index1,newFirst);
79   BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U2,myBspl->IsPeriodic(),
80                             1,Nb,Index2,newLast);
81   if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) { 
82     if (Index1 < Nb) Index1++;
83   }
84   if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
85     Index2--;
86   Standard_Integer MultMax;
87   // attention aux courbes peridiques.
88   if ( (myBspl->IsPeriodic()) && (Index1 == Nb) )
89     Index1 = 1;
90
91   if ( Index2 - Index1 <= 0) {
92     MultMax = 100;  // CN entre 2 Noeuds consecutifs
93   }
94   else {
95     MultMax = TM(Index1+1);
96     for(Standard_Integer i = Index1+1;i<=Index2;i++) {
97       if ( TM(i)>MultMax) MultMax=TM(i);
98     }
99     MultMax = myBspl->Degree() - MultMax;
100   }
101   if ( MultMax <= 0) {
102     return GeomAbs_C0;
103   }
104   else if ( MultMax == 1) {
105     return GeomAbs_C1;
106   } 
107   else if ( MultMax == 2) {
108     return GeomAbs_C2;
109   }
110   else if ( MultMax == 3) {
111     return GeomAbs_C3;
112   }
113   else { 
114     return GeomAbs_CN;
115   }
116 }
117
118
119 //=======================================================================
120 //function : Load
121 //purpose  : 
122 //=======================================================================
123
124 void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
125                              const Standard_Real UFirst,
126                              const Standard_Real ULast)
127 {
128   myFirst = UFirst;
129   myLast  = ULast;
130
131   if ( myCurve != C) {
132     myCurve = C;
133     
134     const Handle(Standard_Type)& TheType = C->DynamicType();
135     if ( TheType == STANDARD_TYPE(Geom_TrimmedCurve)) {
136       Load((*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve(),UFirst,ULast);
137     }
138     else if ( TheType ==  STANDARD_TYPE(Geom_Circle)) {
139       myTypeCurve = GeomAbs_Circle;
140     }
141     else if ( TheType ==STANDARD_TYPE(Geom_Line)) {
142       myTypeCurve = GeomAbs_Line;
143     }
144     else if ( TheType == STANDARD_TYPE(Geom_Ellipse)) {
145       myTypeCurve = GeomAbs_Ellipse;
146     }
147     else if ( TheType == STANDARD_TYPE(Geom_Parabola)) {
148       myTypeCurve = GeomAbs_Parabola;
149     }
150     else if ( TheType == STANDARD_TYPE(Geom_Hyperbola)) {
151       myTypeCurve = GeomAbs_Hyperbola;
152     }
153     else if ( TheType == STANDARD_TYPE(Geom_BezierCurve)) {
154       myTypeCurve = GeomAbs_BezierCurve;
155     }
156     else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
157       myTypeCurve = GeomAbs_BSplineCurve;
158     }
159     else {
160       myTypeCurve = GeomAbs_OtherCurve;
161     }
162   }
163 }  
164
165 //    --
166 //    --     Global methods - Apply to the whole curve.
167 //    --     
168
169 //=======================================================================
170 //function : Continuity
171 //purpose  : 
172 //=======================================================================
173
174 GeomAbs_Shape GeomAdaptor_Curve::Continuity() const 
175 {
176   if (myTypeCurve == GeomAbs_BSplineCurve)
177     return LocalContinuity(myFirst, myLast);
178
179   if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
180   {
181     const GeomAbs_Shape S =
182       (*((Handle(Geom_OffsetCurve)*)&myCurve))->GetBasisCurveContinuity();
183     switch(S)
184     {
185       case GeomAbs_CN: return GeomAbs_CN;
186       case GeomAbs_C3: return GeomAbs_C2;
187       case GeomAbs_C2: return GeomAbs_C1;
188       case GeomAbs_C1: return GeomAbs_C0; 
189       case GeomAbs_G1: return GeomAbs_G1;
190       case GeomAbs_G2: return GeomAbs_G2;
191       default:
192         Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Continuity");
193     }
194   }
195   else if (myTypeCurve == GeomAbs_OtherCurve) {
196     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Contunuity");
197   }
198
199   return GeomAbs_CN;
200 }
201
202 //=======================================================================
203 //function : NbIntervals
204 //purpose  : 
205 //=======================================================================
206
207 Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) 
208 {
209   Standard_Integer myNbIntervals = 1;
210   Standard_Integer NbSplit;
211   if (myTypeCurve == GeomAbs_BSplineCurve) {
212     Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
213     Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
214     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
215     if ( S > Continuity()) {
216       Standard_Integer Cont;
217       switch ( S) {
218       case GeomAbs_G1:
219       case GeomAbs_G2:
220         Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
221         break;
222       case GeomAbs_C0:
223         myNbIntervals = 1;
224         break;
225       case GeomAbs_C1:
226       case GeomAbs_C2:
227       case GeomAbs_C3: 
228       case GeomAbs_CN: 
229         {
230           if      ( S == GeomAbs_C1) Cont = 1;
231           else if ( S == GeomAbs_C2) Cont = 2;
232           else if ( S == GeomAbs_C3) Cont = 3;
233           else                       Cont = myBspl->Degree();
234           Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
235           Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
236           Standard_Integer Degree = myBspl->Degree();
237           Standard_Integer NbKnots = myBspl->NbKnots();
238           TColStd_Array1OfInteger Mults (1, NbKnots);
239           myBspl->Multiplicities (Mults);
240           NbSplit = 1;
241           Standard_Integer Index   = FirstIndex;
242           Inter (NbSplit) = Index;
243           Index++;
244           NbSplit++;
245           while (Index < LastIndex) 
246             {
247               if (Degree - Mults (Index) < Cont) 
248                 {
249                   Inter (NbSplit) = Index;
250                   NbSplit++;
251                 }
252               Index++;
253             }
254           Inter (NbSplit) = Index;
255
256           Standard_Integer NbInt = NbSplit-1;
257           
258           Standard_Integer Nb = myBspl->NbKnots();
259           Standard_Integer Index1 = 0;
260           Standard_Integer Index2 = 0;
261           Standard_Real newFirst, newLast;
262           TColStd_Array1OfReal    TK(1,Nb);
263           TColStd_Array1OfInteger TM(1,Nb);
264           myBspl->Knots(TK);
265           myBspl->Multiplicities(TM);
266           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
267                                     myBspl->IsPeriodic(),
268                                     1,Nb,Index1,newFirst);
269           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
270                                     myBspl->IsPeriodic(),
271                                     1,Nb,Index2,newLast);
272
273           // On decale eventuellement les indices  
274           // On utilise une "petite" tolerance, la resolution ne doit 
275           // servir que pour les tres longue courbes....(PRO9248)
276           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
277                                   Precision::PConfusion()); 
278           if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
279           if ( newLast-TK(Index2)> Eps) Index2++;
280           
281           myNbIntervals = 1;
282           for ( Standard_Integer i=1; i<=NbInt; i++)
283             if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
284         }
285         break;
286       }
287     }
288   }
289   
290   else if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))){
291     GeomAbs_Shape BaseS=GeomAbs_C0;
292     switch(S){
293     case GeomAbs_G1:
294     case GeomAbs_G2:
295       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
296       break;
297     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
298     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
299     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
300     default: BaseS = GeomAbs_CN;
301     }
302     GeomAdaptor_Curve C
303       ((*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve());
304     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
305     //                    the number of intervals obtained from the basis to
306     //              vvv   reflect parameter bounds
307     Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
308     if (iNbBasisInt>1)
309     {
310       TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
311       C.Intervals(rdfInter,BaseS);
312       for (iInt=1; iInt<=iNbBasisInt; iInt++)
313         if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
314           myNbIntervals++;
315     }
316     // akm 05/04/02 ^^^
317   }
318   return myNbIntervals;
319 }
320
321 //=======================================================================
322 //function : Intervals
323 //purpose  : 
324 //=======================================================================
325
326 void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
327                                   const GeomAbs_Shape S   )  
328 {
329   Standard_Integer myNbIntervals = 1;
330   Standard_Integer NbSplit;
331   Standard_Real FirstParam = myFirst, LastParam = myLast;
332
333   if (myTypeCurve == GeomAbs_BSplineCurve) 
334     {
335       Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
336       Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
337       TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
338       
339       if ( S > Continuity()) {
340         Standard_Integer Cont;
341         switch ( S) {
342         case GeomAbs_G1:
343         case GeomAbs_G2:
344           Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
345           break;
346         case GeomAbs_C0:
347           myNbIntervals = 1;
348           break;
349         case GeomAbs_C1:
350         case GeomAbs_C2:
351         case GeomAbs_C3: 
352         case GeomAbs_CN: 
353           {
354             if      ( S == GeomAbs_C1) Cont = 1;
355             else if ( S == GeomAbs_C2) Cont = 2;
356             else if ( S == GeomAbs_C3) Cont = 3;
357             else                       Cont = myBspl->Degree();
358             Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
359             Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
360             Standard_Integer Degree = myBspl->Degree();
361             Standard_Integer NbKnots = myBspl->NbKnots();
362             TColStd_Array1OfInteger Mults (1, NbKnots);
363             myBspl->Multiplicities (Mults);
364             NbSplit = 1;
365             Standard_Integer Index   = FirstIndex;
366             Inter (NbSplit) = Index;
367             Index++;
368             NbSplit++;
369             while (Index < LastIndex) 
370               {
371                 if (Degree - Mults (Index) < Cont) 
372                   {
373                     Inter (NbSplit) = Index;
374                     NbSplit++;
375                   }
376                 Index++;
377               }
378             Inter (NbSplit) = Index;
379             Standard_Integer NbInt = NbSplit-1;
380             //        GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
381             //        Standard_Integer NbInt = Convector.NbSplits()-1;
382             //        TColStd_Array1OfInteger Inter(1,NbInt+1);
383             //        Convector.Splitting( Inter);
384             
385             Standard_Integer Nb = myBspl->NbKnots();
386             Standard_Integer Index1 = 0;
387             Standard_Integer Index2 = 0;
388             Standard_Real newFirst, newLast;
389             TColStd_Array1OfReal    TK(1,Nb);
390             TColStd_Array1OfInteger TM(1,Nb);
391             myBspl->Knots(TK);
392             myBspl->Multiplicities(TM);
393             BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
394                                       myBspl->IsPeriodic(),
395                                       1,Nb,Index1,newFirst);
396             BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
397                                       myBspl->IsPeriodic(),
398                                       1,Nb,Index2,newLast);
399             FirstParam = newFirst;
400             LastParam = 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() ) = FirstParam;
460   T( T.Lower() + myNbIntervals ) = LastParam;
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 = 0, Ifin = 0;
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 = 0, Ifin = 0;
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 = 0, Ifin = 0;
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 = 0, Ifin = 0;
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 = 0, Ifin = 0;
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 = 0, Ifin = 0;
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