The code below illustrates a number of possible techniques using the topographical library.
It generates a 3D object looking like this:
(The generated object has no actual function. It exists only for demonstration purposes)
Tools used:
• g++ version 4.7.3
• OpenCASCADE Community Edition 0.9.1-3
STEP models were converted into meshes using FreeCAD and then rendered in Povray.
#include <iostream> #include <gp_Ax2.hxx> #include <TopoDS_Shape.hxx> #include <BRepPrimAPI_MakeSphere.hxx> #include <TDocStd_Document.hxx> #include <Handle_TDocStd_Document.hxx> #include <XCAFApp_Application.hxx> #include <Handle_XCAFApp_Application.hxx> #include <XCAFDoc_ShapeTool.hxx> #include <Handle_XCAFDoc_ShapeTool.hxx> #include <XCAFDoc_DocumentTool.hxx> #include <STEPCAFControl_Writer.hxx> #include <StlAPI_Writer.hxx> #include <BRepPrimAPI_MakeSphere.hxx> #include <BRepFeat_MakeCylindricalHole.hxx> #include <BRepPrimAPI_MakeCylinder.hxx> #include <BRepBuilderAPI_Transform.hxx> #include <BRepAlgoAPI_Cut.hxx> #include <BRepAlgoAPI_Fuse.hxx> #include <BRepPrimAPI_MakeTorus.hxx> #include <TColgp_Array1OfPnt.hxx> #include <BRepPrimAPI_MakeRevol.hxx> #include <BRepBuilderAPI_MakeWire.hxx> #include <BRepBuilderAPI_MakeEdge.hxx> #include <BRepBuilderAPI_MakeFace.hxx> TopoDS_Shape Generate_Shape() { // Create a sphere with faces top and bottom Standard_Real sphere_radius = 1.0; Standard_Real sphere_angle = atan(0.5); gp_Ax2 sphere_origin = gp_Ax2(gp_Pnt(0,0,0), gp_Dir(0,0,1)); TopoDS_Shape sphere = BRepPrimAPI_MakeSphere(sphere_origin, sphere_radius, -sphere_angle, sphere_angle).Shape(); return sphere; } TopoDS_Shape Add_Feature(TopoDS_Shape& base) { // Add a "feature" to a shape. In this case we drill a hole through it. Standard_Real feature_diameter = 0.8; gp_Ax1 feature_origin = gp_Ax1(gp_Pnt(0,0,0), gp_Dir(0,0,1)); BRepFeat_MakeCylindricalHole feature_maker(base, feature_origin); feature_maker.Perform(feature_diameter / 2.0); return feature_maker.Shape(); } TopoDS_Shape Boolean_Cut(TopoDS_Shape& base) { // Create a cylinder, move it and subtract it (repeatedly) from the input shape // Array of cylinders on the right. Result of operation on the left. // Create a cylinder Standard_Real cylinder_radius = 0.25; Standard_Real cylinder_height = 2.0; gp_Ax2 cylinder_origin(gp_Pnt(0.0, 0.0, - cylinder_height / 2.0), gp_Dir(0.0, 0.0, 1.0)); BRepPrimAPI_MakeCylinder cylinder(cylinder_origin, cylinder_radius, cylinder_height); // Repeatedly move and subtract it from the input shape gp_Trsf move = gp_Trsf(); TopoDS_Shape boolean_result = base; TopoDS_Shape moved_cylinder; Standard_Real clone_radius = 1.0; for (int clone = 0; clone <= 7; ++clone) { double angle = clone * M_PI / 4.0; // Move the cylinder move.SetTranslation(gp_Vec(cos(angle) * clone_radius, sin(angle) * clone_radius, 0.0)); moved_cylinder = BRepBuilderAPI_Transform(cylinder.Shape(), move, true).Shape(); // Subtract the moved cylinder from the drilled sphere boolean_result = BRepAlgoAPI_Cut(boolean_result, moved_cylinder).Shape(); } return boolean_result; } TopoDS_Shape Boolean_Fuse(TopoDS_Shape& base) { // Create a torus and fuse it with the input shape. Standard_Real ring_radius = 0.25; Standard_Real torus_radius = 1.0 - ring_radius; BRepPrimAPI_MakeTorus torus(torus_radius, ring_radius); return BRepAlgoAPI_Fuse(base, torus.Shape()); } TopoDS_Shape Revolved_Cut(TopoDS_Shape& base) { // Create a hexagonal face. Use this face to create a solid by revolving // it around an axis. Subtract the generated shape (shown on the right) from // the input shape. // Define 7 points TColgp_Array1OfPnt FacePoints(1,7); Standard_Real face_inner_radius = 0.6; FacePoints(1) = gp_Pnt( face_inner_radius - 0.05, 0.0, -0.05 ); FacePoints(2) = gp_Pnt( face_inner_radius - 0.10, 0.0, -0.025); FacePoints(3) = gp_Pnt( face_inner_radius - 0.10, 0.0, 0.025); FacePoints(4) = gp_Pnt( face_inner_radius + 0.10, 0.0, 0.025); FacePoints(5) = gp_Pnt( face_inner_radius + 0.10, 0.0, -0.025); FacePoints(6) = gp_Pnt( face_inner_radius + 0.05, 0.0, -0.05 ); FacePoints(7) = gp_Pnt( face_inner_radius - 0.05, 0.0, -0.05 ); // Use these points to create edges and add these edges to a wire BRepBuilderAPI_MakeWire hexwire; for (Standard_Integer i = 1; i < 7; i++) { BRepBuilderAPI_MakeEdge hexedge(FacePoints(i), FacePoints(i+1)); hexwire.Add(hexedge); } // Turn the wire into a 6 sided face TopoDS_Face hexface = BRepBuilderAPI_MakeFace(hexwire.Wire()); // Revolve the face around an axis gp_Ax1 revolve_axis(gp_Pnt(0,0,0),gp_Dir(0,0,1)); TopoDS_Shape revolved_shape = BRepPrimAPI_MakeRevol(hexface, revolve_axis).Shape(); // Move the generated shape gp_Trsf move = gp_Trsf(); move.SetTranslation(gp_Pnt(0,0,0), gp_Pnt(0,0, sin(0.5))); TopoDS_Shape moved_shape = BRepBuilderAPI_Transform(revolved_shape, move, false); // Remove the revolved shape return BRepAlgoAPI_Cut(base, moved_shape).Shape(); } TopoDS_Shape Generate_Demo() { TopoDS_Shape basic_shape = Generate_Shape(); TopoDS_Shape featured_shape = Add_Feature(basic_shape); TopoDS_Shape cut_shape = Boolean_Cut(featured_shape); TopoDS_Shape fused_shape = Boolean_Fuse(cut_shape); TopoDS_Shape revolved_shape = Revolved_Cut(fused_shape); return revolved_shape; } void Write_STEP(const TopoDS_Shape& shape) { // Create document Handle(TDocStd_Document) aDoc; Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication(); anApp->NewDocument("MDTV-XCAF",aDoc); // Create label and add our shape Handle (XCAFDoc_ShapeTool) myShapeTool = XCAFDoc_DocumentTool::ShapeTool(aDoc->Main()); TDF_Label aLabel = myShapeTool->NewShape(); myShapeTool->SetShape(aLabel, shape); // Write as STEP file STEPCAFControl_Writer *myWriter = new STEPCAFControl_Writer(); myWriter->Perform(aDoc,"demo1.stp"); } void Write_STL(const TopoDS_Shape& shape) { // Write as STL StlAPI_Writer stl_writer; stl_writer.SetDeflection(0.001); stl_writer.RelativeMode() = false; stl_writer.Write(shape, "demo1.stl"); } int main() { TopoDS_Shape generated_shape = Generate_Demo(); Write_STEP(generated_shape); Write_STL(generated_shape); std::cout << std::endl << "Press a key to continue"; std::cin.get(); return 0; }(Download source)