0026838: Using GeomEvaluators for calculation of values of curves
[occt.git] / src / GeomAdaptor / GeomAdaptor_Curve.cxx
1 // Created on: 1993-04-29
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 : RBV -> traitement des offset curves
20
21 #define No_Standard_RangeError
22 #define No_Standard_OutOfRange
23
24
25 #include <Adaptor3d_HCurve.hxx>
26 #include <BSplCLib.hxx>
27 #include <BSplCLib_Cache.hxx>
28 #include <Geom_BezierCurve.hxx>
29 #include <Geom_BSplineCurve.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_Curve.hxx>
32 #include <Geom_Ellipse.hxx>
33 #include <Geom_Hyperbola.hxx>
34 #include <Geom_Line.hxx>
35 #include <Geom_OffsetCurve.hxx>
36 #include <Geom_Parabola.hxx>
37 #include <Geom_TrimmedCurve.hxx>
38 #include <GeomAbs_Shape.hxx>
39 #include <GeomAdaptor_Curve.hxx>
40 #include <GeomAdaptor_HCurve.hxx>
41 #include <GeomAdaptor_Surface.hxx>
42 #include <GeomEvaluator_OffsetCurve.hxx>
43 #include <gp_Circ.hxx>
44 #include <gp_Elips.hxx>
45 #include <gp_Hypr.hxx>
46 #include <gp_Lin.hxx>
47 #include <gp_Parab.hxx>
48 #include <gp_Pnt.hxx>
49 #include <gp_Vec.hxx>
50 #include <Precision.hxx>
51 #include <Standard_ConstructionError.hxx>
52 #include <Standard_DomainError.hxx>
53 #include <Standard_NoSuchObject.hxx>
54 #include <Standard_NotImplemented.hxx>
55 #include <Standard_NullObject.hxx>
56 #include <Standard_OutOfRange.hxx>
57 #include <TColgp_Array1OfPnt.hxx>
58 #include <TColStd_Array1OfInteger.hxx>
59 #include <TColStd_Array1OfReal.hxx>
60 #include <TColStd_HArray1OfInteger.hxx>
61
62 //#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
63 static const Standard_Real PosTol = Precision::PConfusion() / 2;
64
65
66 //=======================================================================
67 //function : LocalContinuity
68 //purpose  : Computes the Continuity of a BSplineCurve 
69 //           between the parameters U1 and U2
70 //           The continuity is C(d-m) 
71 //             with   d = degree, 
72 //                    m = max multiplicity of the Knots between U1 and U2
73 //=======================================================================
74
75 GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1, 
76                                                  const Standard_Real U2) 
77      const 
78 {
79   Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
80   Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
81   Standard_Integer Nb = aBspl->NbKnots();
82   Standard_Integer Index1 = 0;
83   Standard_Integer Index2 = 0;
84   Standard_Real newFirst, newLast;
85   TColStd_Array1OfReal    TK(1,Nb);
86   TColStd_Array1OfInteger TM(1,Nb);
87   aBspl->Knots(TK);
88   aBspl->Multiplicities(TM);
89   BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,U1,aBspl->IsPeriodic(),
90                             1,Nb,Index1,newFirst);
91   BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,U2,aBspl->IsPeriodic(),
92                             1,Nb,Index2,newLast);
93   if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) { 
94     if (Index1 < Nb) Index1++;
95   }
96   if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
97     Index2--;
98   Standard_Integer MultMax;
99   // attention aux courbes peridiques.
100   if ( (aBspl->IsPeriodic()) && (Index1 == Nb) )
101     Index1 = 1;
102
103   if ( Index2 - Index1 <= 0) {
104     MultMax = 100;  // CN entre 2 Noeuds consecutifs
105   }
106   else {
107     MultMax = TM(Index1+1);
108     for(Standard_Integer i = Index1+1;i<=Index2;i++) {
109       if ( TM(i)>MultMax) MultMax=TM(i);
110     }
111     MultMax = aBspl->Degree() - MultMax;
112   }
113   if ( MultMax <= 0) {
114     return GeomAbs_C0;
115   }
116   else if ( MultMax == 1) {
117     return GeomAbs_C1;
118   } 
119   else if ( MultMax == 2) {
120     return GeomAbs_C2;
121   }
122   else if ( MultMax == 3) {
123     return GeomAbs_C3;
124   }
125   else { 
126     return GeomAbs_CN;
127   }
128 }
129
130
131 //=======================================================================
132 //function : Load
133 //purpose  : 
134 //=======================================================================
135
136 void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
137                              const Standard_Real UFirst,
138                              const Standard_Real ULast)
139 {
140   myFirst = UFirst;
141   myLast  = ULast;
142
143   if ( myCurve != C) {
144     myCurve = C;
145     myCurveCache = Handle(BSplCLib_Cache)();
146     myNestedEvaluator = Handle(GeomEvaluator_Curve)();
147
148     const Handle(Standard_Type)& TheType = C->DynamicType();
149     if ( TheType == STANDARD_TYPE(Geom_TrimmedCurve)) {
150       Load(Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve(),UFirst,ULast);
151     }
152     else if ( TheType ==  STANDARD_TYPE(Geom_Circle)) {
153       myTypeCurve = GeomAbs_Circle;
154     }
155     else if ( TheType ==STANDARD_TYPE(Geom_Line)) {
156       myTypeCurve = GeomAbs_Line;
157     }
158     else if ( TheType == STANDARD_TYPE(Geom_Ellipse)) {
159       myTypeCurve = GeomAbs_Ellipse;
160     }
161     else if ( TheType == STANDARD_TYPE(Geom_Parabola)) {
162       myTypeCurve = GeomAbs_Parabola;
163     }
164     else if ( TheType == STANDARD_TYPE(Geom_Hyperbola)) {
165       myTypeCurve = GeomAbs_Hyperbola;
166     }
167     else if ( TheType == STANDARD_TYPE(Geom_BezierCurve)) {
168       myTypeCurve = GeomAbs_BezierCurve;
169       // Create cache for Bezier
170       Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
171       Standard_Integer aDeg = aBezier->Degree();
172       TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
173       myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
174           aBezier->Poles(), aBezier->Weights());
175     }
176     else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
177       myTypeCurve = GeomAbs_BSplineCurve;
178       // Create cache for B-spline
179       Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
180       myCurveCache = new BSplCLib_Cache(aBspl->Degree(), aBspl->IsPeriodic(),
181           aBspl->KnotSequence(), aBspl->Poles(), aBspl->Weights());
182     }
183     else if ( TheType == STANDARD_TYPE(Geom_OffsetCurve)) {
184       myTypeCurve = GeomAbs_OffsetCurve;
185       Handle(Geom_OffsetCurve) anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(myCurve);
186       // Create nested adaptor for base curve
187       Handle(Geom_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
188       Handle(GeomAdaptor_HCurve) aBaseAdaptor = new GeomAdaptor_HCurve(aBaseCurve);
189       myNestedEvaluator = new GeomEvaluator_OffsetCurve(
190           aBaseAdaptor, anOffsetCurve->Offset(), anOffsetCurve->Direction());
191     }
192     else {
193       myTypeCurve = GeomAbs_OtherCurve;
194     }
195   }
196 }  
197
198 //    --
199 //    --     Global methods - Apply to the whole curve.
200 //    --     
201
202 //=======================================================================
203 //function : Continuity
204 //purpose  : 
205 //=======================================================================
206
207 GeomAbs_Shape GeomAdaptor_Curve::Continuity() const 
208 {
209   if (myTypeCurve == GeomAbs_BSplineCurve)
210     return LocalContinuity(myFirst, myLast);
211
212   if (myTypeCurve == GeomAbs_OffsetCurve)
213   {
214     const GeomAbs_Shape S =
215       Handle(Geom_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
216     switch(S)
217     {
218       case GeomAbs_CN: return GeomAbs_CN;
219       case GeomAbs_C3: return GeomAbs_C2;
220       case GeomAbs_C2: return GeomAbs_C1;
221       case GeomAbs_C1: return GeomAbs_C0; 
222       case GeomAbs_G1: return GeomAbs_G1;
223       case GeomAbs_G2: return GeomAbs_G2;
224       default:
225         Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Continuity");
226     }
227   }
228   else if (myTypeCurve == GeomAbs_OtherCurve) {
229     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Contunuity");
230   }
231
232   return GeomAbs_CN;
233 }
234
235 //=======================================================================
236 //function : NbIntervals
237 //purpose  : 
238 //=======================================================================
239
240 Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
241 {
242   Standard_Integer myNbIntervals = 1;
243   Standard_Integer NbSplit;
244   if (myTypeCurve == GeomAbs_BSplineCurve) {
245     Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
246     Standard_Integer FirstIndex = aBspl->FirstUKnotIndex();
247     Standard_Integer LastIndex  = aBspl->LastUKnotIndex();
248     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
249     if ( S > Continuity()) {
250       Standard_Integer Cont;
251       switch ( S) {
252       case GeomAbs_G1:
253       case GeomAbs_G2:
254         Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
255         break;
256       case GeomAbs_C0:
257         myNbIntervals = 1;
258         break;
259       case GeomAbs_C1:
260       case GeomAbs_C2:
261       case GeomAbs_C3: 
262       case GeomAbs_CN: 
263         {
264           if      ( S == GeomAbs_C1) Cont = 1;
265           else if ( S == GeomAbs_C2) Cont = 2;
266           else if ( S == GeomAbs_C3) Cont = 3;
267           else                       Cont = aBspl->Degree();
268           Standard_Integer Degree = aBspl->Degree();
269           Standard_Integer NbKnots = aBspl->NbKnots();
270           TColStd_Array1OfInteger Mults (1, NbKnots);
271           aBspl->Multiplicities (Mults);
272           NbSplit = 1;
273           Standard_Integer Index   = FirstIndex;
274           Inter (NbSplit) = Index;
275           Index++;
276           NbSplit++;
277           while (Index < LastIndex) 
278             {
279               if (Degree - Mults (Index) < Cont) 
280                 {
281                   Inter (NbSplit) = Index;
282                   NbSplit++;
283                 }
284               Index++;
285             }
286           Inter (NbSplit) = Index;
287
288           Standard_Integer NbInt = NbSplit-1;
289           
290           Standard_Integer Nb = aBspl->NbKnots();
291           Standard_Integer Index1 = 0;
292           Standard_Integer Index2 = 0;
293           Standard_Real newFirst, newLast;
294           TColStd_Array1OfReal    TK(1,Nb);
295           TColStd_Array1OfInteger TM(1,Nb);
296           aBspl->Knots(TK);
297           aBspl->Multiplicities(TM);
298           BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myFirst,
299                                     aBspl->IsPeriodic(),
300                                     1,Nb,Index1,newFirst);
301           BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myLast,
302                                     aBspl->IsPeriodic(),
303                                     1,Nb,Index2,newLast);
304
305           // On decale eventuellement les indices  
306           // On utilise une "petite" tolerance, la resolution ne doit 
307           // servir que pour les tres longue courbes....(PRO9248)
308           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
309                                   Precision::PConfusion()); 
310           if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
311           if ( newLast-TK(Index2)> Eps) Index2++;
312           
313           myNbIntervals = 1;
314           for ( Standard_Integer i=1; i<=NbInt; i++)
315             if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
316         }
317         break;
318       }
319     }
320   }
321   
322   else if (myTypeCurve == GeomAbs_OffsetCurve) {
323     GeomAbs_Shape BaseS=GeomAbs_C0;
324     switch(S){
325     case GeomAbs_G1:
326     case GeomAbs_G2:
327       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
328       break;
329     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
330     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
331     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
332     default: BaseS = GeomAbs_CN;
333     }
334     GeomAdaptor_Curve C
335       (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
336     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
337     //                    the number of intervals obtained from the basis to
338     //              vvv   reflect parameter bounds
339     Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
340     if (iNbBasisInt>1)
341     {
342       TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
343       C.Intervals(rdfInter,BaseS);
344       for (iInt=1; iInt<=iNbBasisInt; iInt++)
345         if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
346           myNbIntervals++;
347     }
348     // akm 05/04/02 ^^^
349   }
350   return myNbIntervals;
351 }
352
353 //=======================================================================
354 //function : Intervals
355 //purpose  : 
356 //=======================================================================
357
358 void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
359                                   const GeomAbs_Shape S   ) const
360 {
361   Standard_Integer myNbIntervals = 1;
362   Standard_Integer NbSplit;
363   Standard_Real FirstParam = myFirst, LastParam = myLast;
364
365   if (myTypeCurve == GeomAbs_BSplineCurve) 
366     {
367       Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
368       Standard_Integer FirstIndex = aBspl->FirstUKnotIndex();
369       Standard_Integer LastIndex  = aBspl->LastUKnotIndex();
370       TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
371       
372       if ( S > Continuity()) {
373         Standard_Integer Cont;
374         switch ( S) {
375         case GeomAbs_G1:
376         case GeomAbs_G2:
377           Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
378           break;
379         case GeomAbs_C0:
380           myNbIntervals = 1;
381           break;
382         case GeomAbs_C1:
383         case GeomAbs_C2:
384         case GeomAbs_C3: 
385         case GeomAbs_CN: 
386           {
387             if      ( S == GeomAbs_C1) Cont = 1;
388             else if ( S == GeomAbs_C2) Cont = 2;
389             else if ( S == GeomAbs_C3) Cont = 3;
390             else                       Cont = aBspl->Degree();
391             Standard_Integer Degree = aBspl->Degree();
392             Standard_Integer NbKnots = aBspl->NbKnots();
393             TColStd_Array1OfInteger Mults (1, NbKnots);
394             aBspl->Multiplicities (Mults);
395             NbSplit = 1;
396             Standard_Integer Index   = FirstIndex;
397             Inter (NbSplit) = Index;
398             Index++;
399             NbSplit++;
400             while (Index < LastIndex) 
401               {
402                 if (Degree - Mults (Index) < Cont) 
403                   {
404                     Inter (NbSplit) = Index;
405                     NbSplit++;
406                   }
407                 Index++;
408               }
409             Inter (NbSplit) = Index;
410             Standard_Integer NbInt = NbSplit-1;
411             //        GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
412             //        Standard_Integer NbInt = Convector.NbSplits()-1;
413             //        TColStd_Array1OfInteger Inter(1,NbInt+1);
414             //        Convector.Splitting( Inter);
415             
416             Standard_Integer Nb = aBspl->NbKnots();
417             Standard_Integer Index1 = 0;
418             Standard_Integer Index2 = 0;
419             Standard_Real newFirst, newLast;
420             TColStd_Array1OfReal    TK(1,Nb);
421             TColStd_Array1OfInteger TM(1,Nb);
422             aBspl->Knots(TK);
423             aBspl->Multiplicities(TM);
424             BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myFirst,
425                                       aBspl->IsPeriodic(),
426                                       1,Nb,Index1,newFirst);
427             BSplCLib::LocateParameter(aBspl->Degree(),TK,TM,myLast,
428                                       aBspl->IsPeriodic(),
429                                       1,Nb,Index2,newLast);
430             FirstParam = newFirst;
431             LastParam = newLast;
432             // On decale eventuellement les indices  
433             // On utilise une "petite" tolerance, la resolution ne doit 
434             // servir que pour les tres longue courbes....(PRO9248)
435             Standard_Real Eps = Min(Resolution(Precision::Confusion()),
436                                     Precision::PConfusion()); 
437             if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
438             if ( newLast-TK(Index2)> Eps) Index2++;
439             
440             Inter( 1) = Index1;
441             myNbIntervals = 1;
442             for ( Standard_Integer i=1; i<=NbInt; i++) {
443               if (Inter(i) > Index1 && Inter(i)<Index2 ) {
444                 myNbIntervals++;
445                 Inter(myNbIntervals) = Inter(i);
446               }
447             }
448             Inter(myNbIntervals+1) = Index2;
449             
450             for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
451               T(I) = TK(Inter(I));
452             }
453           }
454           break;
455         }
456       }
457     }
458
459   else if (myTypeCurve == GeomAbs_OffsetCurve){
460     GeomAbs_Shape BaseS=GeomAbs_C0;
461     switch(S){
462     case GeomAbs_G1:
463     case GeomAbs_G2:
464       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
465       break;
466     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
467     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
468     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
469     default: BaseS = GeomAbs_CN;
470     }
471     GeomAdaptor_Curve C
472       (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
473     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
474     //                    the array of intervals obtained from the basis to
475     //              vvv   reflect parameter bounds
476     Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
477     if (iNbBasisInt>1)
478     {
479       TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
480       C.Intervals(rdfInter,BaseS);
481       for (iInt=1; iInt<=iNbBasisInt; iInt++)
482         if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
483           T(++myNbIntervals)=rdfInter(iInt);
484     }
485     // old - myNbIntervals = C.NbIntervals(BaseS);
486     // old - C.Intervals(T, BaseS);
487     // akm 05/04/02 ^^^
488   }
489   
490   T( T.Lower() ) = FirstParam;
491   T( T.Lower() + myNbIntervals ) = LastParam;
492 }
493
494 //=======================================================================
495 //function : Trim
496 //purpose  : 
497 //=======================================================================
498
499 Handle(Adaptor3d_HCurve) GeomAdaptor_Curve::Trim(const Standard_Real First,
500                                                  const Standard_Real Last,
501                                                  const Standard_Real /*Tol*/) const
502 {
503   return Handle(GeomAdaptor_HCurve)(new GeomAdaptor_HCurve(myCurve,First,Last));
504 }
505
506
507 //=======================================================================
508 //function : IsClosed
509 //purpose  : 
510 //=======================================================================
511
512 Standard_Boolean GeomAdaptor_Curve::IsClosed() const
513 {
514   if (!Precision::IsPositiveInfinite(myLast) &&
515       !Precision::IsNegativeInfinite(myFirst))
516   {
517     const gp_Pnt Pd = Value(myFirst);
518     const gp_Pnt Pf = Value(myLast);
519     return (Pd.Distance(Pf) <= Precision::Confusion());
520   }
521   return Standard_False;
522 }
523
524 //=======================================================================
525 //function : IsPeriodic
526 //purpose  : 
527 //=======================================================================
528
529 Standard_Boolean GeomAdaptor_Curve::IsPeriodic() const 
530 {
531   return (myCurve->IsPeriodic()? IsClosed() : Standard_False);
532 }
533
534 //=======================================================================
535 //function : Period
536 //purpose  : 
537 //=======================================================================
538
539 Standard_Real GeomAdaptor_Curve::Period() const 
540 {
541   return myCurve->LastParameter() - myCurve->FirstParameter();
542 }
543
544 //=======================================================================
545 //function : RebuildCache
546 //purpose  : 
547 //=======================================================================
548 void GeomAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
549 {
550   if (myTypeCurve == GeomAbs_BezierCurve)
551   {
552     Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
553     Standard_Integer aDeg = aBezier->Degree();
554     TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
555     myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
556         aBezier->Poles(), aBezier->Weights());
557   }
558   else if (myTypeCurve == GeomAbs_BSplineCurve)
559   {
560     Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
561     myCurveCache->BuildCache(theParameter, aBspl->Degree(),
562         aBspl->IsPeriodic(), aBspl->KnotSequence(),
563         aBspl->Poles(), aBspl->Weights());
564   }
565 }
566
567 //=======================================================================
568 //function : IsBoundary
569 //purpose  : 
570 //=======================================================================
571 Standard_Boolean GeomAdaptor_Curve::IsBoundary(const Standard_Real theU,
572                                                Standard_Integer& theSpanStart,
573                                                Standard_Integer& theSpanFinish) const
574 {
575   Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
576   if (!aBspl.IsNull() && (theU == myFirst || theU == myLast))
577   {
578     if (theU == myFirst)
579     {
580       aBspl->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
581       if (theSpanStart < 1)
582         theSpanStart = 1;
583       if (theSpanStart >= theSpanFinish)
584         theSpanFinish = theSpanStart + 1;
585     }
586     else if (theU == myLast)
587     {
588       aBspl->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
589       if (theSpanFinish > aBspl->NbKnots())
590         theSpanFinish = aBspl->NbKnots();
591       if (theSpanStart >= theSpanFinish)
592         theSpanStart = theSpanFinish - 1;
593     }
594     return Standard_True;
595   }
596   return Standard_False;
597 }
598
599 //=======================================================================
600 //function : Value
601 //purpose  : 
602 //=======================================================================
603
604 gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
605 {
606   gp_Pnt aValue;
607   D0(U, aValue);
608   return aValue;
609 }
610
611 //=======================================================================
612 //function : D0
613 //purpose  : 
614 //=======================================================================
615
616 void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
617 {
618   switch (myTypeCurve)
619   {
620   case GeomAbs_BezierCurve:
621   case GeomAbs_BSplineCurve:
622   {
623     Standard_Integer aStart = 0, aFinish = 0;
624     if (IsBoundary(U, aStart, aFinish))
625     {
626       Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
627       aBspl->LocalD0(U, aStart, aFinish, P);
628     }
629     else if (!myCurveCache.IsNull()) // use cached data
630     {
631       if (!myCurveCache->IsCacheValid(U))
632         RebuildCache(U);
633       myCurveCache->D0(U, P);
634     }
635     else
636       myCurve->D0(U, P);
637     break;
638   }
639
640   case GeomAbs_OffsetCurve:
641     myNestedEvaluator->D0(U, P);
642     break;
643
644   default:
645     myCurve->D0(U, P);
646   }
647 }
648
649 //=======================================================================
650 //function : D1
651 //purpose  : 
652 //=======================================================================
653
654 void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const 
655 {
656   switch (myTypeCurve)
657   {
658   case GeomAbs_BezierCurve:
659   case GeomAbs_BSplineCurve:
660   {
661     Standard_Integer aStart = 0, aFinish = 0;
662     if (IsBoundary(U, aStart, aFinish))
663     {
664       Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
665       aBspl->LocalD1(U, aStart, aFinish, P, V);
666     }
667     else if (!myCurveCache.IsNull()) // use cached data
668     {
669       if (!myCurveCache->IsCacheValid(U))
670         RebuildCache(U);
671       myCurveCache->D1(U, P, V);
672     }
673     else
674       myCurve->D1(U, P, V);
675     break;
676   }
677
678   case GeomAbs_OffsetCurve:
679     myNestedEvaluator->D1(U, P, V);
680     break;
681
682   default:
683     myCurve->D1(U, P, V);
684   }
685 }
686
687 //=======================================================================
688 //function : D2
689 //purpose  : 
690 //=======================================================================
691
692 void GeomAdaptor_Curve::D2(const Standard_Real U, 
693                            gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const 
694 {
695   switch (myTypeCurve)
696   {
697   case GeomAbs_BezierCurve:
698   case GeomAbs_BSplineCurve:
699   {
700     Standard_Integer aStart = 0, aFinish = 0;
701     if (IsBoundary(U, aStart, aFinish))
702     {
703       Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
704       aBspl->LocalD2(U, aStart, aFinish, P, V1, V2);
705     }
706     else if (!myCurveCache.IsNull()) // use cached data
707     {
708       if (!myCurveCache->IsCacheValid(U))
709         RebuildCache(U);
710       myCurveCache->D2(U, P, V1, V2);
711     }
712     else
713       myCurve->D2(U, P, V1, V2);
714     break;
715   }
716
717   case GeomAbs_OffsetCurve:
718     myNestedEvaluator->D2(U, P, V1, V2);
719     break;
720
721   default:
722     myCurve->D2(U, P, V1, V2);
723   }
724 }
725
726 //=======================================================================
727 //function : D3
728 //purpose  : 
729 //=======================================================================
730
731 void GeomAdaptor_Curve::D3(const Standard_Real U, 
732                            gp_Pnt& P, gp_Vec& V1, 
733                            gp_Vec& V2, gp_Vec& V3) const 
734 {
735   switch (myTypeCurve)
736   {
737   case GeomAbs_BezierCurve:
738   case GeomAbs_BSplineCurve:
739   {
740     Standard_Integer aStart = 0, aFinish = 0;
741     if (IsBoundary(U, aStart, aFinish))
742     {
743       Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
744       aBspl->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
745     }
746     else if (!myCurveCache.IsNull()) // use cached data
747     {
748       if (!myCurveCache->IsCacheValid(U))
749         RebuildCache(U);
750       myCurveCache->D3(U, P, V1, V2, V3);
751     }
752     else
753       myCurve->D3(U, P, V1, V2, V3);
754     break;
755   }
756
757   case GeomAbs_OffsetCurve:
758     myNestedEvaluator->D3(U, P, V1, V2, V3);
759     break;
760
761   default:
762     myCurve->D3(U, P, V1, V2, V3);
763   }
764 }
765
766 //=======================================================================
767 //function : DN
768 //purpose  : 
769 //=======================================================================
770
771 gp_Vec GeomAdaptor_Curve::DN(const Standard_Real    U, 
772                              const Standard_Integer N) const 
773 {
774   switch (myTypeCurve)
775   {
776   case GeomAbs_BezierCurve:
777   case GeomAbs_BSplineCurve:
778   {
779     Standard_Integer aStart = 0, aFinish = 0;
780     if (IsBoundary(U, aStart, aFinish))
781     {
782       Handle(Geom_BSplineCurve) aBspl = Handle(Geom_BSplineCurve)::DownCast(myCurve);
783       return aBspl->LocalDN(U, aStart, aFinish, N);
784     }
785     else
786       return myCurve->DN(U, N);
787     break;
788   }
789
790   case GeomAbs_OffsetCurve:
791     return myNestedEvaluator->DN(U, N);
792     break;
793
794   default: // to eliminate gcc warning
795     break;
796   }
797   return myCurve->DN(U, N);
798 }
799
800 //=======================================================================
801 //function : Resolution
802 //purpose  : 
803 //=======================================================================
804
805 Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
806 {
807   switch ( myTypeCurve) {
808   case GeomAbs_Line :
809     return R3D;
810   case GeomAbs_Circle: {
811     Standard_Real R = Handle(Geom_Circle)::DownCast (myCurve)->Circ().Radius();
812     if ( R > R3D/2. )
813       return 2*ASin(R3D/(2*R));
814     else
815       return 2*M_PI;
816   }
817   case GeomAbs_Ellipse: {
818     return R3D / Handle(Geom_Ellipse)::DownCast (myCurve)->MajorRadius();
819   }
820   case GeomAbs_BezierCurve: {
821     Standard_Real res;
822     Handle(Geom_BezierCurve)::DownCast (myCurve)->Resolution(R3D,res);
823     return res;
824   }
825   case GeomAbs_BSplineCurve: {
826     Standard_Real res;
827     Handle(Geom_BSplineCurve)::DownCast (myCurve)->Resolution(R3D,res);
828     return res;
829   }
830   default:
831     return Precision::Parametric(R3D);
832   }  
833 }
834
835
836 //    --
837 //    --     The following methods must  be called when GetType returned
838 //    --     the corresponding type.
839 //    --     
840
841 //=======================================================================
842 //function : Line
843 //purpose  : 
844 //=======================================================================
845
846 gp_Lin GeomAdaptor_Curve::Line() const 
847 {
848   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
849   return Handle(Geom_Line)::DownCast (myCurve)->Lin();  
850 }
851
852 //=======================================================================
853 //function : Circle
854 //purpose  : 
855 //=======================================================================
856
857 gp_Circ  GeomAdaptor_Curve::Circle() const 
858 {
859   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
860   return Handle(Geom_Circle)::DownCast (myCurve)->Circ();
861 }
862
863 //=======================================================================
864 //function : Ellipse
865 //purpose  : 
866 //=======================================================================
867
868 gp_Elips GeomAdaptor_Curve::Ellipse() const 
869 {
870   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
871   return Handle(Geom_Ellipse)::DownCast (myCurve)->Elips();
872 }
873
874 //=======================================================================
875 //function : Hyperbola
876 //purpose  : 
877 //=======================================================================
878
879 gp_Hypr GeomAdaptor_Curve::Hyperbola() const 
880 {
881   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
882   return Handle(Geom_Hyperbola)::DownCast (myCurve)->Hypr();  
883 }
884
885 //=======================================================================
886 //function : Parabola
887 //purpose  : 
888 //=======================================================================
889
890 gp_Parab GeomAdaptor_Curve::Parabola() const 
891 {
892   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
893   return Handle(Geom_Parabola)::DownCast (myCurve)->Parab();
894 }
895
896 //=======================================================================
897 //function : Degree
898 //purpose  : 
899 //=======================================================================
900
901 Standard_Integer GeomAdaptor_Curve::Degree() const
902 {
903   if (myTypeCurve == GeomAbs_BezierCurve)
904     return Handle(Geom_BezierCurve)::DownCast (myCurve)->Degree();
905   else if (myTypeCurve == GeomAbs_BSplineCurve)
906     return Handle(Geom_BSplineCurve)::DownCast (myCurve)->Degree();
907   else
908     Standard_NoSuchObject::Raise();
909   // portage WNT 
910   return 0;
911 }
912
913 //=======================================================================
914 //function : IsRational
915 //purpose  : 
916 //=======================================================================
917
918 Standard_Boolean GeomAdaptor_Curve::IsRational() const {
919   switch( myTypeCurve) {
920   case GeomAbs_BSplineCurve:
921     return Handle(Geom_BSplineCurve)::DownCast (myCurve)->IsRational();
922   case GeomAbs_BezierCurve:
923     return Handle(Geom_BezierCurve)::DownCast (myCurve)->IsRational();
924   default:
925     return Standard_False;
926   }
927 }
928
929 //=======================================================================
930 //function : NbPoles
931 //purpose  : 
932 //=======================================================================
933
934 Standard_Integer GeomAdaptor_Curve::NbPoles() const
935 {
936   if (myTypeCurve == GeomAbs_BezierCurve)
937     return Handle(Geom_BezierCurve)::DownCast (myCurve)->NbPoles();
938   else if (myTypeCurve == GeomAbs_BSplineCurve)
939     return Handle(Geom_BSplineCurve)::DownCast (myCurve)->NbPoles();
940   else
941     Standard_NoSuchObject::Raise();
942   // portage WNT
943   return 0;
944 }
945
946 //=======================================================================
947 //function : NbKnots
948 //purpose  : 
949 //=======================================================================
950
951 Standard_Integer GeomAdaptor_Curve::NbKnots() const
952 {
953   if ( myTypeCurve != GeomAbs_BSplineCurve)
954     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::NbKnots");
955   return Handle(Geom_BSplineCurve)::DownCast (myCurve)->NbKnots();
956 }
957
958 //=======================================================================
959 //function : Bezier
960 //purpose  : 
961 //=======================================================================
962
963 Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const 
964 {
965  if ( myTypeCurve != GeomAbs_BezierCurve)
966     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Bezier");
967   return Handle(Geom_BezierCurve)::DownCast (myCurve);
968 }
969
970 //=======================================================================
971 //function : BSpline
972 //purpose  : 
973 //=======================================================================
974
975 Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const 
976 {
977  if ( myTypeCurve != GeomAbs_BSplineCurve)
978     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::BSpline");
979
980   return Handle(Geom_BSplineCurve)::DownCast (myCurve);
981 }