0024800: Point of intersection was not found for 2d offset curve.
[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))->BasisCurve()->Continuity(); 
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     default:
224       Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::Continuity");
225     }
226   }
227
228   else if (myTypeCurve == GeomAbs_OtherCurve) {
229     Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::Continuity");
230   }
231   else {
232     return GeomAbs_CN;
233   }
234
235   // portage WNT
236   return GeomAbs_CN;
237 }
238
239 //=======================================================================
240 //function : NbIntervals
241 //purpose  : 
242 //=======================================================================
243
244 Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
245 {
246   Standard_Integer myNbIntervals = 1;
247   Standard_Integer NbSplit;
248   if (myTypeCurve == GeomAbs_BSplineCurve) {
249     Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
250     Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
251     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
252     if ( S > Continuity()) {
253       Standard_Integer Cont;
254       switch ( S) {
255       case GeomAbs_G1:
256       case GeomAbs_G2:
257         Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
258         break;
259       case GeomAbs_C0:
260         myNbIntervals = 1;
261         break;
262       case GeomAbs_C1:
263       case GeomAbs_C2:
264       case GeomAbs_C3: 
265       case GeomAbs_CN: 
266         {
267           if      ( S == GeomAbs_C1) Cont = 1;
268           else if ( S == GeomAbs_C2) Cont = 2;
269           else if ( S == GeomAbs_C3) Cont = 3;
270           else                       Cont = myBspl->Degree();
271           Standard_Integer Degree = myBspl->Degree();
272           Standard_Integer NbKnots = myBspl->NbKnots();
273           TColStd_Array1OfInteger Mults (1, NbKnots);
274           myBspl->Multiplicities (Mults);
275           NbSplit = 1;
276           Standard_Integer Index   = FirstIndex;
277           Inter (NbSplit) = Index;
278           Index++;
279           NbSplit++;
280           while (Index < LastIndex) 
281             {
282               if (Degree - Mults (Index) < Cont) 
283                 {
284                   Inter (NbSplit) = Index;
285                   NbSplit++;
286                 }
287               Index++;
288             }
289           Inter (NbSplit) = Index;
290
291           Standard_Integer NbInt = NbSplit-1;
292           
293           Standard_Integer Nb = myBspl->NbKnots();
294           Standard_Integer Index1 = 0;
295           Standard_Integer Index2 = 0;
296           Standard_Real newFirst, newLast;
297           TColStd_Array1OfReal    TK(1,Nb);
298           TColStd_Array1OfInteger TM(1,Nb);
299           myBspl->Knots(TK);
300           myBspl->Multiplicities(TM);
301           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
302                                     myBspl->IsPeriodic(),
303                                     1,Nb,Index1,newFirst);
304           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
305                                     myBspl->IsPeriodic(),
306                                     1,Nb,Index2,newLast);
307
308           // On decale eventuellement les indices  
309           // On utilise une "petite" tolerance, la resolution ne doit 
310           // servir que pour les tres longue courbes....(PRO9248)
311           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
312                                   Precision::PConfusion()); 
313           if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
314           if ( newLast-TK(Index2)> Eps) Index2++;
315           
316           myNbIntervals = 1;
317           for ( Standard_Integer i=1; i<=NbInt; i++)
318             if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
319         }
320         break;
321       }
322     }
323   }
324   else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))){
325     GeomAbs_Shape BaseS=GeomAbs_C0;
326     switch(S){
327     case GeomAbs_G1:
328     case GeomAbs_G2:
329       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
330       break;
331     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
332     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
333     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
334     default: BaseS = GeomAbs_CN;
335     }
336     Geom2dAdaptor_Curve C
337       ((*((Handle(Geom2d_OffsetCurve)*)&myCurve))->BasisCurve());
338     myNbIntervals = C.NbIntervals(BaseS);
339   }
340
341   return myNbIntervals;
342 }
343
344 //=======================================================================
345 //function : Intervals
346 //purpose  : 
347 //=======================================================================
348
349 void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
350                                     const GeomAbs_Shape S   ) const 
351 {
352   Standard_Integer myNbIntervals = 1;
353   Standard_Integer NbSplit;
354   if (myTypeCurve == GeomAbs_BSplineCurve) {
355     Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
356     Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
357     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
358     if ( S > Continuity()) {
359       Standard_Integer Cont;
360       switch ( S) {
361       case GeomAbs_G1:
362       case GeomAbs_G2:
363         Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
364         break;
365       case GeomAbs_C0:
366         myNbIntervals = 1;
367         break;
368       case GeomAbs_C1:
369       case GeomAbs_C2:
370       case GeomAbs_C3: 
371       case GeomAbs_CN: 
372         {
373           if      ( S == GeomAbs_C1) Cont = 1;
374           else if ( S == GeomAbs_C2) Cont = 2;
375           else if ( S == GeomAbs_C3) Cont = 3;
376           else                       Cont = myBspl->Degree();
377           Standard_Integer Degree = myBspl->Degree();
378           Standard_Integer NbKnots = myBspl->NbKnots();
379           TColStd_Array1OfInteger Mults (1, NbKnots);
380           myBspl->Multiplicities (Mults);
381           NbSplit = 1;
382           Standard_Integer Index   = FirstIndex;
383           Inter (NbSplit) = Index;
384           Index++;
385           NbSplit++;
386           while (Index < LastIndex) 
387             {
388               if (Degree - Mults (Index) < Cont) 
389                 {
390                   Inter (NbSplit) = Index;
391                   NbSplit++;
392                 }
393               Index++;
394             }
395           Inter (NbSplit) = Index;
396           Standard_Integer NbInt = NbSplit-1;
397           
398           Standard_Integer Nb = myBspl->NbKnots();
399           Standard_Integer Index1 = 0;
400           Standard_Integer Index2 = 0;
401           Standard_Real newFirst, newLast;
402           TColStd_Array1OfReal    TK(1,Nb);
403           TColStd_Array1OfInteger TM(1,Nb);
404           myBspl->Knots(TK);
405           myBspl->Multiplicities(TM);
406           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
407                                     myBspl->IsPeriodic(),
408                                     1,Nb,Index1,newFirst);
409           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
410                                     myBspl->IsPeriodic(),
411                                     1,Nb,Index2,newLast);
412
413
414           // On decale eventuellement les indices  
415           // On utilise une "petite" tolerance, la resolution ne doit 
416           // servir que pour les tres longue courbes....(PRO9248)
417           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
418                                   Precision::PConfusion()); 
419           if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
420           if ( newLast-TK(Index2)> Eps) Index2++;
421           
422           Inter( 1) = Index1;
423           myNbIntervals = 1;
424           for ( Standard_Integer i=1; i<=NbInt; i++) {
425             if (Inter(i) > Index1 && Inter(i)<Index2 ) {
426               myNbIntervals++;
427               Inter(myNbIntervals) = Inter(i);
428             }
429           }
430           Inter(myNbIntervals+1) = Index2;
431           
432           Standard_Integer ii = T.Lower() - 1;
433           for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
434             T(ii + I) = TK(Inter(I));
435           }
436         }
437         break;
438       }
439     }
440   }
441   else if (myCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))){
442     GeomAbs_Shape BaseS=GeomAbs_C0;
443     switch(S){
444     case GeomAbs_G1:
445     case GeomAbs_G2:
446       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
447       break;
448     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
449     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
450     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
451     default: BaseS = GeomAbs_CN;
452     }
453     Geom2dAdaptor_Curve C
454       ((*((Handle(Geom2d_OffsetCurve)*)&myCurve))->BasisCurve());
455     myNbIntervals = C.NbIntervals(BaseS);
456     C.Intervals(T, BaseS);
457   }
458
459   T( T.Lower() ) = myFirst;
460   T( T.Lower() + myNbIntervals ) = myLast;
461 }
462
463 //=======================================================================
464 //function : Trim
465 //purpose  : 
466 //=======================================================================
467
468 Handle(Adaptor2d_HCurve2d) Geom2dAdaptor_Curve::Trim
469 (const Standard_Real First,
470  const Standard_Real Last,
471 // const Standard_Real Tol) const 
472  const Standard_Real ) const 
473 {
474   Handle(Geom2dAdaptor_HCurve) HE = new Geom2dAdaptor_HCurve(myCurve,First,Last);
475   return HE;
476 }
477
478
479 //=======================================================================
480 //function : IsClosed
481 //purpose  : 
482 //=======================================================================
483
484 Standard_Boolean Geom2dAdaptor_Curve::IsClosed() const 
485 {
486   if (!Precision::IsPositiveInfinite(myLast) &&
487       !Precision::IsNegativeInfinite(myFirst)) {
488     gp_Pnt2d Pd = Value(myFirst);
489     gp_Pnt2d Pf = Value(myLast);
490     return ( Pd.Distance(Pf) <= Precision::Confusion());
491   }
492   else
493     return Standard_False;
494 }
495
496 //=======================================================================
497 //function : IsPeriodic
498 //purpose  : 
499 //=======================================================================
500
501 Standard_Boolean Geom2dAdaptor_Curve::IsPeriodic() const 
502 {
503   if (myCurve->IsPeriodic())
504     return IsClosed();
505   else
506     return Standard_False;
507 }
508
509 //=======================================================================
510 //function : Period
511 //purpose  : 
512 //=======================================================================
513
514 Standard_Real Geom2dAdaptor_Curve::Period() const 
515 {
516   return myCurve->LastParameter() - myCurve->FirstParameter();
517 }
518
519 //=======================================================================
520 //function : Value
521 //purpose  : 
522 //=======================================================================
523
524 gp_Pnt2d Geom2dAdaptor_Curve::Value(const Standard_Real U) const 
525 {
526   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
527       (U==myFirst || U==myLast) ) {
528     Standard_Integer Ideb = 0, Ifin = 0;
529     if (U==myFirst) {
530       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
531       if (Ideb<1) Ideb=1;
532       if (Ideb>=Ifin) Ifin = Ideb+1;
533     }
534     if (U==myLast) {
535       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
536       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
537       if (Ideb>=Ifin) Ideb = Ifin-1;
538     }
539     return myBspl->LocalValue(U, Ideb, Ifin);
540   }
541   else {
542     return myCurve->Value( U);
543   }
544 }
545
546 //=======================================================================
547 //function : D0
548 //purpose  : 
549 //=======================================================================
550
551 void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
552 {
553   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
554       (U==myFirst || U==myLast) ) {
555     Standard_Integer Ideb = 0, Ifin = 0;
556     if (U==myFirst) {
557       myBspl->LocateU(myFirst,  PosTol, Ideb, Ifin);
558       if (Ideb<1) Ideb=1;
559       if (Ideb>=Ifin) Ifin = Ideb+1;
560     }
561     if (U==myLast) {
562       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
563       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
564       if (Ideb>=Ifin) Ideb = Ifin-1;
565     }
566     myBspl->LocalD0( U, Ideb, Ifin, P);
567   }
568   else {
569     myCurve->D0(U, P);
570   } 
571 }
572
573 //=======================================================================
574 //function : D1
575 //purpose  : 
576 //=======================================================================
577
578 void Geom2dAdaptor_Curve::D1(const Standard_Real U,
579                              gp_Pnt2d& P, gp_Vec2d& V) const 
580 {
581   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
582       (U==myFirst || U==myLast) ) {
583     Standard_Integer Ideb = 0, Ifin = 0;
584     if (U==myFirst) {
585       myBspl->LocateU(myFirst,  PosTol, Ideb, Ifin);
586       if (Ideb<1) Ideb=1;
587       if (Ideb>=Ifin) Ifin = Ideb+1;
588     }
589     if (U==myLast) {
590       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
591       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
592       if (Ideb>=Ifin) Ideb = Ifin-1;
593     }
594     myBspl->LocalD1( U, Ideb, Ifin, P, V); 
595   } 
596   else {
597     myCurve->D1( U, P, V);
598   }
599 }
600
601 //=======================================================================
602 //function : D2
603 //purpose  : 
604 //=======================================================================
605
606 void Geom2dAdaptor_Curve::D2(const Standard_Real U, 
607                              gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const 
608 {
609   if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
610       (U==myFirst || U==myLast) ) {
611     Standard_Integer Ideb = 0, Ifin = 0;
612     if (U==myFirst) {
613       myBspl->LocateU(myFirst,  PosTol, Ideb, Ifin);
614       if (Ideb<1) Ideb=1;
615       if (Ideb>=Ifin) Ifin = Ideb+1;
616     }
617     if (U==myLast) {
618       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
619       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
620       if (Ideb>=Ifin) Ideb = Ifin-1;
621     }
622     myBspl->LocalD2( U, Ideb, Ifin, P, V1, V2);
623   }
624   else {
625     myCurve->D2( U, P, V1, V2);
626   }
627 }
628
629 //=======================================================================
630 //function : D3
631 //purpose  : 
632 //=======================================================================
633
634 void Geom2dAdaptor_Curve::D3(const Standard_Real U, 
635                              gp_Pnt2d& P,  gp_Vec2d& V1, 
636                              gp_Vec2d& V2, gp_Vec2d& V3) const 
637 {
638   if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
639       (U==myFirst || U==myLast) ) {
640     Standard_Integer Ideb = 0, Ifin = 0;
641     if (U==myFirst) {
642       myBspl->LocateU(myFirst,  PosTol, Ideb, Ifin);
643       if (Ideb<1) Ideb=1;
644       if (Ideb>=Ifin) Ifin = Ideb+1;
645     }
646     if (U==myLast) {
647       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
648       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
649       if (Ideb>=Ifin) Ideb = Ifin-1;
650     }
651     myBspl->LocalD3( U, Ideb, Ifin, P, V1, V2, V3);  
652   }
653   else {
654     myCurve->D3( U, P, V1, V2, V3);
655   }
656 }
657
658 //=======================================================================
659 //function : DN
660 //purpose  : 
661 //=======================================================================
662
663 gp_Vec2d Geom2dAdaptor_Curve::DN(const Standard_Real U, 
664                                  const Standard_Integer N) const 
665 {
666   if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
667       (U==myFirst || U==myLast) ) {
668     Standard_Integer Ideb = 0, Ifin = 0;
669     if (U==myFirst) {
670       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
671       if (Ideb<1) Ideb=1;
672       if (Ideb>=Ifin) Ifin = Ideb+1;
673     }
674     if (U==myLast) {
675       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
676       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
677       if (Ideb>=Ifin) Ideb = Ifin-1;
678     } 
679     return myBspl->LocalDN( U, Ideb, Ifin, N);
680   }  
681   else {
682     return myCurve->DN( U, N);
683   }
684 }
685
686 //=======================================================================
687 //function : Resolution
688 //purpose  : 
689 //=======================================================================
690
691 Standard_Real Geom2dAdaptor_Curve::Resolution(const Standard_Real Ruv) const {
692   switch ( myTypeCurve) {
693   case GeomAbs_Line :
694     return Ruv;
695   case GeomAbs_Circle: {
696     Standard_Real R = (*((Handle(Geom2d_Circle)*)&myCurve))->Circ2d().Radius();
697     if ( R > Ruv/2.)
698       return 2*ASin(Ruv/(2*R));
699     else
700       return 2*M_PI;
701   }
702   case GeomAbs_Ellipse: {
703     return Ruv / (*((Handle(Geom2d_Ellipse)*)&myCurve))->MajorRadius();
704   }
705   case GeomAbs_BezierCurve: {
706     Standard_Real res;
707     (*((Handle(Geom2d_BezierCurve)*)&myCurve))->Resolution(Ruv,res);
708     return res;
709   }
710   case GeomAbs_BSplineCurve: {
711     Standard_Real res;
712     (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->Resolution(Ruv,res);
713     return res;
714   }
715   default:
716     return Precision::Parametric(Ruv);
717   }  
718 }
719
720
721 //    --
722 //    --     The following methods must  be called when GetType returned
723 //    --     the corresponding type.
724 //    --     
725
726 //=======================================================================
727 //function : Line
728 //purpose  : 
729 //=======================================================================
730
731 gp_Lin2d Geom2dAdaptor_Curve::Line() const 
732 {
733   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
734   return (*((Handle(Geom2d_Line)*)&myCurve))->Lin2d();
735 }
736
737 //=======================================================================
738 //function : Circle
739 //purpose  : 
740 //=======================================================================
741
742 gp_Circ2d  Geom2dAdaptor_Curve::Circle() const 
743 {
744   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
745   return (*((Handle(Geom2d_Circle)*)&myCurve))->Circ2d();
746 }
747
748 //=======================================================================
749 //function : Ellipse
750 //purpose  : 
751 //=======================================================================
752
753 gp_Elips2d Geom2dAdaptor_Curve::Ellipse() const 
754 {
755   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
756   return (*((Handle(Geom2d_Ellipse)*)&myCurve))->Elips2d();
757 }
758
759 //=======================================================================
760 //function : Hyperbola
761 //purpose  : 
762 //=======================================================================
763
764 gp_Hypr2d Geom2dAdaptor_Curve::Hyperbola() const 
765 {
766   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
767   return (*((Handle(Geom2d_Hyperbola)*)&myCurve))->Hypr2d();
768 }
769
770 //=======================================================================
771 //function : Parabola
772 //purpose  : 
773 //=======================================================================
774
775 gp_Parab2d Geom2dAdaptor_Curve::Parabola() const 
776 {
777   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
778   return (*((Handle(Geom2d_Parabola)*)&myCurve))->Parab2d();
779 }
780
781 //=======================================================================
782 //function : Degree
783 //purpose  : 
784 //=======================================================================
785
786 Standard_Integer Geom2dAdaptor_Curve::Degree() const
787 {
788   if (myTypeCurve == GeomAbs_BezierCurve)
789     return (*((Handle(Geom2d_BezierCurve)*)&myCurve))->Degree();
790   else if (myTypeCurve == GeomAbs_BSplineCurve)
791     return (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->Degree();
792   else
793     Standard_NoSuchObject::Raise();
794   // portage WNT 
795   return 0;
796 }
797
798 //=======================================================================
799 //function : IsRational
800 //purpose  : 
801 //=======================================================================
802
803 Standard_Boolean Geom2dAdaptor_Curve::IsRational() const {
804   switch( myTypeCurve) {
805   case GeomAbs_BSplineCurve:
806     return (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->IsRational();
807   case GeomAbs_BezierCurve:
808     return (*((Handle(Geom2d_BezierCurve)*)&myCurve))->IsRational();
809   default:
810     return Standard_False;
811   }
812 }
813
814 //=======================================================================
815 //function : NbPoles
816 //purpose  : 
817 //=======================================================================
818
819 Standard_Integer Geom2dAdaptor_Curve::NbPoles() const
820 {
821   if (myTypeCurve == GeomAbs_BezierCurve)
822     return (*((Handle(Geom2d_BezierCurve)*)&myCurve))->NbPoles();
823   else if (myTypeCurve == GeomAbs_BSplineCurve)
824     return (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->NbPoles();
825   else
826     Standard_NoSuchObject::Raise();
827   // portage WNT 
828   return 0;
829 }
830
831 //=======================================================================
832 //function : NbKnots
833 //purpose  : 
834 //=======================================================================
835
836 Standard_Integer Geom2dAdaptor_Curve::NbKnots() const {
837   if ( myTypeCurve != GeomAbs_BSplineCurve)
838     Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::NbKnots");
839   return (*((Handle(Geom2d_BSplineCurve)*)&myCurve))->NbKnots();
840
841 }
842
843 //=======================================================================
844 //function : Bezier
845 //purpose  : 
846 //=======================================================================
847
848 Handle(Geom2d_BezierCurve) Geom2dAdaptor_Curve::Bezier() const 
849 {
850   return *((Handle(Geom2d_BezierCurve)*)&myCurve);
851 }
852
853 //=======================================================================
854 //function : BSpline
855 //purpose  : 
856 //=======================================================================
857
858 Handle(Geom2d_BSplineCurve) Geom2dAdaptor_Curve::BSpline() const 
859 {
860   return *((Handle(Geom2d_BSplineCurve)*)&myCurve);
861 }
862
863 static Standard_Integer nbPoints(const Handle(Geom2d_Curve)& theCurve) 
864 {
865  
866   Standard_Integer nbs = 10;
867   
868   if(theCurve->IsKind(STANDARD_TYPE( Geom2d_Line)) )
869     nbs = 2;
870   else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BezierCurve))) 
871   {
872     nbs = 3 + (*((Handle(Geom2d_BezierCurve)*)&theCurve))->NbPoles();
873   }
874   else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BSplineCurve))) { 
875     nbs =  (*((Handle(Geom2d_BSplineCurve)*)&theCurve))->NbKnots();
876     nbs*= (*((Handle(Geom2d_BSplineCurve)*)&theCurve))->Degree();
877     if(nbs < 2.0) nbs=2;
878   }
879   else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
880   {
881     Handle(Geom2d_Curve) aCurve = (*((Handle(Geom2d_OffsetCurve)*)&theCurve))->BasisCurve();
882     return Max(nbs, nbPoints(aCurve));
883   }
884
885   else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
886   {
887     Handle(Geom2d_Curve) aCurve = (*((Handle(Geom2d_TrimmedCurve)*)&theCurve))->BasisCurve();
888     return Max(nbs, nbPoints(aCurve));
889   }
890   if(nbs>300)
891     nbs = 300;
892   return nbs;
893   
894 }
895
896 Standard_Integer Geom2dAdaptor_Curve::NbSamples() const
897 {
898   return  nbPoints(myCurve);
899 }