Building 3D Models with pythonOCC: Practical Examples

Building 3D Models with pythonOCC: Practical ExamplesCreating 3D models programmatically can unlock repeatable, parametric, and automatable design workflows. pythonOCC is a Python wrapper around the Open CASCADE Technology (OCCT) geometry kernel, giving access to powerful CAD modeling, boolean operations, meshing, and file export functions. This article walks through practical examples that progressively demonstrate how to build, modify, and export 3D models using pythonOCC — from basic shapes to assemblies and exporting for visualization or FEM.


What is pythonOCC (brief)

pythonOCC exposes OCCT functionality to Python, letting you create BRep geometry (edges, wires, faces, shells, solids), perform boolean operations, apply transformations, and export to industry formats such as STEP and STL. It’s suitable for parametric CAD, procedural model generation, and integration with scientific/engineering Python stacks.


Setup and environment

Install pythonOCC from pip (depending on platform and OCCT build availability, you may prefer conda):

pip install --upgrade --pre pythonocc-core 

On some systems a conda package is more reliable:

conda install -c conda-forge pythonocc-core 

Typical imports used in the examples below:

from OCC.Core.gp import gp_Pnt, gp_Dir, gp_Ax1, gp_Trsf, gp_Vec from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeCylinder, BRepPrimAPI_MakeSphere from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse, BRepAlgoAPI_Cut from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeEdge, BRepBuilderAPI_MakeWire, BRepBuilderAPI_MakeFace from OCC.Core.BRep import BRep_Tool from OCC.Core.BRepTools import breptools_Write from OCC.Core.STEPControl import STEPControl_Writer, STEPControl_AsIs from OCC.Core.StlAPI import StlAPI_Writer from OCC.Core.TopLoc import TopLoc_Location 

Note: some example code below omits import lines for brevity — include necessary imports when running code.


Example 1 — Basic primitives and transformations

Goal: create a box, cylinder, and sphere, then arrange them with simple translations and rotations.

Key steps:

  • Create primitives
  • Apply gp_Trsf transformations
  • Combine into one compound (or keep separate)

Example:

from OCC.Core.gp import gp_Pnt, gp_Vec, gp_Trsf from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeCylinder, BRepPrimAPI_MakeSphere from OCC.Core.TopLoc import TopLoc_Location from OCC.Core.TopoDS import TopoDS_Compound, TopoDS_Builder # primitives box = BRepPrimAPI_MakeBox(40.0, 30.0, 20.0).Shape() cyl = BRepPrimAPI_MakeCylinder(10.0, 40.0).Shape() sph = BRepPrimAPI_MakeSphere(12.0).Shape() # move cylinder up tr = gp_Trsf() tr.SetTranslation(gp_Vec(20, 15, 20)) cyl.Location = TopLoc_Location(tr)  # assign location (or use BRepBuilderAPI_Transform) # move sphere to corner tr2 = gp_Trsf() tr2.SetTranslation(gp_Vec(-10, -10, 10)) sph.Location = TopLoc_Location(tr2) # create compound comp = TopoDS_Compound() builder = TopoDS_Builder() builder.MakeCompound(comp) builder.Add(comp, box) builder.Add(comp, cyl) builder.Add(comp, sph) # export STEP from OCC.Core.STEPControl import STEPControl_Writer, STEPControl_AsIs step_writer = STEPControl_Writer() step_writer.Transfer(comp, STEPControl_AsIs) step_writer.Write("primitives.step") 

Notes:

  • Using TopLoc_Location assignment is a quick way to place shapes; BRepBuilderAPI_Transform produces a transformed copy.
  • Units are consistent but not implicitly tied to meters — document your units.

Example 2 — Creating a lofted shape (sweeps and lofts)

Goal: loft a set of cross-section wires to create a smooth-bodied part (useful for hulls, ducts, handles).

Key steps:

  • Create profile wires (circles, rectangles) at different planes
  • Use BRepOffsetAPI_ThruSections (or BRepOffsetAPI_ThruSections) to generate a loft

Example:

from OCC.Core.gp import gp_Ax2, gp_Pnt, gp_Dir from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeWire from OCC.Core.GC import GC_MakeCircle from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeEdge from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_ThruSections # create circular profiles at different Z positions def circle_wire(radius, z):     center = gp_Pnt(0, 0, z)     circ = GC_MakeCircle(gp_Ax2(center, gp_Dir(0,0,1)), radius).Value()     edge = BRepBuilderAPI_MakeEdge(circ).Edge()     wire = BRepBuilderAPI_MakeWire(edge).Wire()     return wire w1 = circle_wire(10.0, 0.0) w2 = circle_wire(8.0, 20.0) w3 = circle_wire(4.0, 40.0) loft = BRepOffsetAPI_ThruSections(True, False, 1.0e-3) loft.AddWire(w1) loft.AddWire(w2) loft.AddWire(w3) loft.Build() shape = loft.Shape() 

Tips:

  • Adjust the tolerance and ruled/solid parameters for expected surface behavior.
  • Profiles must be oriented consistently.

Example 3 — Boolean operations: cut, fuse, common

Goal: subtract holes, fuse parts, and find intersections.

Example: create a box with cylindrical holes and subtract them.

from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Cut from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox, BRepPrimAPI_MakeCylinder from OCC.Core.gp import gp_Vec, gp_Trsf from OCC.Core.TopLoc import TopLoc_Location box = BRepPrimAPI_MakeBox(100, 60, 30).Shape() # three cylinders through the box cyls = [] for x in (20, 50, 80):     c = BRepPrimAPI_MakeCylinder(5, 40).Shape()     tr = gp_Trsf()     tr.SetTranslation(gp_Vec(x, 30, 0))     c.Location = TopLoc_Location(tr)     cyls.append(c) # subtract successive cylinders result = box for c in cyls:     result = BRepAlgoAPI_Cut(result, c).Shape() # export STL from OCC.Core.StlAPI import StlAPI_Writer stl_writer = StlAPI_Writer() stl_writer.Write(result, "box_with_holes.stl") 

Notes:

  • Boolean operations can fail if geometry is ill-conditioned; increasing tolerances or refining geometry helps.
  • For many boolean operations, using BOPAlgo module can be more robust.

Example 4 — Building parametric parts: a bolt-like fastener

Goal: programmatically generate a parametric bolt (hex head, threaded cylinder approximated).

Approach:

  • Create hexagon profile, extrude for head
  • Create shaft as cylinder
  • Optionally model coarse threads by sweeping a triangular profile along a helix (or skip for simplified model)
  • Fuse head and shaft

Example (simplified head + shaft):

from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeCylinder from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakePolygon from OCC.Core.BRepOffsetAPI import BRepOffsetAPI_MakeThickSolid from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakePrism from OCC.Core.gp import gp_Vec # hexagon head poly = BRepBuilderAPI_MakePolygon() r = 8.0 import math for i in range(6):     angle = math.radians(60*i)     poly.Add(gp_Pnt(r*math.cos(angle), r*math.sin(angle), 0)) poly.Close() wire = poly.Wire() face = BRepBuilderAPI_MakeFace(wire).Face() head = BRepPrimAPI_MakePrism(face, gp_Vec(0,0,4)).Shape() # shaft shaft = BRepPrimAPI_MakeCylinder(3.5, 16).Shape() # position shaft under head from OCC.Core.gp import gp_Trsf from OCC.Core.TopLoc import TopLoc_Location tr = gp_Trsf() tr.SetTranslation(gp_Vec(0,0,-16)) shaft.Location = TopLoc_Location(tr) # fuse from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse bolt = BRepAlgoAPI_Fuse(head, shaft).Shape() 

For real threads: create a helix curve (GCE2d or using BRepOffsetAPI_MakePipeShell) and sweep a triangular profile. That is more advanced but possible with pythonOCC.


Example 5 — Meshing and exporting for FEM/3D printing

Goal: export watertight solids to STL with sufficient mesh density.

Key steps:

  • Ensure shape is a closed solid
  • Use StlAPI_Writer or meshing tools (e.g., OCC meshing via BRepMesh_IncrementalMesh)
  • Control deflection to control triangle size

Example:

from OCC.Core.BRepMesh import BRepMesh_IncrementalMesh # 'shape' should be a solid mesh = BRepMesh_IncrementalMesh(shape, 0.5)  # deflection controls accuracy mesh.Perform() from OCC.Core.StlAPI import StlAPI_Writer stl_w = StlAPI_Writer() stl_w.Write(shape, "export.stl") 

Notes:

  • Smaller deflection => finer mesh and larger files.
  • Always check manifoldness and normals orientation before printing.

Visualization options

  • pythonOCC includes a Qt-based 3D viewer. Use OCC.Display.SimpleGui.init_display() for quick interactive previews.
  • For headless rendering/exporting, convert to mesh and use external tools (trimesh, pyglet, or Blender via import).
  • Export STEP for CAD interoperability, STL for printing, and VRML/OBJ for visualization.

Quick display snippet:

from OCC.Display.SimpleGui import init_display display, start_display, add_menu, add_function_to_menu = init_display() display.DisplayShape(bolt, update=True) start_display() 

Best practices and pitfalls

  • Work in consistent units and document them.
  • Keep tolerances in mind; OCCT uses geometric tolerances that affect boolean ops and meshing.
  • Prefer creating solids (closed shells) when intending to export as STL or STEP.
  • Complex booleans sometimes require healing (shape.fix or using BOPAlgo tools).
  • For parametric parts, encapsulate geometry construction in functions that accept parameters (dimensions, fillet radii, etc.).

Where to go next

  • Learn advanced topology tools: wires/wire-building, edge/face manipulation, sewing and shell building.
  • Explore BRepOffsetAPI for fillets, chamfers, and thickening.
  • Integrate with numpy, trimesh, or FEM tools to run analyses on generated geometry.
  • Study the pythonOCC examples repository and OCCT documentation for deeper API insights.

Practical examples here give a foundation to start building parametric 3D parts with pythonOCC. Adapt the snippets to your geometry and refine tolerances and meshing parameters as needed.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *