0024023: Revamp the OCCT Handle -- downcast (automatic)
[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 <BSplCLib_Cache.hxx>
30 #include <GeomAbs_Shape.hxx>
31 #include <TColgp_Array1OfPnt2d.hxx>
32 #include <TColStd_Array1OfReal.hxx>
33 #include <TColStd_Array1OfInteger.hxx>
34 #include <TColStd_HArray1OfInteger.hxx>
35 #include <Precision.hxx>
36 #include <gp.hxx>
37 #include <Geom2d_TrimmedCurve.hxx>
38 #include <Geom2d_Circle.hxx>
39 #include <Geom2d_Line.hxx>
40 #include <Geom2d_TrimmedCurve.hxx>
41 #include <Geom2d_BezierCurve.hxx>
42 #include <Geom2d_BSplineCurve.hxx>
43 #include <Geom2d_Ellipse.hxx>
44 #include <Geom2d_Parabola.hxx>
45 #include <Geom2d_Hyperbola.hxx>
46 #include <Geom2d_UndefinedValue.hxx>
47 #include <Geom2d_UndefinedDerivative.hxx>
48 #include <CSLib_Offset.hxx>
49 //#include <Geom2dConvert_BSplineCurveKnotSplitting.hxx>
50
51 #include <Standard_OutOfRange.hxx>
52 #include <Standard_NoSuchObject.hxx>
53 #include <Standard_NullObject.hxx>
54 #include <Standard_NotImplemented.hxx>
55
56 #define myBspl Handle(Geom2d_BSplineCurve)::DownCast (myCurve)
57 #define PosTol Precision::PConfusion()/2
58
59 static const int maxDerivOrder = 3;
60 static const Standard_Real MinStep   = 1e-7;
61
62 static gp_Vec2d dummyDerivative; // used as empty value for unused derivatives in AdjustDerivative
63
64 // Recalculate derivatives in the singular point
65 // Returns true is the direction of derivatives is changed
66 static Standard_Boolean AdjustDerivative(const Handle(Adaptor2d_HCurve2d)& theAdaptor, Standard_Integer theMaxDerivative,
67                                          Standard_Real theU, gp_Vec2d& theD1, gp_Vec2d& theD2 = dummyDerivative,
68                                          gp_Vec2d& theD3 = dummyDerivative, gp_Vec2d& theD4 = dummyDerivative);
69
70 //=======================================================================
71 //function : LocalContinuity
72 //purpose  : Computes the Continuity of a BSplineCurve 
73 //           between the parameters U1 and U2
74 //           The continuity is C(d-m) 
75 //             with   d = degree, 
76 //                    m = max multiplicity of the Knots between U1 and U2
77 //=======================================================================
78
79 GeomAbs_Shape Geom2dAdaptor_Curve::LocalContinuity(const Standard_Real U1, 
80                                                    const Standard_Real U2) 
81      const {
82
83        Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
84        Standard_Integer Nb = myBspl->NbKnots();
85        Standard_Integer Index1 = 0;
86        Standard_Integer Index2 = 0;
87        Standard_Real newFirst, newLast;
88        TColStd_Array1OfReal    TK(1,Nb);
89        TColStd_Array1OfInteger TM(1,Nb);
90        myBspl->Knots(TK);
91        myBspl->Multiplicities(TM);
92        BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U1,myBspl->IsPeriodic(),
93                                  1,Nb,Index1,newFirst);
94        BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U2,myBspl->IsPeriodic(),
95                                  1,Nb,Index2,newLast);
96        if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) { 
97          if (Index1 < Nb)Index1++;
98        }
99        if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
100          Index2--;
101        Standard_Integer MultMax;
102        // attention aux courbes peridiques.
103        if ( (myBspl->IsPeriodic()) && (Index1 == Nb) )
104          Index1 = 1;
105
106        if ( Index2 - Index1 <= 0) {
107          MultMax = 100;  // CN entre 2 Noeuds consecutifs
108        }
109        else {
110          MultMax = TM(Index1+1);
111          for(Standard_Integer i = Index1+1;i<=Index2;i++) {
112            if ( TM(i)>MultMax) MultMax=TM(i);
113          }
114          MultMax = myBspl->Degree() - MultMax;
115        }
116        if ( MultMax <= 0) {
117          return GeomAbs_C0;
118        }
119        else if ( MultMax == 1) {
120          return GeomAbs_C1;
121        } 
122        else if ( MultMax == 2) {
123          return GeomAbs_C2;
124        }
125        else if ( MultMax == 3) {
126          return GeomAbs_C3;
127        }
128        else { 
129          return GeomAbs_CN;
130        }
131      }
132
133
134 //=======================================================================
135 //function : Geom2dAdaptor_Curve
136 //purpose  : 
137 //=======================================================================
138
139 Geom2dAdaptor_Curve::Geom2dAdaptor_Curve()
140 : myTypeCurve(GeomAbs_OtherCurve),
141   myFirst    (0.0),
142   myLast     (0.0)
143 {
144 }
145
146 //=======================================================================
147 //function : Geom2dAdaptor_Curve
148 //purpose  : 
149 //=======================================================================
150
151 Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv)
152 : myTypeCurve(GeomAbs_OtherCurve),
153   myFirst    (0.0),
154   myLast     (0.0)
155 {
156   Load(theCrv);
157 }
158
159 //=======================================================================
160 //function : Geom2dAdaptor_Curve
161 //purpose  : 
162 //=======================================================================
163
164 Geom2dAdaptor_Curve::Geom2dAdaptor_Curve(const Handle(Geom2d_Curve)& theCrv,
165                                          const Standard_Real theUFirst,
166                                          const Standard_Real theULast)
167 : myTypeCurve(GeomAbs_OtherCurve),
168   myFirst    (theUFirst),
169   myLast     (theULast)
170 {
171   Load(theCrv, theUFirst, theULast);
172 }
173
174
175 //=======================================================================
176 //function : Load
177 //purpose  : 
178 //=======================================================================
179
180 void Geom2dAdaptor_Curve::load(const Handle(Geom2d_Curve)& C,
181                                                  const Standard_Real UFirst,
182                                                  const Standard_Real ULast) 
183 {
184   myFirst = UFirst;
185   myLast  = ULast;
186
187   if ( myCurve != C) {
188     myCurve = C;
189
190     Handle(Standard_Type) TheType = C->DynamicType();
191     if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
192       Load(Handle(Geom2d_TrimmedCurve)::DownCast (C)->BasisCurve(),
193            UFirst,ULast);
194     }
195     else if ( TheType ==  STANDARD_TYPE(Geom2d_Circle)) {
196       myTypeCurve = GeomAbs_Circle;
197     }
198     else if ( TheType ==STANDARD_TYPE(Geom2d_Line)) {
199       myTypeCurve = GeomAbs_Line;
200     }
201     else if ( TheType == STANDARD_TYPE(Geom2d_Ellipse)) {
202       myTypeCurve = GeomAbs_Ellipse;
203     }
204     else if ( TheType == STANDARD_TYPE(Geom2d_Parabola)) {
205       myTypeCurve = GeomAbs_Parabola;
206     }
207     else if ( TheType == STANDARD_TYPE(Geom2d_Hyperbola)) {
208       myTypeCurve = GeomAbs_Hyperbola;
209     }
210     else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
211       myTypeCurve = GeomAbs_BezierCurve;
212     }
213     else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
214       myTypeCurve = GeomAbs_BSplineCurve;
215       // Create cache for B-spline
216       myCurveCache = new BSplCLib_Cache(myBspl->Degree(), myBspl->IsPeriodic(), 
217         myBspl->KnotSequence(), myBspl->Poles(), myBspl->Weights());
218     }
219     else if ( TheType == STANDARD_TYPE(Geom2d_OffsetCurve))
220     {
221       myTypeCurve = GeomAbs_OtherCurve;
222       // Create nested adaptor for base curve
223       Handle(Geom2d_Curve) aBase = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->BasisCurve();
224       myOffsetBaseCurveAdaptor = new Geom2dAdaptor_HCurve(aBase);
225     }
226     else {
227       myTypeCurve = GeomAbs_OtherCurve;
228     }
229   }
230 }
231
232 //    --
233 //    --     Global methods - Apply to the whole curve.
234 //    --     
235
236 //=======================================================================
237 //function : Continuity
238 //purpose  : 
239 //=======================================================================
240
241 GeomAbs_Shape Geom2dAdaptor_Curve::Continuity() const 
242 {
243   if (myTypeCurve == GeomAbs_BSplineCurve) {
244     return LocalContinuity(myFirst, myLast);
245   }
246   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)){
247     GeomAbs_Shape S = 
248       Handle(Geom2d_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity(); 
249     switch(S){
250     case GeomAbs_CN: return GeomAbs_CN;
251     case GeomAbs_C3: return GeomAbs_C2;
252     case GeomAbs_C2: return GeomAbs_C1;
253     case GeomAbs_C1: return GeomAbs_C0;  
254     case GeomAbs_G1: return GeomAbs_G1;
255     case GeomAbs_G2: return GeomAbs_G2;
256
257     default:
258       Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::Continuity");
259     }
260   }
261
262   else if (myTypeCurve == GeomAbs_OtherCurve) {
263     Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::Continuity");
264   }
265   else {
266     return GeomAbs_CN;
267   }
268
269   // portage WNT
270   return GeomAbs_CN;
271 }
272
273 //=======================================================================
274 //function : NbIntervals
275 //purpose  : 
276 //=======================================================================
277
278 Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
279 {
280   Standard_Integer myNbIntervals = 1;
281   Standard_Integer NbSplit;
282   if (myTypeCurve == GeomAbs_BSplineCurve) {
283     Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
284     Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
285     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
286     if ( S > Continuity()) {
287       Standard_Integer Cont;
288       switch ( S) {
289       case GeomAbs_G1:
290       case GeomAbs_G2:
291         Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
292         break;
293       case GeomAbs_C0:
294         myNbIntervals = 1;
295         break;
296       case GeomAbs_C1:
297       case GeomAbs_C2:
298       case GeomAbs_C3: 
299       case GeomAbs_CN: 
300         {
301           if      ( S == GeomAbs_C1) Cont = 1;
302           else if ( S == GeomAbs_C2) Cont = 2;
303           else if ( S == GeomAbs_C3) Cont = 3;
304           else                       Cont = myBspl->Degree();
305           Standard_Integer Degree = myBspl->Degree();
306           Standard_Integer NbKnots = myBspl->NbKnots();
307           TColStd_Array1OfInteger Mults (1, NbKnots);
308           myBspl->Multiplicities (Mults);
309           NbSplit = 1;
310           Standard_Integer Index   = FirstIndex;
311           Inter (NbSplit) = Index;
312           Index++;
313           NbSplit++;
314           while (Index < LastIndex) 
315             {
316               if (Degree - Mults (Index) < Cont) 
317                 {
318                   Inter (NbSplit) = Index;
319                   NbSplit++;
320                 }
321               Index++;
322             }
323           Inter (NbSplit) = Index;
324
325           Standard_Integer NbInt = NbSplit-1;
326           
327           Standard_Integer Nb = myBspl->NbKnots();
328           Standard_Integer Index1 = 0;
329           Standard_Integer Index2 = 0;
330           Standard_Real newFirst, newLast;
331           TColStd_Array1OfReal    TK(1,Nb);
332           TColStd_Array1OfInteger TM(1,Nb);
333           myBspl->Knots(TK);
334           myBspl->Multiplicities(TM);
335           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
336                                     myBspl->IsPeriodic(),
337                                     1,Nb,Index1,newFirst);
338           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
339                                     myBspl->IsPeriodic(),
340                                     1,Nb,Index2,newLast);
341
342           // On decale eventuellement les indices  
343           // On utilise une "petite" tolerance, la resolution ne doit 
344           // servir que pour les tres longue courbes....(PRO9248)
345           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
346                                   Precision::PConfusion()); 
347           if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
348           if ( newLast-TK(Index2)> Eps) Index2++;
349           
350           myNbIntervals = 1;
351           for ( Standard_Integer i=1; i<=NbInt; i++)
352             if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
353         }
354         break;
355       }
356     }
357   }
358   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)){
359     GeomAbs_Shape BaseS=GeomAbs_C0;
360     switch(S){
361     case GeomAbs_G1:
362     case GeomAbs_G2:
363       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
364       break;
365     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
366     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
367     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
368     default: BaseS = GeomAbs_CN;
369     }
370     myNbIntervals = myOffsetBaseCurveAdaptor->NbIntervals(BaseS);
371   }
372
373   return myNbIntervals;
374 }
375
376 //=======================================================================
377 //function : Intervals
378 //purpose  : 
379 //=======================================================================
380
381 void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
382                                     const GeomAbs_Shape S   ) const 
383 {
384   Standard_Integer myNbIntervals = 1;
385   Standard_Integer NbSplit;
386   if (myTypeCurve == GeomAbs_BSplineCurve) {
387     Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
388     Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
389     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
390     if ( S > Continuity()) {
391       Standard_Integer Cont;
392       switch ( S) {
393       case GeomAbs_G1:
394       case GeomAbs_G2:
395         Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
396         break;
397       case GeomAbs_C0:
398         myNbIntervals = 1;
399         break;
400       case GeomAbs_C1:
401       case GeomAbs_C2:
402       case GeomAbs_C3: 
403       case GeomAbs_CN: 
404         {
405           if      ( S == GeomAbs_C1) Cont = 1;
406           else if ( S == GeomAbs_C2) Cont = 2;
407           else if ( S == GeomAbs_C3) Cont = 3;
408           else                       Cont = myBspl->Degree();
409           Standard_Integer Degree = myBspl->Degree();
410           Standard_Integer NbKnots = myBspl->NbKnots();
411           TColStd_Array1OfInteger Mults (1, NbKnots);
412           myBspl->Multiplicities (Mults);
413           NbSplit = 1;
414           Standard_Integer Index   = FirstIndex;
415           Inter (NbSplit) = Index;
416           Index++;
417           NbSplit++;
418           while (Index < LastIndex) 
419             {
420               if (Degree - Mults (Index) < Cont) 
421                 {
422                   Inter (NbSplit) = Index;
423                   NbSplit++;
424                 }
425               Index++;
426             }
427           Inter (NbSplit) = Index;
428           Standard_Integer NbInt = NbSplit-1;
429           
430           Standard_Integer Nb = myBspl->NbKnots();
431           Standard_Integer Index1 = 0;
432           Standard_Integer Index2 = 0;
433           Standard_Real newFirst, newLast;
434           TColStd_Array1OfReal    TK(1,Nb);
435           TColStd_Array1OfInteger TM(1,Nb);
436           myBspl->Knots(TK);
437           myBspl->Multiplicities(TM);
438           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
439                                     myBspl->IsPeriodic(),
440                                     1,Nb,Index1,newFirst);
441           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
442                                     myBspl->IsPeriodic(),
443                                     1,Nb,Index2,newLast);
444
445
446           // On decale eventuellement les indices  
447           // On utilise une "petite" tolerance, la resolution ne doit 
448           // servir que pour les tres longue courbes....(PRO9248)
449           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
450                                   Precision::PConfusion()); 
451           if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
452           if ( newLast-TK(Index2)> Eps) Index2++;
453           
454           Inter( 1) = Index1;
455           myNbIntervals = 1;
456           for ( Standard_Integer i=1; i<=NbInt; i++) {
457             if (Inter(i) > Index1 && Inter(i)<Index2 ) {
458               myNbIntervals++;
459               Inter(myNbIntervals) = Inter(i);
460             }
461           }
462           Inter(myNbIntervals+1) = Index2;
463           
464           Standard_Integer ii = T.Lower() - 1;
465           for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
466             T(ii + I) = TK(Inter(I));
467           }
468         }
469         break;
470       }
471     }
472   }
473   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve)){
474     GeomAbs_Shape BaseS=GeomAbs_C0;
475     switch(S){
476     case GeomAbs_G1:
477     case GeomAbs_G2:
478       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
479       break;
480     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
481     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
482     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
483     default: BaseS = GeomAbs_CN;
484     }
485     myNbIntervals = myOffsetBaseCurveAdaptor->NbIntervals(BaseS);
486     myOffsetBaseCurveAdaptor->Intervals(T, BaseS);
487   }
488
489   T( T.Lower() ) = myFirst;
490   T( T.Lower() + myNbIntervals ) = myLast;
491 }
492
493 //=======================================================================
494 //function : Trim
495 //purpose  : 
496 //=======================================================================
497
498 Handle(Adaptor2d_HCurve2d) Geom2dAdaptor_Curve::Trim
499 (const Standard_Real First,
500  const Standard_Real Last,
501 // const Standard_Real Tol) const 
502  const Standard_Real ) const 
503 {
504   Handle(Geom2dAdaptor_HCurve) HE = new Geom2dAdaptor_HCurve(myCurve,First,Last);
505   return HE;
506 }
507
508
509 //=======================================================================
510 //function : IsClosed
511 //purpose  : 
512 //=======================================================================
513
514 Standard_Boolean Geom2dAdaptor_Curve::IsClosed() const 
515 {
516   if (!Precision::IsPositiveInfinite(myLast) &&
517       !Precision::IsNegativeInfinite(myFirst)) {
518     gp_Pnt2d Pd = Value(myFirst);
519     gp_Pnt2d Pf = Value(myLast);
520     return ( Pd.Distance(Pf) <= Precision::Confusion());
521   }
522   else
523     return Standard_False;
524 }
525
526 //=======================================================================
527 //function : IsPeriodic
528 //purpose  : 
529 //=======================================================================
530
531 Standard_Boolean Geom2dAdaptor_Curve::IsPeriodic() const 
532 {
533   if (myCurve->IsPeriodic())
534     return IsClosed();
535   else
536     return Standard_False;
537 }
538
539 //=======================================================================
540 //function : Period
541 //purpose  : 
542 //=======================================================================
543
544 Standard_Real Geom2dAdaptor_Curve::Period() const 
545 {
546   return myCurve->LastParameter() - myCurve->FirstParameter();
547 }
548
549 //=======================================================================
550 //function : RebuildCache
551 //purpose  : 
552 //=======================================================================
553 void Geom2dAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
554 {
555   myCurveCache->BuildCache(theParameter, myBspl->Degree(), 
556     myBspl->IsPeriodic(), myBspl->KnotSequence(), 
557     myBspl->Poles(), myBspl->Weights());
558 }
559
560 //=======================================================================
561 //function : Value
562 //purpose  : 
563 //=======================================================================
564
565 gp_Pnt2d Geom2dAdaptor_Curve::Value(const Standard_Real U) const 
566 {
567   if (myTypeCurve == GeomAbs_BSplineCurve)
568     return ValueBSpline(U);
569   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
570     return ValueOffset(U);
571
572   return myCurve->Value(U);
573 }
574
575 //=======================================================================
576 //function : ValueBSpline
577 //purpose  : Computes the point of parameter U on the B-spline curve
578 //=======================================================================
579 gp_Pnt2d Geom2dAdaptor_Curve::ValueBSpline(const Standard_Real theU) const
580 {
581   if (theU == myFirst || theU == myLast)
582   {
583     Standard_Integer Ideb = 0, Ifin = 0;
584     if (theU == myFirst)
585     {
586       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
587       if (Ideb<1) Ideb=1;
588       if (Ideb>=Ifin) Ifin = Ideb+1;
589     }
590     if (theU == myLast)
591     {
592       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
593       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
594       if (Ideb>=Ifin) Ideb = Ifin-1;
595     }
596     return myBspl->LocalValue(theU, Ideb, Ifin);
597   }
598   else if (!myCurveCache.IsNull()) // use cached B-spline data
599   {
600     if (!myCurveCache->IsCacheValid(theU))
601       RebuildCache(theU);
602     gp_Pnt2d aRes;
603     myCurveCache->D0(theU, aRes);
604     return aRes;
605   }
606   return myCurve->Value(theU);
607 }
608
609 //=======================================================================
610 //function : ValueOffset
611 //purpose  : Computes the point of parameter U on the offset curve
612 //=======================================================================
613 gp_Pnt2d Geom2dAdaptor_Curve::ValueOffset(const Standard_Real theU) const
614 {
615   gp_Pnt2d aP;
616   gp_Vec2d aD1;
617   myOffsetBaseCurveAdaptor->D1(theU, aP, aD1);
618   Standard_Boolean isDirectionChange = Standard_False;
619   const Standard_Real aTol = gp::Resolution();
620   if(aD1.SquareMagnitude() <= aTol)
621     isDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 1, theU, aD1);
622
623   Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
624   CSLib_Offset::D0(aP, aD1, anOffset, isDirectionChange, aP);
625   return aP;
626 }
627
628 //=======================================================================
629 //function : D0
630 //purpose  : 
631 //=======================================================================
632
633 void Geom2dAdaptor_Curve::D0(const Standard_Real U, gp_Pnt2d& P) const
634 {
635   if (myTypeCurve == GeomAbs_BSplineCurve)
636   {
637     D0BSpline(U, P);
638     return;
639   }
640   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
641   {
642     D0Offset(U, P);
643     return;
644   }
645
646   myCurve->D0(U, P);
647 }
648
649 //=======================================================================
650 //function : D0BSpline
651 //purpose  : Computes the point of parameter theU on the B-spline curve
652 //=======================================================================
653 void Geom2dAdaptor_Curve::D0BSpline(const Standard_Real theU, gp_Pnt2d& theP) const
654 {
655   if (theU == myFirst || theU == myLast)
656   {
657     Standard_Integer Ideb = 0, Ifin = 0;
658     if (theU == myFirst) {
659       myBspl->LocateU(myFirst,  PosTol, Ideb, Ifin);
660       if (Ideb<1) Ideb=1;
661       if (Ideb>=Ifin) Ifin = Ideb+1;
662     }
663     if (theU == myLast) {
664       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
665       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
666       if (Ideb>=Ifin) Ideb = Ifin-1;
667     }
668     myBspl->LocalD0(theU, Ideb, Ifin, theP);
669     return;
670   }
671   else if (!myCurveCache.IsNull()) // use cached B-spline data
672   {
673     if (!myCurveCache->IsCacheValid(theU))
674       RebuildCache(theU);
675     myCurveCache->D0(theU, theP);
676     return;
677   }
678   myCurve->D0(theU, theP);
679 }
680
681 //=======================================================================
682 //function : D0Offset
683 //purpose  : Computes the point of parameter theU on the offset curve
684 //=======================================================================
685 void Geom2dAdaptor_Curve::D0Offset(const Standard_Real theU, gp_Pnt2d& theP) const
686 {
687   theP = ValueOffset(theU);
688 }
689
690 //=======================================================================
691 //function : D1
692 //purpose  : 
693 //=======================================================================
694
695 void Geom2dAdaptor_Curve::D1(const Standard_Real U, 
696                              gp_Pnt2d& P, gp_Vec2d& V) const 
697 {
698   if (myTypeCurve == GeomAbs_BSplineCurve)
699   {
700     D1BSpline(U, P, V);
701     return;
702   }
703   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
704   {
705     D1Offset(U, P, V);
706     return;
707   }
708
709   myCurve->D1(U, P, V);
710 }
711
712 //=======================================================================
713 //function : D1BSpline
714 //purpose  : Computes the point of parameter theU on the B-spline curve and its derivative
715 //=======================================================================
716 void Geom2dAdaptor_Curve::D1BSpline(const Standard_Real theU, gp_Pnt2d& theP, gp_Vec2d& theV) const
717 {
718   if (theU == myFirst || theU == myLast)
719   {
720     Standard_Integer Ideb = 0, Ifin = 0;
721     if (theU == myFirst) {
722       myBspl->LocateU(myFirst,  PosTol, Ideb, Ifin);
723       if (Ideb<1) Ideb=1;
724       if (Ideb>=Ifin) Ifin = Ideb+1;
725     }
726     if (theU == myLast) {
727       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
728       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
729       if (Ideb>=Ifin) Ideb = Ifin-1;
730     }
731     myBspl->LocalD1(theU, Ideb, Ifin, theP, theV); 
732     return;
733   }
734   else if (!myCurveCache.IsNull()) // use cached B-spline data
735   {
736     if (!myCurveCache->IsCacheValid(theU))
737       RebuildCache(theU);
738     myCurveCache->D1(theU, theP, theV);
739     return;
740   }
741   myCurve->D1(theU, theP, theV);
742 }
743
744 //=======================================================================
745 //function : D1Offset
746 //purpose  : Computes the point of parameter theU on the offset curve and its derivative
747 //=======================================================================
748 void Geom2dAdaptor_Curve::D1Offset(const Standard_Real theU, gp_Pnt2d& theP, gp_Vec2d& theV) const
749 {
750    // P(u) = p(u) + Offset * Ndir / R
751    // with R = || p' ^ Z|| and Ndir = P' ^ Z
752
753    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
754
755   gp_Vec2d V2;
756   myOffsetBaseCurveAdaptor->D2 (theU, theP, theV, V2);
757
758   Standard_Boolean IsDirectionChange = Standard_False;
759   if(theV.SquareMagnitude() <= gp::Resolution())
760     IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 2, theU, theV, V2);
761
762   Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
763   CSLib_Offset::D1(theP, theV, V2, anOffset, IsDirectionChange, theP, theV);
764 }
765
766 //=======================================================================
767 //function : D2
768 //purpose  : 
769 //=======================================================================
770
771 void Geom2dAdaptor_Curve::D2(const Standard_Real U, 
772                              gp_Pnt2d& P, gp_Vec2d& V1, gp_Vec2d& V2) const 
773 {
774   if (myTypeCurve == GeomAbs_BSplineCurve)
775   {
776     D2BSpline(U, P, V1, V2);
777     return;
778   }
779   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
780   {
781     D2Offset(U, P, V1, V2);
782     return;
783   }
784
785   myCurve->D2(U, P, V1, V2);
786 }
787
788 //=======================================================================
789 //function : D2BSpline
790 //purpose  : Computes the point of parameter theU on the B-spline curve and its first and second derivatives
791 //=======================================================================
792 void Geom2dAdaptor_Curve::D2BSpline(const Standard_Real theU, gp_Pnt2d& theP,
793                                     gp_Vec2d& theV1, gp_Vec2d& theV2) const
794 {
795   if (theU == myFirst || theU == myLast)
796   {
797     Standard_Integer Ideb = 0, Ifin = 0;
798     if (theU == myFirst) {
799       myBspl->LocateU(myFirst,  PosTol, Ideb, Ifin);
800       if (Ideb<1) Ideb=1;
801       if (Ideb>=Ifin) Ifin = Ideb+1;
802     }
803     if (theU == myLast) {
804       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
805       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
806       if (Ideb>=Ifin) Ideb = Ifin-1;
807     }
808     myBspl->LocalD2(theU, Ideb, Ifin, theP, theV1, theV2);
809     return;
810   }
811   else if (!myCurveCache.IsNull()) // use cached B-spline data
812   {
813     if (!myCurveCache->IsCacheValid(theU))
814       RebuildCache(theU);
815     myCurveCache->D2(theU, theP, theV1, theV2);
816     return;
817   }
818   myCurve->D2(theU, theP, theV1, theV2);
819 }
820 //=======================================================================
821 //function : D2Offset
822 //purpose  : Computes the point of parameter theU on the offset curve and its first and second derivatives
823 //=======================================================================
824 void Geom2dAdaptor_Curve::D2Offset(const Standard_Real theU, gp_Pnt2d& theP,
825                                     gp_Vec2d& theV1, gp_Vec2d& theV2) const
826 {
827    // P(u) = p(u) + Offset * Ndir / R
828    // with R = || p' ^ Z|| and Ndir = P' ^ Z
829
830    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
831
832    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
833    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
834
835   gp_Vec2d V3;
836   myOffsetBaseCurveAdaptor->D3 (theU, theP, theV1, theV2, V3);
837
838   Standard_Boolean IsDirectionChange = Standard_False;
839   if(theV1.SquareMagnitude() <= gp::Resolution())
840     IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 3, theU, theV1, theV2, V3);
841
842   Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
843   CSLib_Offset::D2(theP, theV1, theV2, V3, anOffset, IsDirectionChange, theP, theV1, theV2);
844 }
845
846 //=======================================================================
847 //function : D3
848 //purpose  : 
849 //=======================================================================
850
851 void Geom2dAdaptor_Curve::D3(const Standard_Real U, 
852                              gp_Pnt2d& P,  gp_Vec2d& V1, 
853                              gp_Vec2d& V2, gp_Vec2d& V3) const 
854 {
855   if (myTypeCurve == GeomAbs_BSplineCurve)
856   {
857     D3BSpline(U, P, V1, V2, V3);
858     return;
859   }
860   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
861   {
862     D3Offset(U, P, V1, V2, V3);
863     return;
864   }
865
866   myCurve->D3(U, P, V1, V2, V3);
867 }
868
869 //=======================================================================
870 //function : D3BSpline
871 //purpose  : Computes the point of parameter theU on the B-spline curve and its 1st - 3rd derivatives
872 //=======================================================================
873 void Geom2dAdaptor_Curve::D3BSpline(const Standard_Real theU, gp_Pnt2d& theP,
874                                     gp_Vec2d& theV1, gp_Vec2d& theV2, gp_Vec2d& theV3) const
875 {
876   if (theU == myFirst || theU == myLast)
877   {
878     Standard_Integer Ideb = 0, Ifin = 0;
879     if (theU == myFirst) {
880       myBspl->LocateU(myFirst,  PosTol, Ideb, Ifin);
881       if (Ideb<1) Ideb=1;
882       if (Ideb>=Ifin) Ifin = Ideb+1;
883     }
884     if (theU == myLast) {
885       myBspl->LocateU(myLast,  PosTol, Ideb, Ifin);
886       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
887       if (Ideb>=Ifin) Ideb = Ifin-1;
888     }
889     myBspl->LocalD3(theU, Ideb, Ifin, theP, theV1, theV2, theV3);
890     return;
891   }
892   else if (!myCurveCache.IsNull()) // use cached B-spline data
893   {
894     if (!myCurveCache->IsCacheValid(theU))
895       RebuildCache(theU);
896     myCurveCache->D3(theU, theP, theV1, theV2, theV3);
897     return;
898   }
899   myCurve->D3(theU, theP, theV1, theV2, theV3);
900 }
901 //=======================================================================
902 //function : D3Offset
903 //purpose  : Computes the point of parameter theU on the offset curve and its 1st - 3rd derivatives
904 //=======================================================================
905 void Geom2dAdaptor_Curve::D3Offset(const Standard_Real theU, gp_Pnt2d& theP,
906                                     gp_Vec2d& theV1, gp_Vec2d& theV2, gp_Vec2d& theV3) const
907 {
908    // P(u) = p(u) + Offset * Ndir / R
909    // with R = || p' ^ Z|| and Ndir = P' ^ Z
910
911    // P'(u) = p'(u) + (Offset / R**2) * (DNdir/DU * R -  Ndir * (DR/R))
912
913    // P"(u) = p"(u) + (Offset / R) * (D2Ndir/DU - DNdir * (2.0 * Dr/ R**2) +
914    //         Ndir * ( (3.0 * Dr**2 / R**4) - (D2r / R**2)))
915
916    //P"'(u) = p"'(u) + (Offset / R) * (D3Ndir - (3.0 * Dr/R**2 ) * D2Ndir -
917    //         (3.0 * D2r / R2) * DNdir) + (3.0 * Dr * Dr / R4) * DNdir -
918    //         (D3r/R2) * Ndir + (6.0 * Dr * Dr / R4) * Ndir +
919    //         (6.0 * Dr * D2r / R4) * Ndir - (15.0 * Dr* Dr* Dr /R6) * Ndir
920
921   Standard_Boolean IsDirectionChange = Standard_False;
922
923   myOffsetBaseCurveAdaptor->D3 (theU, theP, theV1, theV2, theV3);
924   gp_Vec2d V4 = myOffsetBaseCurveAdaptor->DN (theU, 4);
925
926   if(theV1.SquareMagnitude() <= gp::Resolution())
927     IsDirectionChange = AdjustDerivative(myOffsetBaseCurveAdaptor, 4, theU, theV1, theV2, theV3, V4);
928
929   Standard_Real anOffset = Handle(Geom2d_OffsetCurve)::DownCast(myCurve)->Offset();
930   CSLib_Offset::D3(theP, theV1, theV2, theV3, V4, anOffset, IsDirectionChange,
931                    theP, theV1, theV2, theV3);
932 }
933
934 //=======================================================================
935 //function : DN
936 //purpose  : 
937 //=======================================================================
938
939 gp_Vec2d Geom2dAdaptor_Curve::DN(const Standard_Real U, 
940                                  const Standard_Integer N) const 
941 {
942   if (myTypeCurve == GeomAbs_BSplineCurve)
943     return DNBSpline(U, N);
944   else if (myCurve->DynamicType() == STANDARD_TYPE(Geom2d_OffsetCurve))
945     return DNOffset(U, N);
946
947   return myCurve->DN(U, N);
948 }
949
950 gp_Vec2d Geom2dAdaptor_Curve::DNBSpline(const Standard_Real U, 
951                                         const Standard_Integer N) const 
952 {
953   if (U==myFirst || U==myLast)
954   {
955     Standard_Integer Ideb = 0, Ifin = 0;
956     if (U==myFirst) {
957       myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
958       if (Ideb<1) Ideb=1;
959       if (Ideb>=Ifin) Ifin = Ideb+1;
960     }
961     if (U==myLast) {
962       myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
963       if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
964       if (Ideb>=Ifin) Ideb = Ifin-1;
965     } 
966     return myBspl->LocalDN( U, Ideb, Ifin, N);
967   }
968
969   return myCurve->DN( U, N);
970 }
971
972 gp_Vec2d Geom2dAdaptor_Curve::DNOffset(const Standard_Real    U,
973                                        const Standard_Integer N) const
974 {
975   gp_Pnt2d aPnt;
976   gp_Vec2d aVec, aVN;
977
978   switch (N)
979   {
980   case 1:
981     D1Offset(U, aPnt, aVN);
982     break;
983   case 2:
984     D2Offset(U, aPnt, aVec, aVN);
985     break;
986   case 3:
987     D3Offset(U, aPnt, aVec, aVec, aVN);
988     break;
989   default:
990     aVN = myCurve->DN(U, N);
991   }
992   return aVN;
993 }
994
995 //=======================================================================
996 //function : Resolution
997 //purpose  : 
998 //=======================================================================
999
1000 Standard_Real Geom2dAdaptor_Curve::Resolution(const Standard_Real Ruv) const {
1001   switch ( myTypeCurve) {
1002   case GeomAbs_Line :
1003     return Ruv;
1004   case GeomAbs_Circle: {
1005     Standard_Real R = Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d().Radius();
1006     if ( R > Ruv/2.)
1007       return 2*ASin(Ruv/(2*R));
1008     else
1009       return 2*M_PI;
1010   }
1011   case GeomAbs_Ellipse: {
1012     return Ruv / Handle(Geom2d_Ellipse)::DownCast (myCurve)->MajorRadius();
1013   }
1014   case GeomAbs_BezierCurve: {
1015     Standard_Real res;
1016     Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Resolution(Ruv,res);
1017     return res;
1018   }
1019   case GeomAbs_BSplineCurve: {
1020     Standard_Real res;
1021     Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Resolution(Ruv,res);
1022     return res;
1023   }
1024   default:
1025     return Precision::Parametric(Ruv);
1026   }  
1027 }
1028
1029
1030 //    --
1031 //    --     The following methods must  be called when GetType returned
1032 //    --     the corresponding type.
1033 //    --     
1034
1035 //=======================================================================
1036 //function : Line
1037 //purpose  : 
1038 //=======================================================================
1039
1040 gp_Lin2d Geom2dAdaptor_Curve::Line() const 
1041 {
1042   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
1043   return Handle(Geom2d_Line)::DownCast (myCurve)->Lin2d();
1044 }
1045
1046 //=======================================================================
1047 //function : Circle
1048 //purpose  : 
1049 //=======================================================================
1050
1051 gp_Circ2d  Geom2dAdaptor_Curve::Circle() const 
1052 {
1053   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
1054   return Handle(Geom2d_Circle)::DownCast (myCurve)->Circ2d();
1055 }
1056
1057 //=======================================================================
1058 //function : Ellipse
1059 //purpose  : 
1060 //=======================================================================
1061
1062 gp_Elips2d Geom2dAdaptor_Curve::Ellipse() const 
1063 {
1064   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
1065   return Handle(Geom2d_Ellipse)::DownCast (myCurve)->Elips2d();
1066 }
1067
1068 //=======================================================================
1069 //function : Hyperbola
1070 //purpose  : 
1071 //=======================================================================
1072
1073 gp_Hypr2d Geom2dAdaptor_Curve::Hyperbola() const 
1074 {
1075   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
1076   return Handle(Geom2d_Hyperbola)::DownCast (myCurve)->Hypr2d();
1077 }
1078
1079 //=======================================================================
1080 //function : Parabola
1081 //purpose  : 
1082 //=======================================================================
1083
1084 gp_Parab2d Geom2dAdaptor_Curve::Parabola() const 
1085 {
1086   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
1087   return Handle(Geom2d_Parabola)::DownCast (myCurve)->Parab2d();
1088 }
1089
1090 //=======================================================================
1091 //function : Degree
1092 //purpose  : 
1093 //=======================================================================
1094
1095 Standard_Integer Geom2dAdaptor_Curve::Degree() const
1096 {
1097   if (myTypeCurve == GeomAbs_BezierCurve)
1098     return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->Degree();
1099   else if (myTypeCurve == GeomAbs_BSplineCurve)
1100     return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->Degree();
1101   else
1102     Standard_NoSuchObject::Raise();
1103   // portage WNT 
1104   return 0;
1105 }
1106
1107 //=======================================================================
1108 //function : IsRational
1109 //purpose  : 
1110 //=======================================================================
1111
1112 Standard_Boolean Geom2dAdaptor_Curve::IsRational() const {
1113   switch( myTypeCurve) {
1114   case GeomAbs_BSplineCurve:
1115     return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->IsRational();
1116   case GeomAbs_BezierCurve:
1117     return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->IsRational();
1118   default:
1119     return Standard_False;
1120   }
1121 }
1122
1123 //=======================================================================
1124 //function : NbPoles
1125 //purpose  : 
1126 //=======================================================================
1127
1128 Standard_Integer Geom2dAdaptor_Curve::NbPoles() const
1129 {
1130   if (myTypeCurve == GeomAbs_BezierCurve)
1131     return Handle(Geom2d_BezierCurve)::DownCast (myCurve)->NbPoles();
1132   else if (myTypeCurve == GeomAbs_BSplineCurve)
1133     return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->NbPoles();
1134   else
1135     Standard_NoSuchObject::Raise();
1136   // portage WNT 
1137   return 0;
1138 }
1139
1140 //=======================================================================
1141 //function : NbKnots
1142 //purpose  : 
1143 //=======================================================================
1144
1145 Standard_Integer Geom2dAdaptor_Curve::NbKnots() const {
1146   if ( myTypeCurve != GeomAbs_BSplineCurve)
1147     Standard_NoSuchObject::Raise("Geom2dAdaptor_Curve::NbKnots");
1148   return Handle(Geom2d_BSplineCurve)::DownCast (myCurve)->NbKnots();
1149
1150 }
1151
1152 //=======================================================================
1153 //function : Bezier
1154 //purpose  : 
1155 //=======================================================================
1156
1157 Handle(Geom2d_BezierCurve) Geom2dAdaptor_Curve::Bezier() const 
1158 {
1159   return Handle(Geom2d_BezierCurve)::DownCast (myCurve);
1160 }
1161
1162 //=======================================================================
1163 //function : BSpline
1164 //purpose  : 
1165 //=======================================================================
1166
1167 Handle(Geom2d_BSplineCurve) Geom2dAdaptor_Curve::BSpline() const 
1168 {
1169   return Handle(Geom2d_BSplineCurve)::DownCast (myCurve);
1170 }
1171
1172 static Standard_Integer nbPoints(const Handle(Geom2d_Curve)& theCurve) 
1173 {
1174  
1175   Standard_Integer nbs = 10;
1176   
1177   if(theCurve->IsKind(STANDARD_TYPE( Geom2d_Line)) )
1178     nbs = 2;
1179   else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BezierCurve))) 
1180   {
1181     nbs = 3 + Handle(Geom2d_BezierCurve)::DownCast (theCurve)->NbPoles();
1182   }
1183   else if(theCurve->IsKind(STANDARD_TYPE( Geom2d_BSplineCurve))) { 
1184     nbs =  Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->NbKnots();
1185     nbs*= Handle(Geom2d_BSplineCurve)::DownCast (theCurve)->Degree();
1186     if(nbs < 2.0) nbs=2;
1187   }
1188   else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve)))
1189   {
1190     Handle(Geom2d_Curve) aCurve = Handle(Geom2d_OffsetCurve)::DownCast (theCurve)->BasisCurve();
1191     return Max(nbs, nbPoints(aCurve));
1192   }
1193
1194   else if (theCurve->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1195   {
1196     Handle(Geom2d_Curve) aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
1197     return Max(nbs, nbPoints(aCurve));
1198   }
1199   if(nbs>300)
1200     nbs = 300;
1201   return nbs;
1202   
1203 }
1204
1205 Standard_Integer Geom2dAdaptor_Curve::NbSamples() const
1206 {
1207   return  nbPoints(myCurve);
1208 }
1209
1210
1211 // ============= Auxiliary functions ===================
1212 Standard_Boolean AdjustDerivative(const Handle(Adaptor2d_HCurve2d)& theAdaptor, Standard_Integer theMaxDerivative,
1213                                   Standard_Real theU, gp_Vec2d& theD1, gp_Vec2d& theD2,
1214                                   gp_Vec2d& theD3, gp_Vec2d& theD4)
1215 {
1216   static const Standard_Real aTol = gp::Resolution();
1217
1218   Standard_Boolean IsDirectionChange = Standard_False;
1219   const Standard_Real anUinfium   = theAdaptor->FirstParameter();
1220   const Standard_Real anUsupremum = theAdaptor->LastParameter();
1221
1222   const Standard_Real DivisionFactor = 1.e-3;
1223   Standard_Real du;
1224   if((anUsupremum >= RealLast()) || (anUinfium <= RealFirst())) 
1225     du = 0.0;
1226   else
1227     du = anUsupremum - anUinfium;
1228
1229   const Standard_Real aDelta = Max(du * DivisionFactor, MinStep);
1230
1231   //Derivative is approximated by Taylor-series
1232   Standard_Integer anIndex = 1; //Derivative order
1233   gp_Vec2d V;
1234
1235   do
1236   {
1237     V =  theAdaptor->DN(theU, ++anIndex);
1238   }
1239   while((V.Magnitude() <= aTol) && anIndex < maxDerivOrder);
1240
1241   Standard_Real u;
1242
1243   if(theU-anUinfium < aDelta)
1244     u = theU+aDelta;
1245   else
1246     u = theU-aDelta;
1247
1248   gp_Pnt2d P1, P2;
1249   theAdaptor->D0(Min(theU, u),P1);
1250   theAdaptor->D0(Max(theU, u),P2);
1251
1252   gp_Vec2d V1(P1, P2);
1253   IsDirectionChange = V.Dot(V1) < 0.0;
1254   Standard_Real aSign = IsDirectionChange ? -1.0 : 1.0;
1255
1256   theD1 = V * aSign;
1257   gp_Vec2d* aDeriv[3] = {&theD2, &theD3, &theD4};
1258   for (Standard_Integer i = 1; i < theMaxDerivative; i++)
1259     *(aDeriv[i-1]) = theAdaptor->DN(theU, anIndex + i) * aSign;
1260
1261   return IsDirectionChange;
1262 }