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