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