Open CASCADE basic example

The code below illustrates a number of possible techniques using the topographical library.


It generates a 3D object looking like this:

A 3D object

(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
Step 1
    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.
Step 2
    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.

Step 3

    // 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.

Step 4
    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.

Step 5
    // 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)