public static List <TessalatedShape> Triangulate(TopoDS.Shape topoShape) { TopExp.Explorer ex = new TopExp.Explorer(topoShape, TopAbs.ShapeEnum.FACE, TopAbs.ShapeEnum.SHAPE); BRepMesh.General.Mesh(topoShape, 0.1); List <TessalatedShape> faces = new List <TessalatedShape>(); // Loop all faces while (ex.More()) { TessalatedShape shape = new TessalatedShape(); TopoDS.Face F = TopoDS.General.Face(ex.Current()); TopLoc.Location location = new TopLoc.Location(); Poly.Triangulation triangulation = BRep.Tool.Triangulation(F, location); Poly.Array1OfTriangle arrayOfTriangle = triangulation.Triangles(); TColgp.Array1OfPnt p3d = triangulation.Nodes(); shape.points = new gp.Pnt[p3d.Length()]; for (int i = 0; i < shape.points.Length; ++i) { shape.points[i] = p3d.Value(i + 1); } if (location != null) { gp.Trsf trsf = location.Transformation(); for (int i = 0; i < shape.points.Length; ++i) { trsf.Transforms(out shape.points[i].x, out shape.points[i].y, out shape.points[i].z); } } TColgp.Array1OfPnt2d p2d = triangulation.UVNodes(); if (p2d != null) { shape.uvpoints = new gp.Pnt2d[p2d.Length()]; for (int i = 0; i < shape.uvpoints.Length; ++i) { shape.uvpoints[i] = p2d.Value(i + 1); } } else { shape.uvpoints = null; } shape.triangles = new int[arrayOfTriangle.Length() * 3]; int l = arrayOfTriangle.Length(); for (int i = 0; i < l; ++i) { Poly.Triangle t = arrayOfTriangle.Value(i + 1); shape.triangles[3 * i] = t.Value(1) - 1; shape.triangles[3 * i + 1] = t.Value(2) - 1; shape.triangles[3 * i + 2] = t.Value(3) - 1; } faces.Add(shape); ex.Next(); } return(faces); }
/// <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> public static 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; }
/// <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); }
public static List<TessalatedShape> Triangulate(TopoDS.Shape topoShape) { TopExp.Explorer ex = new TopExp.Explorer(topoShape, TopAbs.ShapeEnum.FACE, TopAbs.ShapeEnum.SHAPE); BRepMesh.General.Mesh(topoShape, 0.1); List<TessalatedShape> faces = new List<TessalatedShape>(); // Loop all faces while (ex.More()) { TessalatedShape shape = new TessalatedShape(); TopoDS.Face F = TopoDS.General.Face(ex.Current()); TopLoc.Location location = new TopLoc.Location(); Poly.Triangulation triangulation = BRep.Tool.Triangulation(F, location); Poly.Array1OfTriangle arrayOfTriangle = triangulation.Triangles(); TColgp.Array1OfPnt p3d = triangulation.Nodes(); shape.points = new gp.Pnt[p3d.Length()]; for (int i = 0; i < shape.points.Length; ++i) { shape.points[i] = p3d.Value(i + 1); } if (location != null) { gp.Trsf trsf = location.Transformation(); for (int i = 0; i < shape.points.Length; ++i) { trsf.Transforms(out shape.points[i].x, out shape.points[i].y, out shape.points[i].z); } } TColgp.Array1OfPnt2d p2d = triangulation.UVNodes(); if (p2d != null) { shape.uvpoints = new gp.Pnt2d[p2d.Length()]; for (int i = 0; i < shape.uvpoints.Length; ++i) { shape.uvpoints[i] = p2d.Value(i + 1); } } else { shape.uvpoints = null; } shape.triangles = new int[arrayOfTriangle.Length() * 3]; int l = arrayOfTriangle.Length(); for (int i = 0; i < l; ++i) { Poly.Triangle t = arrayOfTriangle.Value(i + 1); shape.triangles[3 * i] = t.Value(1) - 1; shape.triangles[3 * i + 1] = t.Value(2) - 1; shape.triangles[3 * i + 2] = t.Value(3) - 1; } faces.Add(shape); ex.Next(); } return faces; }