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