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