SOFA GmbH - Open Cascade .NET Wrapper Demo Source


using System;
using OpenCascade; // this is the main namespace for all OpenCascade classes

namespace OpenCascadeTest
{
   /// <summary>
   /// Class to implement the static MakeBottle method in C# as provideded as an
   /// example in the OpenCascade Tutorial.
   /// </summary>
   public class Bottle
   {
      /// <summary>
      /// Adopted from the OpenCascade Tutorial "My First Application"
      /// </summary>
      /// <param name="myWidth">width of the bottle</param>
      /// <param name="myHeight">height of the bottle</param>
      /// <param name="myThickness">thickness of the bottle skin</param>
      /// <returns>the shape of the bottle</returns>
      static public TopoDS.Shape MakeBottle(double myWidth, double myHeight, double myThickness)
      {
         //Profile : Define Support Points
         gp.Pnt aPnt1 = new gp.Pnt(-myWidth / 2.0, 0, 0);
         gp.Pnt aPnt2 = new gp.Pnt(-myWidth / 2.0, -myThickness / 4.0, 0);
         gp.Pnt aPnt3 = new gp.Pnt(0, -myThickness / 2.0, 0);
         gp.Pnt aPnt4 = new gp.Pnt(myWidth / 2.0, -myThickness / 4.0, 0);
         gp.Pnt aPnt5 = new gp.Pnt(myWidth / 2.0, 0, 0);
         //Profile : Define the Geometry
         Geom.TrimmedCurve aArcOfCircle = (new GC.MakeArcOfCircle(ref aPnt2, ref aPnt3, ref aPnt4)).Value();
         // note: all constructors have to be called in C# with the new keyword in C#
         Geom.TrimmedCurve aSegment1 = (new GC.MakeSegment(ref aPnt1, ref aPnt2)).Value();
         Geom.TrimmedCurve aSegment2 = (new GC.MakeSegment(ref aPnt4, ref aPnt5)).Value();
         //Profile : Define the Topology
         TopoDS.Edge aEdge1 = (new BRepBuilderAPI.MakeEdge(aSegment1)).Edge();
         TopoDS.Edge aEdge2 = (new BRepBuilderAPI.MakeEdge(aArcOfCircle)).Edge();
         TopoDS.Edge aEdge3 = (new BRepBuilderAPI.MakeEdge(aSegment2)).Edge();
         TopoDS.Wire aWire = (new BRepBuilderAPI.MakeWire(aEdge1, aEdge2, aEdge3)).Wire();
         //Complete Profile
         gp.Ax1 xAxis = gp.General.OX();
         gp.Trsf aTrsf = new gp.Trsf();
         aTrsf.SetMirror(ref xAxis);
         BRepBuilderAPI.Transform aBRepTrsf = new BRepBuilderAPI.Transform(aWire, aTrsf, false);
         TopoDS.Shape aMirroredShape = aBRepTrsf.Shape();
         TopoDS.Wire aMirroredWire = TopoDS.General.Wire(aMirroredShape);
         // note: General is the key to use static namespace methods (TopoDS is a namespace), 
         // since there is no such thing in C#

         BRepBuilderAPI.MakeWire mkWire = new BRepBuilderAPI.MakeWire();

         mkWire.Add(aWire);
         mkWire.Add(aMirroredWire);
         TopoDS.Wire myWireProfile = mkWire.Wire();
         //Body : Prism the Profile
         TopoDS.Face myFaceProfile = (new BRepBuilderAPI.MakeFace(myWireProfile, false)).Face();
         gp.Vec aPrismVec = new gp.Vec(0, 0, myHeight);
         TopoDS.Shape myBody = (new BRepPrimAPI.MakePrism(myFaceProfile, ref aPrismVec, false, true)).Shape();
         //Body : Apply Fillets
         BRepFilletAPI.MakeFillet mkFillet = new BRepFilletAPI.MakeFillet(myBody, ChFi3d.FilletShape.Rational);
         TopExp.Explorer aEdgeExplorer = new TopExp.Explorer(myBody, TopAbs.ShapeEnum.EDGE, TopAbs.ShapeEnum.SHAPE);
         while (aEdgeExplorer.More())
         {
            TopoDS.Edge aEdge = TopoDS.General.Edge(aEdgeExplorer.Current());
            //Add edge to fillet algorithm
            mkFillet.Add(myThickness / 12.0, aEdge);
            aEdgeExplorer.Next();
         }
         myBody = mkFillet.Shape();
         //Body : Add the Neck
         gp.Pnt neckLocation = new gp.Pnt(0, 0, myHeight);
         gp.Dir neckNormal = new gp.Dir(0, 0, 1);
         gp.Ax3 neckAx3; 
         neckAx3.axis.loc = neckLocation;
         neckAx3.axis.vdir = neckNormal;
         neckAx3.vxdir = new gp.Dir(1, 0, 0);
         neckAx3.vydir = new gp.Dir(0, 1, 0);
         gp.Ax2 neckAx2; 
         neckAx2.axis.loc = neckLocation;
         neckAx2.axis.vdir = neckNormal;
         neckAx2.vxdir = new gp.Dir(1, 0, 0);
         neckAx2.vydir = new gp.Dir(0, 1, 0);

         double myNeckRadius = myThickness / 4.0;
         double myNeckHeight = myHeight / 10;
         TopoDS.Shape myNeck = (new BRepPrimAPI.MakeCylinder(ref neckAx2, myNeckRadius, myNeckHeight)).Shape();
         myBody = (new BRepAlgoAPI.Fuse(myBody, myNeck)).Shape();

         //Body : Create a Hollowed Solid
         TopoDS.Face faceToRemove = null;
         double zMax = -1;
         for (TopExp.Explorer aFaceExplorer = new TopExp.Explorer(myBody, TopAbs.ShapeEnum.FACE, TopAbs.ShapeEnum.SHAPE);
            aFaceExplorer.More(); aFaceExplorer.Next())
         {
            TopoDS.Face aFace = TopoDS.General.Face(aFaceExplorer.Current());

            //Check if <aFace> is the top face of the bottle’s neck
            Geom.Surface aSurface = BRep.Tool.Surface(aFace);
            if (aSurface is Geom.Plane)
            {
               Geom.Plane aPlane = aSurface as Geom.Plane;
               // note: the powerful as an is operators also work with the OpenCascade class hierarchy (polymorphism)
               gp.Pnt aPnt = aPlane.Location();
               double aZ = aPnt.z;
               if (aZ > zMax)
               {
                  zMax = aZ;
                  faceToRemove = aFace;
               }
            }
         }
         TopTools.ListOfShape facesToRemove = new TopTools.ListOfShape();
         facesToRemove.Append(faceToRemove);
         myBody = (new BRepOffsetAPI.MakeThickSolid(myBody, facesToRemove, -myThickness / 60, 1.0e-3, BRepOffset.Mode.Skin, false, false, GeomAbs.JoinType.Arc)).Shape();
         //Threading : Create Surfaces
         Geom.CylindricalSurface aCyl1 = new Geom.CylindricalSurface(ref neckAx3, myNeckRadius * 0.99);
         Geom.CylindricalSurface aCyl2 = new Geom.CylindricalSurface(ref neckAx3, myNeckRadius * 1.05);
         //Threading : Define 2D Curves
         gp.Pnt2d bPnt = new gp.Pnt2d(2.0 * Math.PI, myNeckHeight / 2.0);
         gp.Dir2d aDir = new gp.Dir2d(2.0 * Math.PI, myNeckHeight / 4.0);

         gp.Ax22d aAx22d = new gp.Ax22d();
         aAx22d.point = bPnt;
         aAx22d.vxdir = aDir;
         aAx22d.vydir = new gp.Dir2d(-aDir.y, aDir.x);

         double aMajor = 2.0 * Math.PI;
         double aMinor = myNeckHeight / 10;
         Geom2d.Ellipse anEllipse1 = new Geom2d.Ellipse(ref aAx22d, aMajor, aMinor);
         Geom2d.Ellipse anEllipse2 = new Geom2d.Ellipse(ref aAx22d, aMajor, aMinor / 4);
         Geom2d.TrimmedCurve aArc1 = new Geom2d.TrimmedCurve(anEllipse1, 0, Math.PI, true);
         Geom2d.TrimmedCurve aArc2 = new Geom2d.TrimmedCurve(anEllipse2, 0, Math.PI, true);
         gp.Pnt2d anEllipsePnt1 = anEllipse1.Value(0);
         gp.Pnt2d anEllipsePnt2 = anEllipse1.Value(Math.PI);
         Geom2d.TrimmedCurve aSegment = (new GCE2d.MakeSegment(ref anEllipsePnt1, ref anEllipsePnt2)).Value();
         //Threading : Build Edges and Wires
         TopoDS.Edge aEdge1OnSurf1 = (new BRepBuilderAPI.MakeEdge(aArc1, aCyl1)).Edge();
         TopoDS.Edge aEdge2OnSurf1 = (new BRepBuilderAPI.MakeEdge(aSegment, aCyl1)).Edge();
         TopoDS.Edge aEdge1OnSurf2 = (new BRepBuilderAPI.MakeEdge(aArc2, aCyl2)).Edge();
         TopoDS.Edge aEdge2OnSurf2 = (new BRepBuilderAPI.MakeEdge(aSegment, aCyl2)).Edge();
         TopoDS.Wire threadingWire1 = (new BRepBuilderAPI.MakeWire(aEdge1OnSurf1, aEdge2OnSurf1)).Wire();
         TopoDS.Wire threadingWire2 = (new BRepBuilderAPI.MakeWire(aEdge1OnSurf2, aEdge2OnSurf2)).Wire();
         BRepLib.General.BuildCurves3d(threadingWire1);
         BRepLib.General.BuildCurves3d(threadingWire2);
         //Create Threading
         BRepOffsetAPI.ThruSections aTool = new BRepOffsetAPI.ThruSections(true, false, 1e-6);
         aTool.AddWire(threadingWire1);
         aTool.AddWire(threadingWire2);
         aTool.CheckCompatibility(false);
         TopoDS.Shape myThreading = aTool.Shape();
         //Building the Resulting Compound
         TopoDS.Compound aRes = new TopoDS.Compound();
         BRep.Builder aBuilder = new BRep.Builder();
         aBuilder.MakeCompound(aRes);
         aBuilder.Add(aRes, myBody);
         aBuilder.Add(aRes, myThreading);
         return aRes;
      }
   }
}