0026949: Geom(2d)Adaptor_Curve/Surface should not do down casts in evaluation
[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   Standard_Integer Nb = myBSplineCurve->NbKnots();
81   Standard_Integer Index1 = 0;
82   Standard_Integer Index2 = 0;
83   Standard_Real newFirst, newLast;
84   TColStd_Array1OfReal    TK(1,Nb);
85   TColStd_Array1OfInteger TM(1,Nb);
86   myBSplineCurve->Knots(TK);
87   myBSplineCurve->Multiplicities(TM);
88   BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U1,myBSplineCurve->IsPeriodic(),
89                             1,Nb,Index1,newFirst);
90   BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U2,myBSplineCurve->IsPeriodic(),
91                             1,Nb,Index2,newLast);
92   if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) { 
93     if (Index1 < Nb) Index1++;
94   }
95   if ( Abs(newLast-TK(Index2))<Precision::PConfusion())
96     Index2--;
97   Standard_Integer MultMax;
98   // attention aux courbes peridiques.
99   if ( (myBSplineCurve->IsPeriodic()) && (Index1 == Nb) )
100     Index1 = 1;
101
102   if ( Index2 - Index1 <= 0) {
103     MultMax = 100;  // CN entre 2 Noeuds consecutifs
104   }
105   else {
106     MultMax = TM(Index1+1);
107     for(Standard_Integer i = Index1+1;i<=Index2;i++) {
108       if ( TM(i)>MultMax) MultMax=TM(i);
109     }
110     MultMax = myBSplineCurve->Degree() - MultMax;
111   }
112   if ( MultMax <= 0) {
113     return GeomAbs_C0;
114   }
115   else if ( MultMax == 1) {
116     return GeomAbs_C1;
117   } 
118   else if ( MultMax == 2) {
119     return GeomAbs_C2;
120   }
121   else if ( MultMax == 3) {
122     return GeomAbs_C3;
123   }
124   else { 
125     return GeomAbs_CN;
126   }
127 }
128
129
130 //=======================================================================
131 //function : Load
132 //purpose  : 
133 //=======================================================================
134
135 void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
136                              const Standard_Real UFirst,
137                              const Standard_Real ULast)
138 {
139   myFirst = UFirst;
140   myLast  = ULast;
141
142   if ( myCurve != C) {
143     myCurve = C;
144     myCurveCache.Nullify();
145     myNestedEvaluator.Nullify();
146     myBSplineCurve.Nullify();
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       myBSplineCurve = aBspl;
181       myCurveCache = new BSplCLib_Cache(aBspl->Degree(), aBspl->IsPeriodic(),
182           aBspl->KnotSequence(), aBspl->Poles(), aBspl->Weights());
183     }
184     else if ( TheType == STANDARD_TYPE(Geom_OffsetCurve)) {
185       myTypeCurve = GeomAbs_OffsetCurve;
186       Handle(Geom_OffsetCurve) anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(myCurve);
187       // Create nested adaptor for base curve
188       Handle(Geom_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
189       Handle(GeomAdaptor_HCurve) aBaseAdaptor = new GeomAdaptor_HCurve(aBaseCurve);
190       myNestedEvaluator = new GeomEvaluator_OffsetCurve(
191           aBaseAdaptor, anOffsetCurve->Offset(), anOffsetCurve->Direction());
192     }
193     else {
194       myTypeCurve = GeomAbs_OtherCurve;
195     }
196   }
197 }  
198
199 //    --
200 //    --     Global methods - Apply to the whole curve.
201 //    --     
202
203 //=======================================================================
204 //function : Continuity
205 //purpose  : 
206 //=======================================================================
207
208 GeomAbs_Shape GeomAdaptor_Curve::Continuity() const 
209 {
210   if (myTypeCurve == GeomAbs_BSplineCurve)
211     return LocalContinuity(myFirst, myLast);
212
213   if (myTypeCurve == GeomAbs_OffsetCurve)
214   {
215     const GeomAbs_Shape S =
216       Handle(Geom_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
217     switch(S)
218     {
219       case GeomAbs_CN: return GeomAbs_CN;
220       case GeomAbs_C3: return GeomAbs_C2;
221       case GeomAbs_C2: return GeomAbs_C1;
222       case GeomAbs_C1: return GeomAbs_C0; 
223       case GeomAbs_G1: return GeomAbs_G1;
224       case GeomAbs_G2: return GeomAbs_G2;
225       default:
226         Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Continuity");
227     }
228   }
229   else if (myTypeCurve == GeomAbs_OtherCurve) {
230     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Contunuity");
231   }
232
233   return GeomAbs_CN;
234 }
235
236 //=======================================================================
237 //function : NbIntervals
238 //purpose  : 
239 //=======================================================================
240
241 Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
242 {
243   Standard_Integer myNbIntervals = 1;
244   Standard_Integer NbSplit;
245   if (myTypeCurve == GeomAbs_BSplineCurve) {
246     Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
247     Standard_Integer LastIndex  = myBSplineCurve->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 = myBSplineCurve->Degree();
268           Standard_Integer Degree = myBSplineCurve->Degree();
269           Standard_Integer NbKnots = myBSplineCurve->NbKnots();
270           TColStd_Array1OfInteger Mults (1, NbKnots);
271           myBSplineCurve->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 = myBSplineCurve->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           myBSplineCurve->Knots(TK);
297           myBSplineCurve->Multiplicities(TM);
298           BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
299                                     myBSplineCurve->IsPeriodic(),
300                                     1,Nb,Index1,newFirst);
301           BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
302                                     myBSplineCurve->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       Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
368       Standard_Integer LastIndex  = myBSplineCurve->LastUKnotIndex();
369       TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
370       
371       if ( S > Continuity()) {
372         Standard_Integer Cont;
373         switch ( S) {
374         case GeomAbs_G1:
375         case GeomAbs_G2:
376           Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
377           break;
378         case GeomAbs_C0:
379           myNbIntervals = 1;
380           break;
381         case GeomAbs_C1:
382         case GeomAbs_C2:
383         case GeomAbs_C3: 
384         case GeomAbs_CN: 
385           {
386             if      ( S == GeomAbs_C1) Cont = 1;
387             else if ( S == GeomAbs_C2) Cont = 2;
388             else if ( S == GeomAbs_C3) Cont = 3;
389             else                       Cont = myBSplineCurve->Degree();
390             Standard_Integer Degree = myBSplineCurve->Degree();
391             Standard_Integer NbKnots = myBSplineCurve->NbKnots();
392             TColStd_Array1OfInteger Mults (1, NbKnots);
393             myBSplineCurve->Multiplicities (Mults);
394             NbSplit = 1;
395             Standard_Integer Index   = FirstIndex;
396             Inter (NbSplit) = Index;
397             Index++;
398             NbSplit++;
399             while (Index < LastIndex) 
400               {
401                 if (Degree - Mults (Index) < Cont) 
402                   {
403                     Inter (NbSplit) = Index;
404                     NbSplit++;
405                   }
406                 Index++;
407               }
408             Inter (NbSplit) = Index;
409             Standard_Integer NbInt = NbSplit-1;
410             //        GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
411             //        Standard_Integer NbInt = Convector.NbSplits()-1;
412             //        TColStd_Array1OfInteger Inter(1,NbInt+1);
413             //        Convector.Splitting( Inter);
414             
415             Standard_Integer Nb = myBSplineCurve->NbKnots();
416             Standard_Integer Index1 = 0;
417             Standard_Integer Index2 = 0;
418             Standard_Real newFirst, newLast;
419             TColStd_Array1OfReal    TK(1,Nb);
420             TColStd_Array1OfInteger TM(1,Nb);
421             myBSplineCurve->Knots(TK);
422             myBSplineCurve->Multiplicities(TM);
423             BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
424                                       myBSplineCurve->IsPeriodic(),
425                                       1,Nb,Index1,newFirst);
426             BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
427                                       myBSplineCurve->IsPeriodic(),
428                                       1,Nb,Index2,newLast);
429             FirstParam = newFirst;
430             LastParam = newLast;
431             // On decale eventuellement les indices  
432             // On utilise une "petite" tolerance, la resolution ne doit 
433             // servir que pour les tres longue courbes....(PRO9248)
434             Standard_Real Eps = Min(Resolution(Precision::Confusion()),
435                                     Precision::PConfusion()); 
436             if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
437             if ( newLast-TK(Index2)> Eps) Index2++;
438             
439             Inter( 1) = Index1;
440             myNbIntervals = 1;
441             for ( Standard_Integer i=1; i<=NbInt; i++) {
442               if (Inter(i) > Index1 && Inter(i)<Index2 ) {
443                 myNbIntervals++;
444                 Inter(myNbIntervals) = Inter(i);
445               }
446             }
447             Inter(myNbIntervals+1) = Index2;
448             
449             for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
450               T(I) = TK(Inter(I));
451             }
452           }
453           break;
454         }
455       }
456     }
457
458   else if (myTypeCurve == GeomAbs_OffsetCurve){
459     GeomAbs_Shape BaseS=GeomAbs_C0;
460     switch(S){
461     case GeomAbs_G1:
462     case GeomAbs_G2:
463       Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
464       break;
465     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
466     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
467     case GeomAbs_C2: BaseS = GeomAbs_C3; break;
468     default: BaseS = GeomAbs_CN;
469     }
470     GeomAdaptor_Curve C
471       (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
472     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
473     //                    the array of intervals obtained from the basis to
474     //              vvv   reflect parameter bounds
475     Standard_Integer iNbBasisInt = C.NbIntervals(BaseS), iInt;
476     if (iNbBasisInt>1)
477     {
478       TColStd_Array1OfReal rdfInter(1,1+iNbBasisInt);
479       C.Intervals(rdfInter,BaseS);
480       for (iInt=1; iInt<=iNbBasisInt; iInt++)
481         if (rdfInter(iInt)>myFirst && rdfInter(iInt)<myLast)
482           T(++myNbIntervals)=rdfInter(iInt);
483     }
484     // old - myNbIntervals = C.NbIntervals(BaseS);
485     // old - C.Intervals(T, BaseS);
486     // akm 05/04/02 ^^^
487   }
488   
489   T( T.Lower() ) = FirstParam;
490   T( T.Lower() + myNbIntervals ) = LastParam;
491 }
492
493 //=======================================================================
494 //function : Trim
495 //purpose  : 
496 //=======================================================================
497
498 Handle(Adaptor3d_HCurve) GeomAdaptor_Curve::Trim(const Standard_Real First,
499                                                  const Standard_Real Last,
500                                                  const Standard_Real /*Tol*/) const
501 {
502   return Handle(GeomAdaptor_HCurve)(new GeomAdaptor_HCurve(myCurve,First,Last));
503 }
504
505
506 //=======================================================================
507 //function : IsClosed
508 //purpose  : 
509 //=======================================================================
510
511 Standard_Boolean GeomAdaptor_Curve::IsClosed() const
512 {
513   if (!Precision::IsPositiveInfinite(myLast) &&
514       !Precision::IsNegativeInfinite(myFirst))
515   {
516     const gp_Pnt Pd = Value(myFirst);
517     const gp_Pnt Pf = Value(myLast);
518     return (Pd.Distance(Pf) <= Precision::Confusion());
519   }
520   return Standard_False;
521 }
522
523 //=======================================================================
524 //function : IsPeriodic
525 //purpose  : 
526 //=======================================================================
527
528 Standard_Boolean GeomAdaptor_Curve::IsPeriodic() const 
529 {
530   return (myCurve->IsPeriodic()? IsClosed() : Standard_False);
531 }
532
533 //=======================================================================
534 //function : Period
535 //purpose  : 
536 //=======================================================================
537
538 Standard_Real GeomAdaptor_Curve::Period() const 
539 {
540   return myCurve->LastParameter() - myCurve->FirstParameter();
541 }
542
543 //=======================================================================
544 //function : RebuildCache
545 //purpose  : 
546 //=======================================================================
547 void GeomAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
548 {
549   if (myTypeCurve == GeomAbs_BezierCurve)
550   {
551     Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
552     Standard_Integer aDeg = aBezier->Degree();
553     TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
554     myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
555         aBezier->Poles(), aBezier->Weights());
556   }
557   else if (myTypeCurve == GeomAbs_BSplineCurve)
558   {
559     myCurveCache->BuildCache(theParameter, myBSplineCurve->Degree(),
560         myBSplineCurve->IsPeriodic(), myBSplineCurve->KnotSequence(),
561         myBSplineCurve->Poles(), myBSplineCurve->Weights());
562   }
563 }
564
565 //=======================================================================
566 //function : IsBoundary
567 //purpose  : 
568 //=======================================================================
569 Standard_Boolean GeomAdaptor_Curve::IsBoundary(const Standard_Real theU,
570                                                Standard_Integer& theSpanStart,
571                                                Standard_Integer& theSpanFinish) const
572 {
573   if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
574   {
575     if (theU == myFirst)
576     {
577       myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
578       if (theSpanStart < 1)
579         theSpanStart = 1;
580       if (theSpanStart >= theSpanFinish)
581         theSpanFinish = theSpanStart + 1;
582     }
583     else if (theU == myLast)
584     {
585       myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
586       if (theSpanFinish > myBSplineCurve->NbKnots())
587         theSpanFinish = myBSplineCurve->NbKnots();
588       if (theSpanStart >= theSpanFinish)
589         theSpanStart = theSpanFinish - 1;
590     }
591     return Standard_True;
592   }
593   return Standard_False;
594 }
595
596 //=======================================================================
597 //function : Value
598 //purpose  : 
599 //=======================================================================
600
601 gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
602 {
603   gp_Pnt aValue;
604   D0(U, aValue);
605   return aValue;
606 }
607
608 //=======================================================================
609 //function : D0
610 //purpose  : 
611 //=======================================================================
612
613 void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
614 {
615   switch (myTypeCurve)
616   {
617   case GeomAbs_BezierCurve:
618   case GeomAbs_BSplineCurve:
619   {
620     Standard_Integer aStart = 0, aFinish = 0;
621     if (IsBoundary(U, aStart, aFinish))
622     {
623       myBSplineCurve->LocalD0(U, aStart, aFinish, P);
624     }
625     else if (!myCurveCache.IsNull()) // use cached data
626     {
627       if (!myCurveCache->IsCacheValid(U))
628         RebuildCache(U);
629       myCurveCache->D0(U, P);
630     }
631     else
632       myCurve->D0(U, P);
633     break;
634   }
635
636   case GeomAbs_OffsetCurve:
637     myNestedEvaluator->D0(U, P);
638     break;
639
640   default:
641     myCurve->D0(U, P);
642   }
643 }
644
645 //=======================================================================
646 //function : D1
647 //purpose  : 
648 //=======================================================================
649
650 void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const 
651 {
652   switch (myTypeCurve)
653   {
654   case GeomAbs_BezierCurve:
655   case GeomAbs_BSplineCurve:
656   {
657     Standard_Integer aStart = 0, aFinish = 0;
658     if (IsBoundary(U, aStart, aFinish))
659     {
660       myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
661     }
662     else if (!myCurveCache.IsNull()) // use cached data
663     {
664       if (!myCurveCache->IsCacheValid(U))
665         RebuildCache(U);
666       myCurveCache->D1(U, P, V);
667     }
668     else
669       myCurve->D1(U, P, V);
670     break;
671   }
672
673   case GeomAbs_OffsetCurve:
674     myNestedEvaluator->D1(U, P, V);
675     break;
676
677   default:
678     myCurve->D1(U, P, V);
679   }
680 }
681
682 //=======================================================================
683 //function : D2
684 //purpose  : 
685 //=======================================================================
686
687 void GeomAdaptor_Curve::D2(const Standard_Real U, 
688                            gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const 
689 {
690   switch (myTypeCurve)
691   {
692   case GeomAbs_BezierCurve:
693   case GeomAbs_BSplineCurve:
694   {
695     Standard_Integer aStart = 0, aFinish = 0;
696     if (IsBoundary(U, aStart, aFinish))
697     {
698       myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
699     }
700     else if (!myCurveCache.IsNull()) // use cached data
701     {
702       if (!myCurveCache->IsCacheValid(U))
703         RebuildCache(U);
704       myCurveCache->D2(U, P, V1, V2);
705     }
706     else
707       myCurve->D2(U, P, V1, V2);
708     break;
709   }
710
711   case GeomAbs_OffsetCurve:
712     myNestedEvaluator->D2(U, P, V1, V2);
713     break;
714
715   default:
716     myCurve->D2(U, P, V1, V2);
717   }
718 }
719
720 //=======================================================================
721 //function : D3
722 //purpose  : 
723 //=======================================================================
724
725 void GeomAdaptor_Curve::D3(const Standard_Real U, 
726                            gp_Pnt& P, gp_Vec& V1, 
727                            gp_Vec& V2, gp_Vec& V3) const 
728 {
729   switch (myTypeCurve)
730   {
731   case GeomAbs_BezierCurve:
732   case GeomAbs_BSplineCurve:
733   {
734     Standard_Integer aStart = 0, aFinish = 0;
735     if (IsBoundary(U, aStart, aFinish))
736     {
737       myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
738     }
739     else if (!myCurveCache.IsNull()) // use cached data
740     {
741       if (!myCurveCache->IsCacheValid(U))
742         RebuildCache(U);
743       myCurveCache->D3(U, P, V1, V2, V3);
744     }
745     else
746       myCurve->D3(U, P, V1, V2, V3);
747     break;
748   }
749
750   case GeomAbs_OffsetCurve:
751     myNestedEvaluator->D3(U, P, V1, V2, V3);
752     break;
753
754   default:
755     myCurve->D3(U, P, V1, V2, V3);
756   }
757 }
758
759 //=======================================================================
760 //function : DN
761 //purpose  : 
762 //=======================================================================
763
764 gp_Vec GeomAdaptor_Curve::DN(const Standard_Real    U, 
765                              const Standard_Integer N) const 
766 {
767   switch (myTypeCurve)
768   {
769   case GeomAbs_BezierCurve:
770   case GeomAbs_BSplineCurve:
771   {
772     Standard_Integer aStart = 0, aFinish = 0;
773     if (IsBoundary(U, aStart, aFinish))
774     {
775       return myBSplineCurve->LocalDN(U, aStart, aFinish, N);
776     }
777     else
778       return myCurve->DN(U, N);
779     break;
780   }
781
782   case GeomAbs_OffsetCurve:
783     return myNestedEvaluator->DN(U, N);
784     break;
785
786   default: // to eliminate gcc warning
787     break;
788   }
789   return myCurve->DN(U, N);
790 }
791
792 //=======================================================================
793 //function : Resolution
794 //purpose  : 
795 //=======================================================================
796
797 Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
798 {
799   switch ( myTypeCurve) {
800   case GeomAbs_Line :
801     return R3D;
802   case GeomAbs_Circle: {
803     Standard_Real R = Handle(Geom_Circle)::DownCast (myCurve)->Circ().Radius();
804     if ( R > R3D/2. )
805       return 2*ASin(R3D/(2*R));
806     else
807       return 2*M_PI;
808   }
809   case GeomAbs_Ellipse: {
810     return R3D / Handle(Geom_Ellipse)::DownCast (myCurve)->MajorRadius();
811   }
812   case GeomAbs_BezierCurve: {
813     Standard_Real res;
814     Handle(Geom_BezierCurve)::DownCast (myCurve)->Resolution(R3D,res);
815     return res;
816   }
817   case GeomAbs_BSplineCurve: {
818     Standard_Real res;
819     myBSplineCurve->Resolution(R3D,res);
820     return res;
821   }
822   default:
823     return Precision::Parametric(R3D);
824   }  
825 }
826
827
828 //    --
829 //    --     The following methods must  be called when GetType returned
830 //    --     the corresponding type.
831 //    --     
832
833 //=======================================================================
834 //function : Line
835 //purpose  : 
836 //=======================================================================
837
838 gp_Lin GeomAdaptor_Curve::Line() const 
839 {
840   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
841   return Handle(Geom_Line)::DownCast (myCurve)->Lin();  
842 }
843
844 //=======================================================================
845 //function : Circle
846 //purpose  : 
847 //=======================================================================
848
849 gp_Circ  GeomAdaptor_Curve::Circle() const 
850 {
851   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
852   return Handle(Geom_Circle)::DownCast (myCurve)->Circ();
853 }
854
855 //=======================================================================
856 //function : Ellipse
857 //purpose  : 
858 //=======================================================================
859
860 gp_Elips GeomAdaptor_Curve::Ellipse() const 
861 {
862   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
863   return Handle(Geom_Ellipse)::DownCast (myCurve)->Elips();
864 }
865
866 //=======================================================================
867 //function : Hyperbola
868 //purpose  : 
869 //=======================================================================
870
871 gp_Hypr GeomAdaptor_Curve::Hyperbola() const 
872 {
873   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
874   return Handle(Geom_Hyperbola)::DownCast (myCurve)->Hypr();  
875 }
876
877 //=======================================================================
878 //function : Parabola
879 //purpose  : 
880 //=======================================================================
881
882 gp_Parab GeomAdaptor_Curve::Parabola() const 
883 {
884   Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
885   return Handle(Geom_Parabola)::DownCast (myCurve)->Parab();
886 }
887
888 //=======================================================================
889 //function : Degree
890 //purpose  : 
891 //=======================================================================
892
893 Standard_Integer GeomAdaptor_Curve::Degree() const
894 {
895   if (myTypeCurve == GeomAbs_BezierCurve)
896     return Handle(Geom_BezierCurve)::DownCast (myCurve)->Degree();
897   else if (myTypeCurve == GeomAbs_BSplineCurve)
898     return myBSplineCurve->Degree();
899   else
900     Standard_NoSuchObject::Raise();
901   // portage WNT 
902   return 0;
903 }
904
905 //=======================================================================
906 //function : IsRational
907 //purpose  : 
908 //=======================================================================
909
910 Standard_Boolean GeomAdaptor_Curve::IsRational() const {
911   switch( myTypeCurve) {
912   case GeomAbs_BSplineCurve:
913     return myBSplineCurve->IsRational();
914   case GeomAbs_BezierCurve:
915     return Handle(Geom_BezierCurve)::DownCast (myCurve)->IsRational();
916   default:
917     return Standard_False;
918   }
919 }
920
921 //=======================================================================
922 //function : NbPoles
923 //purpose  : 
924 //=======================================================================
925
926 Standard_Integer GeomAdaptor_Curve::NbPoles() const
927 {
928   if (myTypeCurve == GeomAbs_BezierCurve)
929     return Handle(Geom_BezierCurve)::DownCast (myCurve)->NbPoles();
930   else if (myTypeCurve == GeomAbs_BSplineCurve)
931     return myBSplineCurve->NbPoles();
932   else
933     Standard_NoSuchObject::Raise();
934   // portage WNT
935   return 0;
936 }
937
938 //=======================================================================
939 //function : NbKnots
940 //purpose  : 
941 //=======================================================================
942
943 Standard_Integer GeomAdaptor_Curve::NbKnots() const
944 {
945   if ( myTypeCurve != GeomAbs_BSplineCurve)
946     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::NbKnots");
947   return myBSplineCurve->NbKnots();
948 }
949
950 //=======================================================================
951 //function : Bezier
952 //purpose  : 
953 //=======================================================================
954
955 Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const 
956 {
957  if ( myTypeCurve != GeomAbs_BezierCurve)
958     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Bezier");
959   return Handle(Geom_BezierCurve)::DownCast (myCurve);
960 }
961
962 //=======================================================================
963 //function : BSpline
964 //purpose  : 
965 //=======================================================================
966
967 Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const 
968 {
969  if ( myTypeCurve != GeomAbs_BSplineCurve)
970     Standard_NoSuchObject::Raise("GeomAdaptor_Curve::BSpline");
971
972   return myBSplineCurve;
973 }