0028724: Extrema between circle and plane cannot be found
[occt.git] / src / GeomAdaptor / GeomAdaptor_Curve.cxx
old mode 100755 (executable)
new mode 100644 (file)
index b4f4a76..112a3eb
@@ -1,23 +1,18 @@
 // Created on: 1993-04-29
 // Created by: Bruno DUMORTIER
 // Copyright (c) 1993-1999 Matra Datavision
-// Copyright (c) 1999-2012 OPEN CASCADE SAS
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 // 20/02/97 : PMN -> Positionement local sur BSpline (PRO6902)
 // 10/07/97 : PMN -> Pas de calcul de resolution dans Nb(Intervals)(PRO9248)
 #define No_Standard_RangeError
 #define No_Standard_OutOfRange
 
-#include <GeomAdaptor_Curve.ixx>
 
-#include <GeomAdaptor_HCurve.hxx>
 #include <Adaptor3d_HCurve.hxx>
 #include <BSplCLib.hxx>
-#include <GeomAbs_Shape.hxx>
-#include <TColgp_Array1OfPnt.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TColStd_Array1OfInteger.hxx>
-#include <TColStd_HArray1OfInteger.hxx>
-#include <Precision.hxx>
-#include <Geom_TrimmedCurve.hxx>
-#include <Geom_Circle.hxx>
-#include <Geom_Line.hxx>
-#include <Geom_TrimmedCurve.hxx>
+#include <BSplCLib_Cache.hxx>
 #include <Geom_BezierCurve.hxx>
 #include <Geom_BSplineCurve.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_Curve.hxx>
 #include <Geom_Ellipse.hxx>
-#include <Geom_Parabola.hxx>
 #include <Geom_Hyperbola.hxx>
-//#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
-
-#include <Standard_OutOfRange.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_OffsetCurve.hxx>
+#include <Geom_Parabola.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <GeomAbs_Shape.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GeomAdaptor_HCurve.hxx>
+#include <GeomAdaptor_Surface.hxx>
+#include <GeomEvaluator_OffsetCurve.hxx>
+#include <gp_Circ.hxx>
+#include <gp_Elips.hxx>
+#include <gp_Hypr.hxx>
+#include <gp_Lin.hxx>
+#include <gp_Parab.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <Precision.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <Standard_DomainError.hxx>
 #include <Standard_NoSuchObject.hxx>
-#include <Standard_NullObject.hxx>
 #include <Standard_NotImplemented.hxx>
-#include <Geom_OffsetCurve.hxx>
+#include <Standard_NullObject.hxx>
+#include <Standard_OutOfRange.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_HArray1OfInteger.hxx>
+
+//#include <GeomConvert_BSplineCurveKnotSplitting.hxx>
+static const Standard_Real PosTol = Precision::PConfusion() / 2;
 
-#define myBspl (*((Handle(Geom_BSplineCurve)*)&myCurve))
-#define PosTol Precision::PConfusion()/2
 
 //=======================================================================
 //function : LocalContinuity
@@ -71,17 +77,15 @@ GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1,
      const 
 {
   Standard_NoSuchObject_Raise_if(myTypeCurve!=GeomAbs_BSplineCurve," ");
-  Standard_Integer Nb = myBspl->NbKnots();
+  Standard_Integer Nb = myBSplineCurve->NbKnots();
   Standard_Integer Index1 = 0;
   Standard_Integer Index2 = 0;
   Standard_Real newFirst, newLast;
-  TColStd_Array1OfReal    TK(1,Nb);
-  TColStd_Array1OfInteger TM(1,Nb);
-  myBspl->Knots(TK);
-  myBspl->Multiplicities(TM);
-  BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U1,myBspl->IsPeriodic(),
+  const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
+  const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
+  BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U1,myBSplineCurve->IsPeriodic(),
                            1,Nb,Index1,newFirst);
-  BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,U2,myBspl->IsPeriodic(),
+  BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,U2,myBSplineCurve->IsPeriodic(),
                            1,Nb,Index2,newLast);
   if ( Abs(newFirst-TK(Index1+1))<Precision::PConfusion()) { 
     if (Index1 < Nb) Index1++;
@@ -90,7 +94,7 @@ GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1,
     Index2--;
   Standard_Integer MultMax;
   // attention aux courbes peridiques.
-  if ( (myBspl->IsPeriodic()) && (Index1 == Nb) )
+  if ( (myBSplineCurve->IsPeriodic()) && (Index1 == Nb) )
     Index1 = 1;
 
   if ( Index2 - Index1 <= 0) {
@@ -101,7 +105,7 @@ GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1,
     for(Standard_Integer i = Index1+1;i<=Index2;i++) {
       if ( TM(i)>MultMax) MultMax=TM(i);
     }
-    MultMax = myBspl->Degree() - MultMax;
+    MultMax = myBSplineCurve->Degree() - MultMax;
   }
   if ( MultMax <= 0) {
     return GeomAbs_C0;
@@ -132,13 +136,16 @@ void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
 {
   myFirst = UFirst;
   myLast  = ULast;
+  myCurveCache.Nullify();
 
   if ( myCurve != C) {
     myCurve = C;
+    myNestedEvaluator.Nullify();
+    myBSplineCurve.Nullify();
     
     const Handle(Standard_Type)& TheType = C->DynamicType();
     if ( TheType == STANDARD_TYPE(Geom_TrimmedCurve)) {
-      Load((*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve(),UFirst,ULast);
+      Load(Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve(),UFirst,ULast);
     }
     else if ( TheType ==  STANDARD_TYPE(Geom_Circle)) {
       myTypeCurve = GeomAbs_Circle;
@@ -160,12 +167,22 @@ void GeomAdaptor_Curve::load(const Handle(Geom_Curve)& C,
     }
     else if ( TheType == STANDARD_TYPE(Geom_BSplineCurve)) {
       myTypeCurve = GeomAbs_BSplineCurve;
+      myBSplineCurve = Handle(Geom_BSplineCurve)::DownCast(myCurve);
+    }
+    else if ( TheType == STANDARD_TYPE(Geom_OffsetCurve)) {
+      myTypeCurve = GeomAbs_OffsetCurve;
+      Handle(Geom_OffsetCurve) anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(myCurve);
+      // Create nested adaptor for base curve
+      Handle(Geom_Curve) aBaseCurve = anOffsetCurve->BasisCurve();
+      Handle(GeomAdaptor_HCurve) aBaseAdaptor = new GeomAdaptor_HCurve(aBaseCurve);
+      myNestedEvaluator = new GeomEvaluator_OffsetCurve(
+          aBaseAdaptor, anOffsetCurve->Offset(), anOffsetCurve->Direction());
     }
     else {
       myTypeCurve = GeomAbs_OtherCurve;
     }
   }
-}  
+}
 
 //    --
 //    --     Global methods - Apply to the whole curve.
@@ -181,22 +198,24 @@ GeomAbs_Shape GeomAdaptor_Curve::Continuity() const
   if (myTypeCurve == GeomAbs_BSplineCurve)
     return LocalContinuity(myFirst, myLast);
 
-  if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
+  if (myTypeCurve == GeomAbs_OffsetCurve)
   {
     const GeomAbs_Shape S =
-      (*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve()->Continuity();
+      Handle(Geom_OffsetCurve)::DownCast (myCurve)->GetBasisCurveContinuity();
     switch(S)
     {
       case GeomAbs_CN: return GeomAbs_CN;
       case GeomAbs_C3: return GeomAbs_C2;
       case GeomAbs_C2: return GeomAbs_C1;
-      case GeomAbs_C1: return GeomAbs_C0;  
+      case GeomAbs_C1: return GeomAbs_C0; 
+      case GeomAbs_G1: return GeomAbs_G1;
+      case GeomAbs_G2: return GeomAbs_G2;
       default:
-      Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Continuity");
+        throw Standard_NoSuchObject("GeomAdaptor_Curve::Continuity");
     }
   }
   else if (myTypeCurve == GeomAbs_OtherCurve) {
-    Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Contunuity");
+    throw Standard_NoSuchObject("GeomAdaptor_Curve::Contunuity");
   }
 
   return GeomAbs_CN;
@@ -207,20 +226,20 @@ GeomAbs_Shape GeomAdaptor_Curve::Continuity() const
 //purpose  : 
 //=======================================================================
 
-Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) 
+Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
 {
   Standard_Integer myNbIntervals = 1;
   Standard_Integer NbSplit;
   if (myTypeCurve == GeomAbs_BSplineCurve) {
-    Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
-    Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
+    Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
+    Standard_Integer LastIndex  = myBSplineCurve->LastUKnotIndex();
     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
     if ( S > Continuity()) {
       Standard_Integer Cont;
       switch ( S) {
       case GeomAbs_G1:
       case GeomAbs_G2:
-        Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
+        throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
         break;
       case GeomAbs_C0:
         myNbIntervals = 1;
@@ -233,13 +252,11 @@ Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S)
           if      ( S == GeomAbs_C1) Cont = 1;
           else if ( S == GeomAbs_C2) Cont = 2;
           else if ( S == GeomAbs_C3) Cont = 3;
-          else                       Cont = myBspl->Degree();
-          Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
-          Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
-          Standard_Integer Degree = myBspl->Degree();
-          Standard_Integer NbKnots = myBspl->NbKnots();
+          else                       Cont = myBSplineCurve->Degree();
+          Standard_Integer Degree = myBSplineCurve->Degree();
+          Standard_Integer NbKnots = myBSplineCurve->NbKnots();
           TColStd_Array1OfInteger Mults (1, NbKnots);
-          myBspl->Multiplicities (Mults);
+          myBSplineCurve->Multiplicities (Mults);
           NbSplit = 1;
           Standard_Integer Index   = FirstIndex;
           Inter (NbSplit) = Index;
@@ -258,19 +275,17 @@ Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S)
 
           Standard_Integer NbInt = NbSplit-1;
           
-          Standard_Integer Nb = myBspl->NbKnots();
+          Standard_Integer Nb = myBSplineCurve->NbKnots();
           Standard_Integer Index1 = 0;
           Standard_Integer Index2 = 0;
           Standard_Real newFirst, newLast;
-          TColStd_Array1OfReal    TK(1,Nb);
-          TColStd_Array1OfInteger TM(1,Nb);
-          myBspl->Knots(TK);
-          myBspl->Multiplicities(TM);
-          BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
-                                    myBspl->IsPeriodic(),
+          const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
+          const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
+          BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
+                                    myBSplineCurve->IsPeriodic(),
                                     1,Nb,Index1,newFirst);
-          BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
-                                   myBspl->IsPeriodic(),
+          BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
+                                    myBSplineCurve->IsPeriodic(),
                                     1,Nb,Index2,newLast);
 
           // On decale eventuellement les indices  
@@ -290,12 +305,12 @@ Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S)
     }
   }
   
-  else if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))){
+  else if (myTypeCurve == GeomAbs_OffsetCurve) {
     GeomAbs_Shape BaseS=GeomAbs_C0;
     switch(S){
     case GeomAbs_G1:
     case GeomAbs_G2:
-      Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
+      throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
       break;
     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
@@ -303,7 +318,7 @@ Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S)
     default: BaseS = GeomAbs_CN;
     }
     GeomAdaptor_Curve C
-      ((*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve());
+      (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
     //                    the number of intervals obtained from the basis to
     //              vvv   reflect parameter bounds
@@ -327,7 +342,7 @@ Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S)
 //=======================================================================
 
 void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
-                                 const GeomAbs_Shape S   )  
+                                  const GeomAbs_Shape S   ) const
 {
   Standard_Integer myNbIntervals = 1;
   Standard_Integer NbSplit;
@@ -335,8 +350,8 @@ void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
 
   if (myTypeCurve == GeomAbs_BSplineCurve) 
     {
-      Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
-      Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
+      Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
+      Standard_Integer LastIndex  = myBSplineCurve->LastUKnotIndex();
       TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
       
       if ( S > Continuity()) {
@@ -344,7 +359,7 @@ void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
        switch ( S) {
        case GeomAbs_G1:
        case GeomAbs_G2:
-         Standard_DomainError::Raise("Geom2dAdaptor_Curve::NbIntervals");
+         throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
          break;
        case GeomAbs_C0:
          myNbIntervals = 1;
@@ -357,13 +372,11 @@ void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
            if      ( S == GeomAbs_C1) Cont = 1;
            else if ( S == GeomAbs_C2) Cont = 2;
            else if ( S == GeomAbs_C3) Cont = 3;
-           else                       Cont = myBspl->Degree();
-           Standard_Integer FirstIndex = myBspl->FirstUKnotIndex();
-           Standard_Integer LastIndex  = myBspl->LastUKnotIndex();
-           Standard_Integer Degree = myBspl->Degree();
-           Standard_Integer NbKnots = myBspl->NbKnots();
+           else                       Cont = myBSplineCurve->Degree();
+           Standard_Integer Degree = myBSplineCurve->Degree();
+           Standard_Integer NbKnots = myBSplineCurve->NbKnots();
            TColStd_Array1OfInteger Mults (1, NbKnots);
-           myBspl->Multiplicities (Mults);
+           myBSplineCurve->Multiplicities (Mults);
            NbSplit = 1;
            Standard_Integer Index   = FirstIndex;
            Inter (NbSplit) = Index;
@@ -385,19 +398,17 @@ void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
            //        TColStd_Array1OfInteger Inter(1,NbInt+1);
            //        Convector.Splitting( Inter);
            
-           Standard_Integer Nb = myBspl->NbKnots();
+           Standard_Integer Nb = myBSplineCurve->NbKnots();
            Standard_Integer Index1 = 0;
            Standard_Integer Index2 = 0;
            Standard_Real newFirst, newLast;
-           TColStd_Array1OfReal    TK(1,Nb);
-           TColStd_Array1OfInteger TM(1,Nb);
-           myBspl->Knots(TK);
-           myBspl->Multiplicities(TM);
-           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myFirst,
-                                     myBspl->IsPeriodic(),
+            const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
+            const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
+           BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
+                                     myBSplineCurve->IsPeriodic(),
                                      1,Nb,Index1,newFirst);
-           BSplCLib::LocateParameter(myBspl->Degree(),TK,TM,myLast,
-                                     myBspl->IsPeriodic(),
+           BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
+                                     myBSplineCurve->IsPeriodic(),
                                      1,Nb,Index2,newLast);
             FirstParam = newFirst;
             LastParam = newLast;
@@ -428,12 +439,12 @@ void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
       }
     }
 
-  else if (myCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve))){
+  else if (myTypeCurve == GeomAbs_OffsetCurve){
     GeomAbs_Shape BaseS=GeomAbs_C0;
     switch(S){
     case GeomAbs_G1:
     case GeomAbs_G2:
-      Standard_DomainError::Raise("GeomAdaptor_Curve::NbIntervals");
+      throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
       break;
     case GeomAbs_C0: BaseS = GeomAbs_C1; break;
     case GeomAbs_C1: BaseS = GeomAbs_C2; break;
@@ -441,7 +452,7 @@ void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
     default: BaseS = GeomAbs_CN;
     }
     GeomAdaptor_Curve C
-      ((*((Handle(Geom_OffsetCurve)*)&myCurve))->BasisCurve());
+      (Handle(Geom_OffsetCurve)::DownCast (myCurve)->BasisCurve());
     // akm 05/04/02 (OCC278)  If our curve is trimmed we must recalculate 
     //                    the array of intervals obtained from the basis to
     //              vvv   reflect parameter bounds
@@ -500,7 +511,7 @@ Standard_Boolean GeomAdaptor_Curve::IsClosed() const
 
 Standard_Boolean GeomAdaptor_Curve::IsPeriodic() const 
 {
-  return (myCurve->IsPeriodic()? IsClosed() : Standard_False);
+  return myCurve->IsPeriodic();
 }
 
 //=======================================================================
@@ -514,28 +525,76 @@ Standard_Real GeomAdaptor_Curve::Period() const
 }
 
 //=======================================================================
-//function : Value
+//function : RebuildCache
 //purpose  : 
 //=======================================================================
+void GeomAdaptor_Curve::RebuildCache(const Standard_Real theParameter) const
+{
+  if (myTypeCurve == GeomAbs_BezierCurve)
+  {
+    // Create cache for Bezier
+    Handle(Geom_BezierCurve) aBezier = Handle(Geom_BezierCurve)::DownCast(myCurve);
+    Standard_Integer aDeg = aBezier->Degree();
+    TColStd_Array1OfReal aFlatKnots(BSplCLib::FlatBezierKnots(aDeg), 1, 2 * (aDeg + 1));
+    if (myCurveCache.IsNull())
+      myCurveCache = new BSplCLib_Cache(aDeg, aBezier->IsPeriodic(), aFlatKnots,
+        aBezier->Poles(), aBezier->Weights());
+    myCurveCache->BuildCache(theParameter, aDeg, aBezier->IsPeriodic(), aFlatKnots,
+        aBezier->Poles(), aBezier->Weights());
+}
+  else if (myTypeCurve == GeomAbs_BSplineCurve)
+{
+    // Create cache for B-spline
+    if (myCurveCache.IsNull())
+      myCurveCache = new BSplCLib_Cache(myBSplineCurve->Degree(), myBSplineCurve->IsPeriodic(),
+        myBSplineCurve->KnotSequence(), myBSplineCurve->Poles(), myBSplineCurve->Weights());
+    myCurveCache->BuildCache(theParameter, myBSplineCurve->Degree(),
+        myBSplineCurve->IsPeriodic(), myBSplineCurve->KnotSequence(),
+        myBSplineCurve->Poles(), myBSplineCurve->Weights());
+}
+}
 
-gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
+//=======================================================================
+//function : IsBoundary
+//purpose  : 
+//=======================================================================
+Standard_Boolean GeomAdaptor_Curve::IsBoundary(const Standard_Real theU,
+                                               Standard_Integer& theSpanStart,
+                                               Standard_Integer& theSpanFinish) const
 {
-  if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
-      (U==myFirst || U==myLast) ) {
-    Standard_Integer Ideb, Ifin;
-    if (U==myFirst) {
-      myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
-      if (Ideb<1) Ideb=1;
-      if (Ideb>=Ifin) Ifin = Ideb+1;
+  if (!myBSplineCurve.IsNull() && (theU == myFirst || theU == myLast))
+  {
+    if (theU == myFirst)
+    {
+      myBSplineCurve->LocateU(myFirst, PosTol, theSpanStart, theSpanFinish);
+      if (theSpanStart < 1)
+        theSpanStart = 1;
+      if (theSpanStart >= theSpanFinish)
+        theSpanFinish = theSpanStart + 1;
     }
-    if (U==myLast) {
-      myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
-      if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
-      if (Ideb>=Ifin) Ideb = Ifin-1;
+    else if (theU == myLast)
+    {
+      myBSplineCurve->LocateU(myLast, PosTol, theSpanStart, theSpanFinish);
+      if (theSpanFinish > myBSplineCurve->NbKnots())
+        theSpanFinish = myBSplineCurve->NbKnots();
+      if (theSpanStart >= theSpanFinish)
+        theSpanStart = theSpanFinish - 1;
     }
-    return myBspl->LocalValue(U, Ideb, Ifin);
+    return Standard_True;
+  }
+  return Standard_False;
   }
-  return myCurve->Value(U);
+
+//=======================================================================
+//function : Value
+//purpose  : 
+//=======================================================================
+
+gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
+{
+  gp_Pnt aValue;
+  D0(U, aValue);
+  return aValue;
 }
 
 //=======================================================================
@@ -545,24 +604,33 @@ gp_Pnt GeomAdaptor_Curve::Value(const Standard_Real U) const
 
 void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
 {
-  if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
-      (U==myFirst || U==myLast) ) {
-    Standard_Integer Ideb, Ifin;
-    if (U==myFirst) {
-      myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
-      if (Ideb<1) Ideb=1;
-      if (Ideb>=Ifin) Ifin = Ideb+1;
-    }
-    if (U==myLast) {
-      myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
-      if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
-      if (Ideb>=Ifin) Ideb = Ifin-1;
+  switch (myTypeCurve)
+{
+  case GeomAbs_BezierCurve:
+  case GeomAbs_BSplineCurve:
+  {
+    Standard_Integer aStart = 0, aFinish = 0;
+    if (IsBoundary(U, aStart, aFinish))
+    {
+      myBSplineCurve->LocalD0(U, aStart, aFinish, P);
     }
-    myBspl->LocalD0( U, Ideb, Ifin, P);
+    else
+  {
+      // use cached data
+      if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
+        RebuildCache(U);
+      myCurveCache->D0(U, P);
   }
-  else {
+    break;
+}
+
+  case GeomAbs_OffsetCurve:
+    myNestedEvaluator->D0(U, P);
+    break;
+
+  default:
     myCurve->D0(U, P);
-  } 
+}
 }
 
 //=======================================================================
@@ -572,24 +640,33 @@ void GeomAdaptor_Curve::D0(const Standard_Real U, gp_Pnt& P) const
 
 void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const 
 {
-  if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
-      (U==myFirst || U==myLast) ) {
-    Standard_Integer Ideb, Ifin;
-    if (U==myFirst) {
-      myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
-      if (Ideb<1) Ideb=1;
-      if (Ideb>=Ifin) Ifin = Ideb+1;
-    }
-    if (U==myLast) {
-      myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
-      if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
-      if (Ideb>=Ifin) Ideb = Ifin-1;
+  switch (myTypeCurve)
+{
+  case GeomAbs_BezierCurve:
+  case GeomAbs_BSplineCurve:
+  {
+    Standard_Integer aStart = 0, aFinish = 0;
+    if (IsBoundary(U, aStart, aFinish))
+    {
+      myBSplineCurve->LocalD1(U, aStart, aFinish, P, V);
     }
-    myBspl->LocalD1( U, Ideb, Ifin, P, V); 
-  } 
-  else {
-    myCurve->D1( U, P, V);
+    else
+  {
+      // use cached data
+      if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
+        RebuildCache(U);
+      myCurveCache->D1(U, P, V);
   }
+    break;
+}
+
+  case GeomAbs_OffsetCurve:
+    myNestedEvaluator->D1(U, P, V);
+    break;
+
+  default:
+    myCurve->D1(U, P, V);
+}
 }
 
 //=======================================================================
@@ -598,26 +675,35 @@ void GeomAdaptor_Curve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V) const
 //=======================================================================
 
 void GeomAdaptor_Curve::D2(const Standard_Real U, 
-                          gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const 
-{
-  if ( (myTypeCurve == GeomAbs_BSplineCurve)&&
-      (U==myFirst || U==myLast) ) {
-    Standard_Integer Ideb, Ifin;
-    if (U==myFirst) {
-      myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
-      if (Ideb<1) Ideb=1;
-      if (Ideb>=Ifin) Ifin = Ideb+1;
-    }
-    if (U==myLast) {
-      myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
-      if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
-      if (Ideb>=Ifin) Ideb = Ifin-1;
+                           gp_Pnt& P, gp_Vec& V1, gp_Vec& V2) const 
+{
+  switch (myTypeCurve)
+{
+  case GeomAbs_BezierCurve:
+  case GeomAbs_BSplineCurve:
+  {
+    Standard_Integer aStart = 0, aFinish = 0;
+    if (IsBoundary(U, aStart, aFinish))
+    {
+      myBSplineCurve->LocalD2(U, aStart, aFinish, P, V1, V2);
     }
-    myBspl->LocalD2( U, Ideb, Ifin, P, V1, V2);         
-  }
-  else {
-    myCurve->D2( U, P, V1, V2);
+    else
+  {
+      // use cached data
+      if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
+        RebuildCache(U);
+      myCurveCache->D2(U, P, V1, V2);
   }
+    break;
+}
+
+  case GeomAbs_OffsetCurve:
+    myNestedEvaluator->D2(U, P, V1, V2);
+    break;
+
+  default:
+    myCurve->D2(U, P, V1, V2);
+}
 }
 
 //=======================================================================
@@ -626,27 +712,36 @@ void GeomAdaptor_Curve::D2(const Standard_Real U,
 //=======================================================================
 
 void GeomAdaptor_Curve::D3(const Standard_Real U, 
-                          gp_Pnt& P, gp_Vec& V1, 
-                          gp_Vec& V2, gp_Vec& V3) const 
-{
-  if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
-      (U==myFirst || U==myLast) ) {
-    Standard_Integer Ideb, Ifin;
-    if (U==myFirst) {
-      myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
-      if (Ideb<1) Ideb=1;
-      if (Ideb>=Ifin) Ifin = Ideb+1;
-    }
-    if (U==myLast) {
-      myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
-      if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
-      if (Ideb>=Ifin) Ideb = Ifin-1;
+                           gp_Pnt& P, gp_Vec& V1, 
+                           gp_Vec& V2, gp_Vec& V3) const 
+{
+  switch (myTypeCurve)
+{
+  case GeomAbs_BezierCurve:
+  case GeomAbs_BSplineCurve:
+  {
+    Standard_Integer aStart = 0, aFinish = 0;
+    if (IsBoundary(U, aStart, aFinish))
+    {
+      myBSplineCurve->LocalD3(U, aStart, aFinish, P, V1, V2, V3);
     }
-    myBspl->LocalD3( U, Ideb, Ifin, P, V1, V2, V3);  
-  }
-  else {
-    myCurve->D3( U, P, V1, V2, V3);
+    else
+  {
+      // use cached data
+      if (myCurveCache.IsNull() || !myCurveCache->IsCacheValid(U))
+        RebuildCache(U);
+      myCurveCache->D3(U, P, V1, V2, V3);
   }
+    break;
+}
+
+  case GeomAbs_OffsetCurve:
+    myNestedEvaluator->D3(U, P, V1, V2, V3);
+    break;
+
+  default:
+    myCurve->D3(U, P, V1, V2, V3);
+}
 }
 
 //=======================================================================
@@ -655,26 +750,31 @@ void GeomAdaptor_Curve::D3(const Standard_Real U,
 //=======================================================================
 
 gp_Vec GeomAdaptor_Curve::DN(const Standard_Real    U, 
-                            const Standard_Integer N) const 
-{
-  if ( (myTypeCurve == GeomAbs_BSplineCurve) &&
-      (U==myFirst || U==myLast) ) {
-    Standard_Integer Ideb, Ifin;
-    if (U==myFirst) {
-      myBspl->LocateU(myFirst, PosTol, Ideb, Ifin);
-      if (Ideb<1) Ideb=1;
-      if (Ideb>=Ifin) Ifin = Ideb+1;
+                             const Standard_Integer N) const 
+{
+  switch (myTypeCurve)
+{
+  case GeomAbs_BezierCurve:
+  case GeomAbs_BSplineCurve:
+  {
+    Standard_Integer aStart = 0, aFinish = 0;
+    if (IsBoundary(U, aStart, aFinish))
+    {
+      return myBSplineCurve->LocalDN(U, aStart, aFinish, N);
     }
-    if (U==myLast) {
-      myBspl->LocateU(myLast, PosTol, Ideb, Ifin);
-      if (Ifin>myBspl->NbKnots()) Ifin = myBspl->NbKnots();
-      if (Ideb>=Ifin) Ideb = Ifin-1;
-    } 
-    return myBspl->LocalDN( U, Ideb, Ifin, N);
-  }  
-  else {
-    return myCurve->DN( U, N);
+    else
+  return myCurve->DN( U, N);
+    break;
+}
+
+  case GeomAbs_OffsetCurve:
+    return myNestedEvaluator->DN(U, N);
+    break;
+
+  default: // to eliminate gcc warning
+    break;
   }
+  return myCurve->DN(U, N);
 }
 
 //=======================================================================
@@ -688,23 +788,23 @@ Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
   case GeomAbs_Line :
     return R3D;
   case GeomAbs_Circle: {
-    Standard_Real R = (*((Handle(Geom_Circle)*)&myCurve))->Circ().Radius();
+    Standard_Real R = Handle(Geom_Circle)::DownCast (myCurve)->Circ().Radius();
     if ( R > R3D/2. )
       return 2*ASin(R3D/(2*R));
     else
       return 2*M_PI;
   }
   case GeomAbs_Ellipse: {
-    return R3D / (*((Handle(Geom_Ellipse)*)&myCurve))->MajorRadius();
+    return R3D / Handle(Geom_Ellipse)::DownCast (myCurve)->MajorRadius();
   }
   case GeomAbs_BezierCurve: {
     Standard_Real res;
-    (*((Handle(Geom_BezierCurve)*)&myCurve))->Resolution(R3D,res);
+    Handle(Geom_BezierCurve)::DownCast (myCurve)->Resolution(R3D,res);
     return res;
   }
   case GeomAbs_BSplineCurve: {
     Standard_Real res;
-    (*((Handle(Geom_BSplineCurve)*)&myCurve))->Resolution(R3D,res);
+    myBSplineCurve->Resolution(R3D,res);
     return res;
   }
   default:
@@ -725,8 +825,9 @@ Standard_Real GeomAdaptor_Curve::Resolution(const Standard_Real R3D) const
 
 gp_Lin GeomAdaptor_Curve::Line() const 
 {
-  Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Line, "");
-  return (*((Handle(Geom_Line)*)&myCurve))->Lin();  
+  Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Line,
+                                  "GeomAdaptor_Curve::Line() - curve is not a Line");
+  return Handle(Geom_Line)::DownCast (myCurve)->Lin();  
 }
 
 //=======================================================================
@@ -736,8 +837,9 @@ gp_Lin GeomAdaptor_Curve::Line() const
 
 gp_Circ  GeomAdaptor_Curve::Circle() const 
 {
-  Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Circle, "");
-  return (*((Handle(Geom_Circle)*)&myCurve))->Circ();
+  Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Circle,
+                                  "GeomAdaptor_Curve::Circle() - curve is not a Circle");
+  return Handle(Geom_Circle)::DownCast (myCurve)->Circ();
 }
 
 //=======================================================================
@@ -747,8 +849,9 @@ gp_Circ  GeomAdaptor_Curve::Circle() const
 
 gp_Elips GeomAdaptor_Curve::Ellipse() const 
 {
-  Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Ellipse, "");
-  return (*((Handle(Geom_Ellipse)*)&myCurve))->Elips();
+  Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Ellipse,
+                                  "GeomAdaptor_Curve::Ellipse() - curve is not an Ellipse");
+  return Handle(Geom_Ellipse)::DownCast (myCurve)->Elips();
 }
 
 //=======================================================================
@@ -758,8 +861,9 @@ gp_Elips GeomAdaptor_Curve::Ellipse() const
 
 gp_Hypr GeomAdaptor_Curve::Hyperbola() const 
 {
-  Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Hyperbola, "");
-  return (*((Handle(Geom_Hyperbola)*)&myCurve))->Hypr();  
+  Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Hyperbola,
+                                  "GeomAdaptor_Curve::Hyperbola() - curve is not a Hyperbola");
+  return Handle(Geom_Hyperbola)::DownCast (myCurve)->Hypr();  
 }
 
 //=======================================================================
@@ -769,8 +873,9 @@ gp_Hypr GeomAdaptor_Curve::Hyperbola() const
 
 gp_Parab GeomAdaptor_Curve::Parabola() const 
 {
-  Standard_NoSuchObject_Raise_if(myTypeCurve != GeomAbs_Parabola, "");
-  return (*((Handle(Geom_Parabola)*)&myCurve))->Parab();
+  Standard_NoSuchObject_Raise_if (myTypeCurve != GeomAbs_Parabola,
+                                  "GeomAdaptor_Curve::Parabola() - curve is not a Parabola");
+  return Handle(Geom_Parabola)::DownCast (myCurve)->Parab();
 }
 
 //=======================================================================
@@ -781,13 +886,11 @@ gp_Parab GeomAdaptor_Curve::Parabola() const
 Standard_Integer GeomAdaptor_Curve::Degree() const
 {
   if (myTypeCurve == GeomAbs_BezierCurve)
-    return (*((Handle(Geom_BezierCurve)*)&myCurve))->Degree();
+    return Handle(Geom_BezierCurve)::DownCast (myCurve)->Degree();
   else if (myTypeCurve == GeomAbs_BSplineCurve)
-    return (*((Handle(Geom_BSplineCurve)*)&myCurve))->Degree();
+    return myBSplineCurve->Degree();
   else
-    Standard_NoSuchObject::Raise();
-  // portage WNT 
-  return 0;
+    throw Standard_NoSuchObject();
 }
 
 //=======================================================================
@@ -798,9 +901,9 @@ Standard_Integer GeomAdaptor_Curve::Degree() const
 Standard_Boolean GeomAdaptor_Curve::IsRational() const {
   switch( myTypeCurve) {
   case GeomAbs_BSplineCurve:
-    return (*((Handle(Geom_BSplineCurve)*)&myCurve))->IsRational();
+    return myBSplineCurve->IsRational();
   case GeomAbs_BezierCurve:
-    return (*((Handle(Geom_BezierCurve)*)&myCurve))->IsRational();
+    return Handle(Geom_BezierCurve)::DownCast (myCurve)->IsRational();
   default:
     return Standard_False;
   }
@@ -814,13 +917,11 @@ Standard_Boolean GeomAdaptor_Curve::IsRational() const {
 Standard_Integer GeomAdaptor_Curve::NbPoles() const
 {
   if (myTypeCurve == GeomAbs_BezierCurve)
-    return (*((Handle(Geom_BezierCurve)*)&myCurve))->NbPoles();
+    return Handle(Geom_BezierCurve)::DownCast (myCurve)->NbPoles();
   else if (myTypeCurve == GeomAbs_BSplineCurve)
-    return (*((Handle(Geom_BSplineCurve)*)&myCurve))->NbPoles();
+    return myBSplineCurve->NbPoles();
   else
-    Standard_NoSuchObject::Raise();
-  // portage WNT
-  return 0;
+    throw Standard_NoSuchObject();
 }
 
 //=======================================================================
@@ -831,8 +932,8 @@ Standard_Integer GeomAdaptor_Curve::NbPoles() const
 Standard_Integer GeomAdaptor_Curve::NbKnots() const
 {
   if ( myTypeCurve != GeomAbs_BSplineCurve)
-    Standard_NoSuchObject::Raise("GeomAdaptor_Curve::NbKnots");
-  return (*((Handle(Geom_BSplineCurve)*)&myCurve))->NbKnots();
+    throw Standard_NoSuchObject("GeomAdaptor_Curve::NbKnots");
+  return myBSplineCurve->NbKnots();
 }
 
 //=======================================================================
@@ -843,8 +944,8 @@ Standard_Integer GeomAdaptor_Curve::NbKnots() const
 Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const 
 {
  if ( myTypeCurve != GeomAbs_BezierCurve)
-    Standard_NoSuchObject::Raise("GeomAdaptor_Curve::Bezier");
-  return *((Handle(Geom_BezierCurve)*)&myCurve);
+    throw Standard_NoSuchObject("GeomAdaptor_Curve::Bezier");
+  return Handle(Geom_BezierCurve)::DownCast (myCurve);
 }
 
 //=======================================================================
@@ -855,8 +956,19 @@ Handle(Geom_BezierCurve) GeomAdaptor_Curve::Bezier() const
 Handle(Geom_BSplineCurve) GeomAdaptor_Curve::BSpline() const 
 {
  if ( myTypeCurve != GeomAbs_BSplineCurve)
-    Standard_NoSuchObject::Raise("GeomAdaptor_Curve::BSpline");
+    throw Standard_NoSuchObject("GeomAdaptor_Curve::BSpline");
 
-  return *((Handle(Geom_BSplineCurve)*)&myCurve);
+  return myBSplineCurve;
 }
 
+//=======================================================================
+//function : BasisCurve
+//purpose  : 
+//=======================================================================
+
+Handle(Geom_OffsetCurve) GeomAdaptor_Curve::OffsetCurve() const
+{
+  if ( myTypeCurve != GeomAbs_OffsetCurve)
+    throw Standard_NoSuchObject("GeomAdaptor_Curve::OffsetCurve");
+  return Handle(Geom_OffsetCurve)::DownCast(myCurve);
+}