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