0023620: Follow up of 0022939 - make Bezier curve/surface evaluation thread-safe
[occt.git] / src / GeomAdaptor / GeomAdaptor_Surface.cxx
index b220f6f..f3423df 100644 (file)
@@ -5,8 +5,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// 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.
 
 #define No_Standard_RangeError
 #define No_Standard_OutOfRange
-#define PosTol (Precision::PConfusion()*0.5)
 
-#include <GeomAdaptor_Surface.ixx>
-
-#include <GeomAdaptor_HSurface.hxx>
-#include <GeomAdaptor_HCurve.hxx>
-#include <GeomAdaptor_Curve.hxx>
+#include <Adaptor3d_HCurve.hxx>
 #include <Adaptor3d_HSurface.hxx>
-#include <Standard_OutOfRange.hxx>
-#include <Geom_RectangularTrimmedSurface.hxx>
-#include <Geom_BSplineSurface.hxx> 
-#include <Geom_BezierSurface.hxx> 
+#include <BSplCLib.hxx>
+#include <BSplSLib_Cache.hxx>
+#include <Geom_BezierSurface.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_ConicalSurface.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_CylindricalSurface.hxx>
 #include <Geom_OffsetSurface.hxx>
-//#include <GeomConvert_BSplineSurfaceKnotSplitting.hxx>
-#include <Standard_OutOfRange.hxx>
-#include <TColStd_HArray1OfInteger.hxx>
-#include <TColStd_Array1OfReal.hxx>
-#include <TColStd_Array1OfInteger.hxx>
 #include <Geom_Plane.hxx>
-#include <Geom_CylindricalSurface.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
 #include <Geom_SphericalSurface.hxx>
-#include <Geom_ToroidalSurface.hxx>
-#include <Geom_ConicalSurface.hxx>
-#include <Geom_SurfaceOfRevolution.hxx>
+#include <Geom_Surface.hxx>
 #include <Geom_SurfaceOfLinearExtrusion.hxx>
-#include <Geom_Curve.hxx>
-#include <Geom_Circle.hxx>
+#include <Geom_SurfaceOfRevolution.hxx>
+#include <Geom_ToroidalSurface.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GeomAdaptor_HCurve.hxx>
+#include <GeomAdaptor_HSurface.hxx>
+#include <GeomAdaptor_Surface.hxx>
+#include <GeomEvaluator_OffsetSurface.hxx>
+#include <GeomEvaluator_SurfaceOfExtrusion.hxx>
+#include <GeomEvaluator_SurfaceOfRevolution.hxx>
+#include <gp_Ax1.hxx>
 #include <gp_Circ.hxx>
+#include <gp_Cone.hxx>
+#include <gp_Cylinder.hxx>
+#include <gp_Dir.hxx>
 #include <gp_Lin.hxx>
+#include <gp_Pln.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Sphere.hxx>
+#include <gp_Torus.hxx>
 #include <gp_Trsf.hxx>
-#include <BSplCLib.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_OutOfRange.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_HArray1OfInteger.hxx>
 
-#define myBspl (*((Handle(Geom_BSplineSurface)*)&mySurface))
-#define myExtSurf (*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))
-#define myRevSurf (*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))
-#define myOffSurf (*((Handle(Geom_OffsetSurface)*)&mySurface))
+static const Standard_Real PosTol = Precision::PConfusion()*0.5;
 
 //=======================================================================
 //function : LocalContinuity
@@ -125,13 +135,13 @@ void GeomAdaptor_Surface::load(const Handle(Geom_Surface)& S,
 
   if ( mySurface != S) {
     mySurface = S;
-    
+    mySurfaceCache = Handle(BSplSLib_Cache)();
+    myNestedEvaluator = Handle(GeomEvaluator_Surface)();
+
     const Handle(Standard_Type)& TheType = S->DynamicType();
-    if ( TheType == STANDARD_TYPE(Geom_BezierSurface))
-      mySurfaceType = GeomAbs_BezierSurface;
-    else if (TheType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
-      Load((*((Handle(Geom_RectangularTrimmedSurface)*)&S))->BasisSurface(),
-          UFirst,ULast,VFirst,VLast);
+    if (TheType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
+      Load(Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface(),
+           UFirst,ULast,VFirst,VLast);
     }
     else if ( TheType == STANDARD_TYPE(Geom_Plane))
       mySurfaceType = GeomAbs_Plane;
@@ -144,15 +154,64 @@ void GeomAdaptor_Surface::load(const Handle(Geom_Surface)& S,
     else if ( TheType == STANDARD_TYPE(Geom_ToroidalSurface))
       mySurfaceType = GeomAbs_Torus;
     else if ( TheType == STANDARD_TYPE(Geom_SurfaceOfRevolution))
+    {
       mySurfaceType = GeomAbs_SurfaceOfRevolution;
+      Handle(Geom_SurfaceOfRevolution) myRevSurf =
+          Handle(Geom_SurfaceOfRevolution)::DownCast(mySurface);
+      // Create nested adaptor for base curve
+      Handle(Geom_Curve) aBaseCurve = myRevSurf->BasisCurve();
+      Handle(GeomAdaptor_HCurve) aBaseAdaptor = new GeomAdaptor_HCurve(aBaseCurve);
+      // Create corresponding evaluator
+      myNestedEvaluator = new GeomEvaluator_SurfaceOfRevolution(
+          Handle(Adaptor3d_HCurve)::DownCast(aBaseAdaptor),
+          myRevSurf->Direction(), myRevSurf->Location());
+    }
     else if ( TheType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
+    {
       mySurfaceType = GeomAbs_SurfaceOfExtrusion;
-    else if ( TheType == STANDARD_TYPE(Geom_BSplineSurface)) {
+      Handle(Geom_SurfaceOfLinearExtrusion) myExtSurf =
+          Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(mySurface);
+      // Create nested adaptor for base curve
+      Handle(Geom_Curve) aBaseCurve = myExtSurf->BasisCurve();
+      Handle(GeomAdaptor_HCurve) aBaseAdaptor = new GeomAdaptor_HCurve(aBaseCurve);
+      // Create corresponding evaluator
+      myNestedEvaluator = new GeomEvaluator_SurfaceOfExtrusion(
+          Handle(Adaptor3d_HCurve)::DownCast(aBaseAdaptor), myExtSurf->Direction());
+    }
+    else if (TheType == STANDARD_TYPE(Geom_BezierSurface))
+    {
+      mySurfaceType = GeomAbs_BezierSurface;
+      // Create cache for Bezier
+      Handle(Geom_BezierSurface) aBezier = Handle(Geom_BezierSurface)::DownCast(mySurface);
+      Standard_Integer aDegU = aBezier->UDegree();
+      Standard_Integer aDegV = aBezier->VDegree();
+      TColStd_Array1OfReal aFlatKnotsU(BSplCLib::FlatBezierKnots(aDegU), 1, 2 * (aDegU + 1));
+      TColStd_Array1OfReal aFlatKnotsV(BSplCLib::FlatBezierKnots(aDegV), 1, 2 * (aDegV + 1));
+      mySurfaceCache = new BSplSLib_Cache(
+        aDegU, aBezier->IsUPeriodic(), aFlatKnotsU,
+        aDegV, aBezier->IsVPeriodic(), aFlatKnotsV,
+        aBezier->Poles(), aBezier->Weights());
+    }
+    else if (TheType == STANDARD_TYPE(Geom_BSplineSurface)) {
       mySurfaceType = GeomAbs_BSplineSurface;
-      myBspl        =  *((Handle(Geom_BSplineSurface)*)&S);
+      Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
+      // Create cache for B-spline
+      mySurfaceCache = new BSplSLib_Cache( 
+        myBspl->UDegree(), myBspl->IsUPeriodic(), myBspl->UKnotSequence(), 
+        myBspl->VDegree(), myBspl->IsVPeriodic(), myBspl->VKnotSequence(), 
+        myBspl->Poles(), myBspl->Weights());
     }
     else if ( TheType == STANDARD_TYPE(Geom_OffsetSurface))
+    {
       mySurfaceType = GeomAbs_OffsetSurface;
+      Handle(Geom_OffsetSurface) myOffSurf = Handle(Geom_OffsetSurface)::DownCast(mySurface);
+      // Create nested adaptor for base surface
+      Handle(Geom_Surface) aBaseSurf = myOffSurf->BasisSurface();
+      Handle(GeomAdaptor_HSurface) aBaseAdaptor =
+          new GeomAdaptor_HSurface(aBaseSurf, myUFirst, myULast, myVFirst, myVLast, myTolU, myTolV);
+      myNestedEvaluator = new GeomEvaluator_OffsetSurface(
+          aBaseAdaptor, myOffSurf->Offset(), myOffSurf->OsculatingSurface());
+    }
     else
       mySurfaceType = GeomAbs_OtherSurface;
   }
@@ -174,6 +233,7 @@ GeomAbs_Shape GeomAdaptor_Surface::UContinuity() const
   {
     case GeomAbs_BSplineSurface:
     {
+      Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
       const Standard_Integer N = myBspl->NbUKnots();
       TColStd_Array1OfReal TK(1,N);
       TColStd_Array1OfInteger TM(1,N);
@@ -199,8 +259,9 @@ GeomAbs_Shape GeomAdaptor_Surface::UContinuity() const
     }
     case GeomAbs_SurfaceOfExtrusion:
     {
-      GeomAdaptor_Curve GC
-        ((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+      Handle(Geom_SurfaceOfLinearExtrusion) myExtSurf =
+          Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(mySurface);
+      GeomAdaptor_Curve GC(myExtSurf->BasisCurve(), myUFirst, myULast);
       return GC.Continuity();
     }
     case GeomAbs_OtherSurface: 
@@ -227,6 +288,7 @@ GeomAbs_Shape GeomAdaptor_Surface::VContinuity() const
   {
     case GeomAbs_BSplineSurface:
     {
+      Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
       const Standard_Integer N = myBspl->NbVKnots();
       TColStd_Array1OfReal TK(1,N);
       TColStd_Array1OfInteger TM(1,N);
@@ -252,8 +314,9 @@ GeomAbs_Shape GeomAdaptor_Surface::VContinuity() const
     }
     case GeomAbs_SurfaceOfRevolution:
     {
-      GeomAdaptor_Curve GC
-        ((*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))->BasisCurve(),myVFirst,myVLast);
+      Handle(Geom_SurfaceOfRevolution) myRevSurf =
+          Handle(Geom_SurfaceOfRevolution)::DownCast(mySurface);
+      GeomAdaptor_Curve GC(myRevSurf->BasisCurve(), myVFirst, myVLast);
       return GC.Continuity();
     }
     case GeomAbs_OtherSurface:
@@ -280,15 +343,17 @@ Standard_Integer GeomAdaptor_Surface::NbUIntervals(const GeomAbs_Shape S) const
   {
     case GeomAbs_BSplineSurface:
     {
+      Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
       GeomAdaptor_Curve myBasisCurve
         (myBspl->VIso(myBspl->VKnot(myBspl->FirstVKnotIndex())),myUFirst,myULast);
       return myBasisCurve.NbIntervals(S);
     }
          case GeomAbs_SurfaceOfExtrusion:
     {
-      GeomAdaptor_Curve myBasisCurve
-        ((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->BasisCurve(),myUFirst,myULast);
-         if (myBasisCurve.GetType() == GeomAbs_BSplineCurve)
+      Handle(Geom_SurfaceOfLinearExtrusion) myExtSurf =
+          Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(mySurface);
+      GeomAdaptor_Curve myBasisCurve(myExtSurf->BasisCurve(), myUFirst, myULast);
+      if (myBasisCurve.GetType() == GeomAbs_BSplineCurve)
         return myBasisCurve.NbIntervals(S);
       break;
     }
@@ -305,7 +370,8 @@ Standard_Integer GeomAdaptor_Surface::NbUIntervals(const GeomAbs_Shape S) const
         case GeomAbs_C3:
         case GeomAbs_CN: break;
       }
-      GeomAdaptor_Surface Sur((*((Handle(Geom_OffsetSurface)*)&mySurface))->BasisSurface());
+      Handle(Geom_OffsetSurface) myOffSurf = Handle(Geom_OffsetSurface)::DownCast(mySurface);
+      GeomAdaptor_Surface Sur(myOffSurf->BasisSurface());
       return Sur.NbUIntervals(BaseS);
     }
     case GeomAbs_Plane:
@@ -331,19 +397,21 @@ Standard_Integer GeomAdaptor_Surface::NbVIntervals(const GeomAbs_Shape S) const
   {
     case GeomAbs_BSplineSurface:
     {
+      Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
       GeomAdaptor_Curve myBasisCurve
         (myBspl->UIso(myBspl->UKnot(myBspl->FirstUKnotIndex())),myVFirst,myVLast);
       return myBasisCurve.NbIntervals(S);
     }
-         case GeomAbs_SurfaceOfRevolution:
+    case GeomAbs_SurfaceOfRevolution:
     {
-      GeomAdaptor_Curve myBasisCurve
-        ((*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))->BasisCurve(),myVFirst,myVLast);
-         if (myBasisCurve.GetType() == GeomAbs_BSplineCurve)
+      Handle(Geom_SurfaceOfRevolution) myRevSurf =
+          Handle(Geom_SurfaceOfRevolution)::DownCast(mySurface);
+      GeomAdaptor_Curve myBasisCurve(myRevSurf->BasisCurve(), myVFirst, myVLast);
+      if (myBasisCurve.GetType() == GeomAbs_BSplineCurve)
         return myBasisCurve.NbIntervals(S);
       break;
     }
-         case GeomAbs_OffsetSurface:
+    case GeomAbs_OffsetSurface:
     {
       GeomAbs_Shape BaseS = GeomAbs_CN;
       switch(S)
@@ -356,9 +424,10 @@ Standard_Integer GeomAdaptor_Surface::NbVIntervals(const GeomAbs_Shape S) const
         case GeomAbs_C3:
         case GeomAbs_CN: break;
       }
-      GeomAdaptor_Surface Sur((*((Handle(Geom_OffsetSurface)*)&mySurface))->BasisSurface());
+      Handle(Geom_OffsetSurface) myOffSurf = Handle(Geom_OffsetSurface)::DownCast(mySurface);
+      GeomAdaptor_Surface Sur(myOffSurf->BasisSurface());
       return Sur.NbVIntervals(BaseS);
-         }
+    }
     case GeomAbs_Plane:
     case GeomAbs_Cylinder:
     case GeomAbs_Cone:
@@ -384,16 +453,17 @@ void GeomAdaptor_Surface::UIntervals(TColStd_Array1OfReal& T, const GeomAbs_Shap
   {
     case GeomAbs_BSplineSurface:
     {
+      Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
       GeomAdaptor_Curve myBasisCurve
         (myBspl->VIso(myBspl->VKnot(myBspl->FirstVKnotIndex())),myUFirst,myULast);
       myNbUIntervals = myBasisCurve.NbIntervals(S);
       myBasisCurve.Intervals(T,S);
       break;
     }
-         case GeomAbs_SurfaceOfExtrusion:
+    case GeomAbs_SurfaceOfExtrusion:
     {
       GeomAdaptor_Curve myBasisCurve
-        ((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+        (Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (mySurface)->BasisCurve(),myUFirst,myULast);
       if (myBasisCurve.GetType() == GeomAbs_BSplineCurve)
       {
         myNbUIntervals = myBasisCurve.NbIntervals(S);
@@ -401,7 +471,7 @@ void GeomAdaptor_Surface::UIntervals(TColStd_Array1OfReal& T, const GeomAbs_Shap
       }
       break;
     }
-         case GeomAbs_OffsetSurface:
+    case GeomAbs_OffsetSurface:
     {
       GeomAbs_Shape BaseS = GeomAbs_CN;
       switch(S)
@@ -414,7 +484,8 @@ void GeomAdaptor_Surface::UIntervals(TColStd_Array1OfReal& T, const GeomAbs_Shap
         case GeomAbs_C3:
         case GeomAbs_CN: break;
       }
-      GeomAdaptor_Surface Sur((*((Handle(Geom_OffsetSurface)*)&mySurface))->BasisSurface());
+      Handle(Geom_OffsetSurface) myOffSurf = Handle(Geom_OffsetSurface)::DownCast(mySurface);
+      GeomAdaptor_Surface Sur(myOffSurf->BasisSurface());
       myNbUIntervals = Sur.NbUIntervals(BaseS);
       Sur.UIntervals(T, BaseS);
     }
@@ -445,16 +516,18 @@ void GeomAdaptor_Surface::VIntervals(TColStd_Array1OfReal& T, const GeomAbs_Shap
   {
     case GeomAbs_BSplineSurface:
     {
+      Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
       GeomAdaptor_Curve myBasisCurve
         (myBspl->UIso(myBspl->UKnot(myBspl->FirstUKnotIndex())),myVFirst,myVLast);
       myNbVIntervals = myBasisCurve.NbIntervals(S);
       myBasisCurve.Intervals(T,S);
       break;
     }
-         case GeomAbs_SurfaceOfRevolution:
+    case GeomAbs_SurfaceOfRevolution:
     {
-      GeomAdaptor_Curve myBasisCurve
-        ((*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))->BasisCurve(),myVFirst,myVLast);
+      Handle(Geom_SurfaceOfRevolution) myRevSurf =
+          Handle(Geom_SurfaceOfRevolution)::DownCast(mySurface);
+      GeomAdaptor_Curve myBasisCurve(myRevSurf->BasisCurve(), myVFirst, myVLast);
       if (myBasisCurve.GetType() == GeomAbs_BSplineCurve)
       {
         myNbVIntervals = myBasisCurve.NbIntervals(S);
@@ -462,7 +535,7 @@ void GeomAdaptor_Surface::VIntervals(TColStd_Array1OfReal& T, const GeomAbs_Shap
       }
       break;
     }
-         case GeomAbs_OffsetSurface:
+    case GeomAbs_OffsetSurface:
     {
       GeomAbs_Shape BaseS = GeomAbs_CN;
       switch(S)
@@ -475,7 +548,8 @@ void GeomAdaptor_Surface::VIntervals(TColStd_Array1OfReal& T, const GeomAbs_Shap
         case GeomAbs_C3:
         case GeomAbs_CN: break;
       }
-      GeomAdaptor_Surface Sur((*((Handle(Geom_OffsetSurface)*)&mySurface))->BasisSurface());
+      Handle(Geom_OffsetSurface) myOffSurf = Handle(Geom_OffsetSurface)::DownCast(mySurface);
+      GeomAdaptor_Surface Sur(myOffSurf->BasisSurface());
       myNbVIntervals = Sur.NbVIntervals(BaseS);
       Sur.VIntervals(T, BaseS);
     }
@@ -599,6 +673,35 @@ Standard_Real GeomAdaptor_Surface::VPeriod() const
   return mySurface->VPeriod();
 }
 
+//=======================================================================
+//function : RebuildCache
+//purpose  : 
+//=======================================================================
+void GeomAdaptor_Surface::RebuildCache(const Standard_Real theU,
+                                       const Standard_Real theV) const
+{
+  if (mySurfaceType == GeomAbs_BezierSurface)
+  {
+    Handle(Geom_BezierSurface) aBezier = Handle(Geom_BezierSurface)::DownCast(mySurface);
+    Standard_Integer aDegU = aBezier->UDegree();
+    Standard_Integer aDegV = aBezier->VDegree();
+    TColStd_Array1OfReal aFlatKnotsU(BSplCLib::FlatBezierKnots(aDegU), 1, 2 * (aDegU + 1));
+    TColStd_Array1OfReal aFlatKnotsV(BSplCLib::FlatBezierKnots(aDegV), 1, 2 * (aDegV + 1));
+    mySurfaceCache->BuildCache(theU, theV,
+      aDegU, aBezier->IsUPeriodic(), aFlatKnotsU,
+      aDegV, aBezier->IsVPeriodic(), aFlatKnotsV,
+      aBezier->Poles(), aBezier->Weights());
+  }
+  else if (mySurfaceType == GeomAbs_BSplineSurface)
+  {
+    Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
+      mySurfaceCache->BuildCache(theU, theV,
+        myBspl->UDegree(), myBspl->IsUPeriodic(), myBspl->UKnotSequence(),
+        myBspl->VDegree(), myBspl->IsVPeriodic(), myBspl->VKnotSequence(),
+        myBspl->Poles(), myBspl->Weights());
+  }
+}
+
 //=======================================================================
 //function : Value
 //purpose  : 
@@ -607,7 +710,9 @@ Standard_Real GeomAdaptor_Surface::VPeriod() const
 gp_Pnt GeomAdaptor_Surface::Value(const Standard_Real U, 
                                   const Standard_Real V) const 
 {
-  return mySurface->Value(U,V);
+  gp_Pnt aValue;
+  D0(U, V, aValue);
+  return aValue;
 }
 
 //=======================================================================
@@ -618,7 +723,31 @@ gp_Pnt GeomAdaptor_Surface::Value(const Standard_Real U,
 void GeomAdaptor_Surface::D0(const Standard_Real U, 
                              const Standard_Real V, gp_Pnt& P) const 
 {
-  mySurface->D0(U,V,P);
+  switch (mySurfaceType)
+  {
+  case GeomAbs_BezierSurface:
+  case GeomAbs_BSplineSurface:
+    if (!mySurfaceCache.IsNull())
+    {
+      if (!mySurfaceCache->IsCacheValid(U, V))
+        RebuildCache(U, V);
+      mySurfaceCache->D0(U, V, P);
+    }
+    else
+      mySurface->D0(U, V, P);
+    break;
+
+  case GeomAbs_OffsetSurface:
+  case GeomAbs_SurfaceOfExtrusion:
+  case GeomAbs_SurfaceOfRevolution:
+    Standard_NoSuchObject_Raise_if(myNestedEvaluator.IsNull(),
+        "GeomAdaptor_Surface::D0: evaluator is not initialized");
+    myNestedEvaluator->D0(U, V, P);
+    break;
+
+  default:
+    mySurface->D0(U, V, P);
+  }
 }
 
 
@@ -629,11 +758,11 @@ void GeomAdaptor_Surface::D0(const Standard_Real U,
 
 void GeomAdaptor_Surface::D1(const Standard_Real U, 
                              const Standard_Real V, 
-                            gp_Pnt&       P,
-                            gp_Vec&       D1U, 
-                            gp_Vec&       D1V ) const 
+                                   gp_Pnt&       P,
+                                   gp_Vec&       D1U, 
+                                   gp_Vec&       D1V ) const 
 {
-  Standard_Integer Ideb,Ifin,IVdeb,IVfin,USide=0,VSide=0;
+  Standard_Integer Ideb, Ifin, IVdeb, IVfin, USide=0, VSide=0;
   Standard_Real u = U, v = V;
   if (Abs(U-myUFirst) <= myTolU) {USide= 1; u = myUFirst;}
   else if (Abs(U-myULast) <= myTolU) {USide= -1; u = myULast;}
@@ -641,39 +770,34 @@ void GeomAdaptor_Surface::D1(const Standard_Real U,
   else if (Abs(V-myVLast) <= myTolV) {VSide= -1; v = myVLast;}
 
   switch(mySurfaceType) {
-  case  GeomAbs_BSplineSurface: 
-    {  
-      if((USide==0)&&(VSide==0)){
-       myBspl->D1(u,v,P,D1U,D1V);
-      }
-      else { 
-       if(IfUVBound(u,v,Ideb,Ifin,IVdeb,IVfin,USide,VSide))
-         myBspl->LocalD1 (u, v, Ideb, Ifin,IVdeb ,IVfin ,P ,D1U,D1V); 
-       else myBspl->D1(u,v,P,D1U,D1V);
-      }
-      break;
+  case GeomAbs_BezierSurface:
+  case GeomAbs_BSplineSurface: {
+    Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
+    if (!myBspl.IsNull() &&
+        (USide != 0 || VSide != 0) && 
+        IfUVBound(u, v, Ideb, Ifin, IVdeb, IVfin, USide, VSide))
+      myBspl->LocalD1(u, v, Ideb, Ifin, IVdeb, IVfin, P, D1U, D1V);
+    else if (!mySurfaceCache.IsNull())
+    {
+      if (!mySurfaceCache->IsCacheValid(U, V))
+        RebuildCache(U, V);
+      mySurfaceCache->D1(U, V, P, D1U, D1V);
     }
-      
-    case GeomAbs_SurfaceOfExtrusion  :
-      
-       if(USide==0) myExtSurf->D1(u,v,P,D1U,D1V);
-       else myExtSurf->LocalD1(u,v,USide,P,D1U,D1V);
-       break;
-     
-    case GeomAbs_SurfaceOfRevolution :
-     
-       if(VSide==0) myRevSurf->D1 (u, v, P,D1U,D1V );
-       else myRevSurf->LocalD1 (u, v, VSide, P,D1U,D1V );
-       break;
-     
-    case  GeomAbs_OffsetSurface :
-      {
-       if((USide==0)&&(VSide==0)) myOffSurf->D1 (u, v,P,D1U,D1V ); 
-       else   myOffSurf->LocalD1 (u, v, USide, VSide ,P,D1U,D1V ); 
-       break;
-      }
-      default :   
-       mySurface->D1(u,v,P,D1U,D1V);
+    else
+      mySurface->D1(u, v, P, D1U, D1V);
+    break;
+    }
+
+  case GeomAbs_SurfaceOfExtrusion:
+  case GeomAbs_SurfaceOfRevolution:
+  case GeomAbs_OffsetSurface:
+    Standard_NoSuchObject_Raise_if(myNestedEvaluator.IsNull(),
+        "GeomAdaptor_Surface::D1: evaluator is not initialized");
+    myNestedEvaluator->D1(u, v, P, D1U, D1V);
+    break;
+
+  default:
+    mySurface->D1(u, v, P, D1U, D1V);
   }
 }
 
@@ -683,50 +807,51 @@ void GeomAdaptor_Surface::D1(const Standard_Real U,
 //=======================================================================
 
 void GeomAdaptor_Surface::D2(const Standard_Real U,
-                             const Standard_Real V, gp_Pnt& P,
-                             gp_Vec& D1U, gp_Vec& D1V, gp_Vec& D2U,
-                             gp_Vec& D2V, gp_Vec& D2UV) const 
+                             const Standard_Real V, 
+                                   gp_Pnt&       P,
+                                   gp_Vec&       D1U, 
+                                   gp_Vec&       D1V, 
+                                   gp_Vec&       D2U,
+                                   gp_Vec&       D2V, 
+                                   gp_Vec&       D2UV) const 
 { 
-  Standard_Integer  Ideb,Ifin,IVdeb,IVfin,USide=0,VSide=0;
+  Standard_Integer Ideb, Ifin, IVdeb, IVfin, USide=0, VSide=0;
   Standard_Real u = U, v = V;
   if (Abs(U-myUFirst) <= myTolU) {USide= 1; u = myUFirst;}
   else if (Abs(U-myULast) <= myTolU) {USide= -1; u = myULast;}
   if (Abs(V-myVFirst) <= myTolV) {VSide= 1; v = myVFirst;}
   else if (Abs(V-myVLast) <= myTolV) {VSide= -1; v = myVLast;}
 
-  switch(mySurfaceType)
+  switch(mySurfaceType) {
+  case GeomAbs_BezierSurface:
+  case  GeomAbs_BSplineSurface: {
+    Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
+    if (!myBspl.IsNull() &&
+        (USide != 0 || VSide != 0) && 
+        IfUVBound(u, v, Ideb, Ifin, IVdeb, IVfin, USide, VSide))
+      myBspl->LocalD2(u, v, Ideb, Ifin, IVdeb, IVfin, P, D1U, D1V, D2U, D2V, D2UV);
+    else if (!mySurfaceCache.IsNull())
     {
-    case  GeomAbs_BSplineSurface:
-      
-       if((USide==0)&&(VSide==0)) myBspl->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
-       else{
-        if(IfUVBound(u,v,Ideb,Ifin,IVdeb,IVfin,USide,VSide))
-          myBspl->LocalD2 (u, v, Ideb, Ifin,IVdeb ,IVfin ,P ,D1U,D1V,D2U,D2V,D2UV); 
-        else myBspl->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
-       }
-       break;
-     
-    case GeomAbs_SurfaceOfExtrusion  :
-      
-       if(USide==0)  myExtSurf->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
-       else myExtSurf->LocalD2(u,v,USide,P,D1U,D1V,D2U,D2V,D2UV);
-       break;
-     
-    case GeomAbs_SurfaceOfRevolution :
-      
-       if(VSide==0) myRevSurf->D2 (u, v, P,D1U,D1V,D2U,D2V,D2UV );
-       else myRevSurf->LocalD2 (u, v, VSide, P,D1U,D1V,D2U,D2V,D2UV );
-       break;
-     
-    case  GeomAbs_OffsetSurface :
-      {
-       if((USide==0)&&(VSide==0)) myOffSurf->D2 (u, v,P,D1U,D1V,D2U,D2V,D2UV ); 
-       else myOffSurf->LocalD2 (u, v, USide, VSide ,P,D1U,D1V,D2U,D2V,D2UV ); 
-       break;
-      }
-      default :  { mySurface->D2(u,v,P,D1U,D1V,D2U,D2V,D2UV);
-                  break;}
+      if (!mySurfaceCache->IsCacheValid(U, V))
+        RebuildCache(U, V);
+      mySurfaceCache->D2(U, V, P, D1U, D1V, D2U, D2V, D2UV);
     }
+    else
+      mySurface->D2(u, v, P, D1U, D1V, D2U, D2V, D2UV);
+    break;
+  }
+
+  case GeomAbs_SurfaceOfExtrusion  :
+  case GeomAbs_SurfaceOfRevolution :
+  case  GeomAbs_OffsetSurface :
+    Standard_NoSuchObject_Raise_if(myNestedEvaluator.IsNull(),
+        "GeomAdaptor_Surface::D2: evaluator is not initialized");
+    myNestedEvaluator->D2(u, v, P, D1U, D1V, D2U, D2V, D2UV);
+    break;
+
+  default:  { mySurface->D2(u, v, P, D1U, D1V, D2U, D2V, D2UV);
+    break;}
+  }
 }
 
 
@@ -749,44 +874,30 @@ void GeomAdaptor_Surface::D3(const Standard_Real U, const Standard_Real V,
   else if (Abs(V-myVLast) <= myTolV) {VSide= -1; v = myVLast;}
 
   switch(mySurfaceType) {
-  case  GeomAbs_BSplineSurface:
-    
-      if((USide==0)&&(VSide==0))
-       myBspl->D3(u,v,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
-      else {
-       if(IfUVBound(u,v,Ideb,Ifin,IVdeb,IVfin,USide,VSide))
-         myBspl-> LocalD3 (u, v, Ideb, Ifin,IVdeb ,IVfin ,
-                           P ,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV); 
-       else
-         myBspl->D3(u,v,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
-      }
-      break;
+  case  GeomAbs_BSplineSurface: {
+    Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
+    if ((USide == 0) && (VSide == 0))
+      myBspl->D3(u, v, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
+    else {
+      if (IfUVBound(u, v, Ideb, Ifin, IVdeb, IVfin, USide, VSide))
+        myBspl->LocalD3(u, v, Ideb, Ifin, IVdeb, IVfin,
+                        P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
+      else
+        myBspl->D3(u, v, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
+    }
+    break;
+  }
     
   case GeomAbs_SurfaceOfExtrusion  :
-    
-      if(USide==0)  myExtSurf->D3(u,v,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
-      else myExtSurf->LocalD3(u,v,USide,P,D1U,D1V,D2U,D2V,D2UV,
-                             D3U,D3V,D3UUV,D3UVV);
-      break;
-    
   case GeomAbs_SurfaceOfRevolution :
-    
-      if(VSide==0) myRevSurf->D3 (u, v, P ,D1U,D1V,D2U,D2V,D2UV,
-                                 D3U,D3V,D3UUV,D3UVV);
-      else myRevSurf->LocalD3 (u, v, VSide, P,D1U,D1V,D2U,D2V,D2UV,
-                              D3U,D3V,D3UUV,D3UVV );
-      break;
-    
-  case  GeomAbs_OffsetSurface : 
-    {
-      if((USide==0)&&(VSide==0)) myOffSurf->D3 (u, v,P ,D1U,D1V,D2U,D2V,D2UV,
-                                               D3U,D3V,D3UUV,D3UVV); 
-      else   myOffSurf->LocalD3 (u, v, USide, VSide ,P ,D1U,D1V,D2U,D2V,D2UV,
-                                D3U,D3V,D3UUV,D3UVV); 
-      break; 
-    }
-    default : {  mySurface->D3(u,v,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV); 
-                break;}
+  case  GeomAbs_OffsetSurface:
+    Standard_NoSuchObject_Raise_if(myNestedEvaluator.IsNull(),
+        "GeomAdaptor_Surface::D3: evaluator is not initialized");
+    myNestedEvaluator->D3(u, v, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
+    break;
+
+  default : {  mySurface->D3(u,v,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV); 
+    break;}
   }
 }
 
@@ -809,30 +920,24 @@ gp_Vec GeomAdaptor_Surface::DN(const Standard_Real    U,
 
   switch(mySurfaceType) 
   {
-  case GeomAbs_BSplineSurface:
-    
-    if((USide==0)&&(VSide==0)) return  myBspl->DN(u,v,Nu,Nv);
+  case GeomAbs_BSplineSurface: {
+    Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
+    if ((USide == 0) && (VSide == 0))
+      return myBspl->DN(u, v, Nu, Nv);
     else {
-      if(IfUVBound(u,v,Ideb,Ifin,IVdeb,IVfin,USide,VSide))
-        return myBspl->LocalDN (u, v, Ideb, Ifin,IVdeb ,IVfin ,Nu,Nv ); 
+      if (IfUVBound(u, v, Ideb, Ifin, IVdeb, IVfin, USide, VSide))
+        return myBspl->LocalDN(u, v, Ideb, Ifin, IVdeb, IVfin, Nu, Nv);
       else
-        return  myBspl->DN(u,v,Nu,Nv); 
+        return myBspl->DN(u, v, Nu, Nv);
     }
-    
+  }
+
   case GeomAbs_SurfaceOfExtrusion:
-    
-    if(USide==0)  return myExtSurf-> DN (u, v,Nu,Nv );
-    else return myExtSurf->LocalDN (u, v, USide,Nu,Nv );
-    
   case GeomAbs_SurfaceOfRevolution:
-
-    if(VSide==0)  return myRevSurf->DN (u, v, Nu, Nv );
-    else  return myRevSurf->LocalDN (u, v,VSide, Nu, Nv );
-     
   case GeomAbs_OffsetSurface:
-    
-    if((USide==0)&&(VSide==0)) return myOffSurf->DN (u, v, Nu, Nv );
-    else return myOffSurf->LocalDN (u, v, USide, VSide, Nu, Nv );
+    Standard_NoSuchObject_Raise_if(myNestedEvaluator.IsNull(),
+        "GeomAdaptor_Surface::DN: evaluator is not initialized");
+    return myNestedEvaluator->DN(u, v, Nu, Nv);
 
   case GeomAbs_Plane:
   case GeomAbs_Cylinder:
@@ -863,12 +968,12 @@ Standard_Real GeomAdaptor_Surface::UResolution(const Standard_Real R3d) const
     case GeomAbs_SurfaceOfExtrusion:
     {
       GeomAdaptor_Curve myBasisCurve
-        ((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+        (Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (mySurface)->BasisCurve(),myUFirst,myULast);
       return myBasisCurve.Resolution(R3d);
     }
        case GeomAbs_Torus:
     {
-      Handle(Geom_ToroidalSurface)& S = *((Handle(Geom_ToroidalSurface)*)&mySurface);
+      Handle(Geom_ToroidalSurface) S (Handle(Geom_ToroidalSurface)::DownCast (mySurface));
       const Standard_Real R = S->MajorRadius() + S->MinorRadius();
       if(R>Precision::Confusion())
         Res = R3d/(2.*R);
@@ -876,7 +981,7 @@ Standard_Real GeomAdaptor_Surface::UResolution(const Standard_Real R3d) const
     }
        case GeomAbs_Sphere:
     {
-      Handle(Geom_SphericalSurface)& S = *((Handle(Geom_SphericalSurface)*)&mySurface);
+      Handle(Geom_SphericalSurface) S (Handle(Geom_SphericalSurface)::DownCast (mySurface));
       const Standard_Real R = S->Radius();
       if(R>Precision::Confusion())
         Res = R3d/(2.*R);
@@ -884,7 +989,7 @@ Standard_Real GeomAdaptor_Surface::UResolution(const Standard_Real R3d) const
     }
        case GeomAbs_Cylinder:
     {
-      Handle(Geom_CylindricalSurface)& S = *((Handle(Geom_CylindricalSurface)*)&mySurface);
+      Handle(Geom_CylindricalSurface) S (Handle(Geom_CylindricalSurface)::DownCast (mySurface));
       const Standard_Real R = S->Radius();
       if(R>Precision::Confusion())
         Res = R3d/(2.*R);
@@ -896,11 +1001,11 @@ Standard_Real GeomAdaptor_Surface::UResolution(const Standard_Real R3d) const
         // Pas vraiment borne => resolution inconnue
         return Precision::Parametric(R3d);
       }
-      Handle(Geom_ConicalSurface)& S = *((Handle(Geom_ConicalSurface)*)&mySurface);
+      Handle(Geom_ConicalSurface) S (Handle(Geom_ConicalSurface)::DownCast (mySurface));
       Handle(Geom_Curve) C = S->VIso(myVLast);
-      const Standard_Real Rayon1 = (*((Handle(Geom_Circle)*)&C))->Radius();
+      const Standard_Real Rayon1 = Handle(Geom_Circle)::DownCast (C)->Radius();
       C = S->VIso(myVFirst);
-      const Standard_Real Rayon2 = (*((Handle(Geom_Circle)*)&C))->Radius();
+      const Standard_Real Rayon2 = Handle(Geom_Circle)::DownCast (C)->Radius();
          const Standard_Real R = (Rayon1 > Rayon2)? Rayon1 : Rayon2;
          return (R>Precision::Confusion()? (R3d / R) : 0.);
     }
@@ -911,18 +1016,18 @@ Standard_Real GeomAdaptor_Surface::UResolution(const Standard_Real R3d) const
        case GeomAbs_BezierSurface:
     {
       Standard_Real Ures,Vres;
-      (*((Handle(Geom_BezierSurface)*)&mySurface))->Resolution(R3d,Ures,Vres);
+      Handle(Geom_BezierSurface)::DownCast (mySurface)->Resolution(R3d,Ures,Vres);
       return Ures;
     }
        case GeomAbs_BSplineSurface:
     {
       Standard_Real Ures,Vres;
-      (*((Handle(Geom_BSplineSurface)*)&mySurface))->Resolution(R3d,Ures,Vres);
+      Handle(Geom_BSplineSurface)::DownCast (mySurface)->Resolution(R3d,Ures,Vres);
       return Ures;
     }
        case GeomAbs_OffsetSurface:
     {
-      Handle(Geom_Surface) base = (*((Handle(Geom_OffsetSurface)*)&mySurface))->BasisSurface();
+      Handle(Geom_Surface) base = Handle(Geom_OffsetSurface)::DownCast (mySurface)->BasisSurface();
       GeomAdaptor_Surface gabase(base,myUFirst,myULast,myVFirst,myVLast);
       return gabase.UResolution(R3d);
     }
@@ -949,12 +1054,12 @@ Standard_Real GeomAdaptor_Surface::VResolution(const Standard_Real R3d) const
     case GeomAbs_SurfaceOfRevolution:
     {
       GeomAdaptor_Curve myBasisCurve
-        ((*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+        (Handle(Geom_SurfaceOfRevolution)::DownCast (mySurface)->BasisCurve(),myUFirst,myULast);
       return myBasisCurve.Resolution(R3d);
     }
        case GeomAbs_Torus:
     {
-      Handle(Geom_ToroidalSurface)& S = *((Handle(Geom_ToroidalSurface)*)&mySurface);
+      Handle(Geom_ToroidalSurface) S (Handle(Geom_ToroidalSurface)::DownCast (mySurface));
       const Standard_Real R = S->MinorRadius();
       if(R>Precision::Confusion())
         Res = R3d/(2.*R);
@@ -962,7 +1067,7 @@ Standard_Real GeomAdaptor_Surface::VResolution(const Standard_Real R3d) const
     }
        case GeomAbs_Sphere:
     {
-      Handle(Geom_SphericalSurface)& S = *((Handle(Geom_SphericalSurface)*)&mySurface);
+      Handle(Geom_SphericalSurface) S (Handle(Geom_SphericalSurface)::DownCast (mySurface));
       const Standard_Real R = S->Radius();
       if(R>Precision::Confusion())
         Res = R3d/(2.*R);
@@ -978,18 +1083,18 @@ Standard_Real GeomAdaptor_Surface::VResolution(const Standard_Real R3d) const
        case GeomAbs_BezierSurface:
     {
       Standard_Real Ures,Vres;
-      (*((Handle(Geom_BezierSurface)*)&mySurface))->Resolution(R3d,Ures,Vres);
+      Handle(Geom_BezierSurface)::DownCast (mySurface)->Resolution(R3d,Ures,Vres);
       return Vres;
     }
        case GeomAbs_BSplineSurface:
     {
       Standard_Real Ures,Vres;
-      (*((Handle(Geom_BSplineSurface)*)&mySurface))->Resolution(R3d,Ures,Vres);
+      Handle(Geom_BSplineSurface)::DownCast (mySurface)->Resolution(R3d,Ures,Vres);
       return Vres;
     }
        case GeomAbs_OffsetSurface:
     {
-      Handle(Geom_Surface) base = (*((Handle(Geom_OffsetSurface)*)&mySurface))->BasisSurface();
+      Handle(Geom_Surface) base = Handle(Geom_OffsetSurface)::DownCast (mySurface)->BasisSurface();
       GeomAdaptor_Surface gabase(base,myUFirst,myULast,myVFirst,myVLast);
       return gabase.VResolution(R3d);
     }
@@ -1011,7 +1116,7 @@ gp_Pln GeomAdaptor_Surface::Plane() const
 {
   if (mySurfaceType != GeomAbs_Plane)
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::Plane");
-  return (*((Handle(Geom_Plane)*)&mySurface))->Pln();
+  return Handle(Geom_Plane)::DownCast (mySurface)->Pln();
 }
 
 //=======================================================================
@@ -1023,7 +1128,7 @@ gp_Cylinder GeomAdaptor_Surface::Cylinder() const
 {
   if (mySurfaceType != GeomAbs_Cylinder)
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::Cylinder");
-  return (*((Handle(Geom_CylindricalSurface)*)&mySurface))->Cylinder();
+  return Handle(Geom_CylindricalSurface)::DownCast (mySurface)->Cylinder();
 }
 
 //=======================================================================
@@ -1035,7 +1140,7 @@ gp_Cone GeomAdaptor_Surface::Cone() const
 {
   if (mySurfaceType != GeomAbs_Cone)
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::Cone");
-  return (*((Handle(Geom_ConicalSurface)*)&mySurface))->Cone();
+  return Handle(Geom_ConicalSurface)::DownCast (mySurface)->Cone();
 }
 
 //=======================================================================
@@ -1047,7 +1152,7 @@ gp_Sphere GeomAdaptor_Surface::Sphere() const
 {
   if (mySurfaceType != GeomAbs_Sphere)
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::Sphere");
-  return (*((Handle(Geom_SphericalSurface)*)&mySurface))->Sphere();
+  return Handle(Geom_SphericalSurface)::DownCast (mySurface)->Sphere();
 }
 
 //=======================================================================
@@ -1059,7 +1164,7 @@ gp_Torus GeomAdaptor_Surface::Torus() const
 {
   if (mySurfaceType != GeomAbs_Torus)
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::Torus");
-  return (*((Handle(Geom_ToroidalSurface)*)&mySurface))->Torus(); 
+  return Handle(Geom_ToroidalSurface)::DownCast (mySurface)->Torus(); 
 }
 
 //=======================================================================
@@ -1070,13 +1175,13 @@ gp_Torus GeomAdaptor_Surface::Torus() const
 Standard_Integer GeomAdaptor_Surface::UDegree() const
 {
   if (mySurfaceType == GeomAbs_BSplineSurface)
-    return (*((Handle(Geom_BSplineSurface)*)&mySurface))->UDegree(); 
+    return Handle(Geom_BSplineSurface)::DownCast (mySurface)->UDegree(); 
   if ( mySurfaceType == GeomAbs_BezierSurface)
-    return (*((Handle(Geom_BezierSurface)*)&mySurface))->UDegree(); 
+    return Handle(Geom_BezierSurface)::DownCast (mySurface)->UDegree(); 
   if ( mySurfaceType == GeomAbs_SurfaceOfExtrusion)
   {
     GeomAdaptor_Curve myBasisCurve
-      ((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+      (Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (mySurface)->BasisCurve(),myUFirst,myULast);
     return myBasisCurve.Degree();
   }
   Standard_NoSuchObject::Raise("GeomAdaptor_Surface::UDegree");
@@ -1091,13 +1196,13 @@ Standard_Integer GeomAdaptor_Surface::UDegree() const
 Standard_Integer GeomAdaptor_Surface::NbUPoles() const
 {
   if (mySurfaceType == GeomAbs_BSplineSurface)
-    return (*((Handle(Geom_BSplineSurface)*)&mySurface))->NbUPoles();
+    return Handle(Geom_BSplineSurface)::DownCast (mySurface)->NbUPoles();
   if ( mySurfaceType == GeomAbs_BezierSurface)
-    return (*((Handle(Geom_BezierSurface)*)&mySurface))->NbUPoles(); 
+    return Handle(Geom_BezierSurface)::DownCast (mySurface)->NbUPoles(); 
   if ( mySurfaceType == GeomAbs_SurfaceOfExtrusion)
   {
     GeomAdaptor_Curve myBasisCurve
-      ((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+      (Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (mySurface)->BasisCurve(),myUFirst,myULast);
     return myBasisCurve.NbPoles();
   }
   Standard_NoSuchObject::Raise("GeomAdaptor_Surface::NbUPoles");
@@ -1112,13 +1217,13 @@ Standard_Integer GeomAdaptor_Surface::NbUPoles() const
 Standard_Integer GeomAdaptor_Surface::VDegree() const
 {
   if (mySurfaceType == GeomAbs_BSplineSurface)
-    return (*((Handle(Geom_BSplineSurface)*)&mySurface))->VDegree(); 
+    return Handle(Geom_BSplineSurface)::DownCast (mySurface)->VDegree(); 
   if ( mySurfaceType == GeomAbs_BezierSurface)
-    return (*((Handle(Geom_BezierSurface)*)&mySurface))->VDegree(); 
+    return Handle(Geom_BezierSurface)::DownCast (mySurface)->VDegree(); 
   if ( mySurfaceType == GeomAbs_SurfaceOfRevolution)
   {
     GeomAdaptor_Curve myBasisCurve
-      ((*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+      (Handle(Geom_SurfaceOfRevolution)::DownCast (mySurface)->BasisCurve(),myUFirst,myULast);
     return myBasisCurve.Degree();
   }
   Standard_NoSuchObject::Raise("GeomAdaptor_Surface::VDegree");
@@ -1133,13 +1238,13 @@ Standard_Integer GeomAdaptor_Surface::VDegree() const
 Standard_Integer GeomAdaptor_Surface::NbVPoles() const
 {
   if (mySurfaceType == GeomAbs_BSplineSurface)
-    return (*((Handle(Geom_BSplineSurface)*)&mySurface))->NbVPoles(); 
+    return Handle(Geom_BSplineSurface)::DownCast (mySurface)->NbVPoles(); 
   if ( mySurfaceType == GeomAbs_BezierSurface)
-    return (*((Handle(Geom_BezierSurface)*)&mySurface))->NbVPoles(); 
+    return Handle(Geom_BezierSurface)::DownCast (mySurface)->NbVPoles(); 
   if ( mySurfaceType == GeomAbs_SurfaceOfRevolution)
   {
     GeomAdaptor_Curve myBasisCurve
-      ((*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+      (Handle(Geom_SurfaceOfRevolution)::DownCast (mySurface)->BasisCurve(),myUFirst,myULast);
     return myBasisCurve.NbPoles();
   }
   Standard_NoSuchObject::Raise("GeomAdaptor_Surface::NbVPoles");
@@ -1154,11 +1259,11 @@ Standard_Integer GeomAdaptor_Surface::NbVPoles() const
 Standard_Integer GeomAdaptor_Surface::NbUKnots() const
 {
   if (mySurfaceType == GeomAbs_BSplineSurface)
-    return (*((Handle(Geom_BSplineSurface)*)&mySurface))->NbUKnots(); 
+    return Handle(Geom_BSplineSurface)::DownCast (mySurface)->NbUKnots(); 
   if ( mySurfaceType == GeomAbs_SurfaceOfExtrusion)
   {
     GeomAdaptor_Curve myBasisCurve
-      ((*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->BasisCurve(),myUFirst,myULast);
+      (Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (mySurface)->BasisCurve(),myUFirst,myULast);
     return myBasisCurve.NbKnots();
   }
   Standard_NoSuchObject::Raise("GeomAdaptor_Surface::NbUKnots");
@@ -1173,7 +1278,7 @@ Standard_Integer GeomAdaptor_Surface::NbUKnots() const
 Standard_Integer GeomAdaptor_Surface::NbVKnots() const 
 {
   if (mySurfaceType == GeomAbs_BSplineSurface)
-    return (*((Handle(Geom_BSplineSurface)*)&mySurface))->NbVKnots(); 
+    return Handle(Geom_BSplineSurface)::DownCast (mySurface)->NbVKnots(); 
   Standard_NoSuchObject::Raise("GeomAdaptor_Surface::NbVKnots");
   return 0;
 }
@@ -1185,9 +1290,9 @@ Standard_Integer GeomAdaptor_Surface::NbVKnots() const
 Standard_Boolean GeomAdaptor_Surface::IsURational() const
 {
   if (mySurfaceType == GeomAbs_BSplineSurface)
-    return (*((Handle(Geom_BSplineSurface)*)&mySurface))->IsURational(); 
+    return Handle(Geom_BSplineSurface)::DownCast (mySurface)->IsURational(); 
   if (mySurfaceType == GeomAbs_BezierSurface)
-    return (*((Handle(Geom_BezierSurface)*)&mySurface))->IsURational(); 
+    return Handle(Geom_BezierSurface)::DownCast (mySurface)->IsURational(); 
   return Standard_False;
 }
 
@@ -1199,9 +1304,9 @@ Standard_Boolean GeomAdaptor_Surface::IsURational() const
 Standard_Boolean GeomAdaptor_Surface::IsVRational() const
 {
   if (mySurfaceType == GeomAbs_BSplineSurface)
-    return (*((Handle(Geom_BSplineSurface)*)&mySurface))->IsVRational(); 
+    return Handle(Geom_BSplineSurface)::DownCast (mySurface)->IsVRational(); 
   if (mySurfaceType == GeomAbs_BezierSurface)
-    return (*((Handle(Geom_BezierSurface)*)&mySurface))->IsVRational(); 
+    return Handle(Geom_BezierSurface)::DownCast (mySurface)->IsVRational(); 
   return Standard_False;
 }
 
@@ -1214,7 +1319,7 @@ Handle(Geom_BezierSurface) GeomAdaptor_Surface::Bezier() const
 {
   if (mySurfaceType != GeomAbs_BezierSurface)
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::Bezier");
-  return *((Handle(Geom_BezierSurface)*)&mySurface);
+  return Handle(Geom_BezierSurface)::DownCast (mySurface);
 }
 
 //=======================================================================
@@ -1226,7 +1331,7 @@ Handle(Geom_BSplineSurface) GeomAdaptor_Surface::BSpline() const
 {
   if (mySurfaceType != GeomAbs_BSplineSurface)  
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::BSpline");
-  return *((Handle(Geom_BSplineSurface)*)&mySurface);
+  return Handle(Geom_BSplineSurface)::DownCast (mySurface);
 }
 
 //=======================================================================
@@ -1238,7 +1343,7 @@ gp_Ax1 GeomAdaptor_Surface::AxeOfRevolution() const
 {
   if (mySurfaceType != GeomAbs_SurfaceOfRevolution)
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::AxeOfRevolution");
-  return (*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))->Axis();
+  return Handle(Geom_SurfaceOfRevolution)::DownCast (mySurface)->Axis();
 }
 
 //=======================================================================
@@ -1250,7 +1355,7 @@ gp_Dir GeomAdaptor_Surface::Direction() const
 {
   if (mySurfaceType != GeomAbs_SurfaceOfExtrusion)
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::Direction");
-  return (*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->Direction();
+  return Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (mySurface)->Direction();
 }
 
 //=======================================================================
@@ -1262,9 +1367,9 @@ Handle(Adaptor3d_HCurve) GeomAdaptor_Surface::BasisCurve() const
 {
   Handle(Geom_Curve) C;
   if (mySurfaceType == GeomAbs_SurfaceOfExtrusion)
-    C = (*((Handle(Geom_SurfaceOfLinearExtrusion)*)&mySurface))->BasisCurve();
+    C = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (mySurface)->BasisCurve();
   else if (mySurfaceType == GeomAbs_SurfaceOfRevolution)
-    C = (*((Handle(Geom_SurfaceOfRevolution)*)&mySurface))->BasisCurve();
+    C = Handle(Geom_SurfaceOfRevolution)::DownCast (mySurface)->BasisCurve();
   else
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::BasisCurve");
   return Handle(GeomAdaptor_HCurve)(new GeomAdaptor_HCurve(C));
@@ -1280,7 +1385,7 @@ Handle(Adaptor3d_HSurface) GeomAdaptor_Surface::BasisSurface() const
   if (mySurfaceType != GeomAbs_OffsetSurface) 
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::BasisSurface");
   return new GeomAdaptor_HSurface
-    ((*((Handle(Geom_OffsetSurface)*)&mySurface))->BasisSurface(),
+    (Handle(Geom_OffsetSurface)::DownCast (mySurface)->BasisSurface(),
      myUFirst,myULast,myVFirst,myVLast);
 }
 
@@ -1293,7 +1398,7 @@ Standard_Real GeomAdaptor_Surface::OffsetValue() const
 {
   if (mySurfaceType != GeomAbs_OffsetSurface) 
     Standard_NoSuchObject::Raise("GeomAdaptor_Surface::BasisSurface");
-  return (*((Handle(Geom_OffsetSurface)*)&mySurface))->Offset();
+  return Handle(Geom_OffsetSurface)::DownCast (mySurface)->Offset();
 }
 
 //=======================================================================
@@ -1313,7 +1418,8 @@ Standard_Boolean GeomAdaptor_Surface::IfUVBound(const Standard_Real U,
                                                 const Standard_Integer VSide) const
 {
   Standard_Integer Ideb,Ifin;
-  Standard_Integer anUFKIndx = myBspl->FirstUKnotIndex(), 
+  Handle(Geom_BSplineSurface) myBspl = Handle(Geom_BSplineSurface)::DownCast(mySurface);
+  Standard_Integer anUFKIndx = myBspl->FirstUKnotIndex(),
     anULKIndx = myBspl->LastUKnotIndex(), 
     aVFKIndx = myBspl->FirstVKnotIndex(), aVLKIndx = myBspl->LastVKnotIndex();
   myBspl->LocateU(U, PosTol, Ideb, Ifin, Standard_False);