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