Python bindings over OpenCASCADE Technology (OCCT), built with pybind11. Two layers:
- Core bindings (
src/bind_*.cpp): preserve OCCT class names and module structure (Geom.BSplineCurve,BRepBuilderAPI.MakeFace). Methods become snake_case but class names stay. Coverage of OCCT is intentionally partial. extend/layer (src/extend/*): modern Python-ergonomic helpers that take and return OCCT types. This is where the 30-year ergonomic debt of OCCT is repaid without hiding OCCT.
Target audience: engineers who use (or want to use) OCCT and need Python ergonomics — CFD, turbomachinery, metrology, scripted CAD workflows.
NOT the audience: hobbyist parametric modeling with fluent DSLs (cadquery, build123d). Do not propose fluent/chainable APIs, shape wrapper classes, or DSLs that hide OCCT — those belong in downstream libraries.
- Helpers take and return OCCT types —
TopoDS_*,Geom_*,gp_*. No wrapper classes. extend/for ergonomics, never the core bindings. Core stays close to OCCT.extend/must earn its keep. Don't add pure sugar over a single OCCT call. Justify with: edge-case handling, parallelism, better errors, multi-step workflows that compose several OCCT APIs.- Prefer pybind11 methods on OCCT classes for discoverable helpers
when possible.
shape.union_faces()>extend.brep.union_faces(shape). - Partial coverage is fine. Don't bind everything just to mirror OCCT.
src/
bind_*.cpp core bindings, one file per OCCT module
extend/
bindings/ pybind11 utility headers
brep/ high-level BRep helpers (ExtrudeCut, RevolveCut, UnionFaces)
containers/ OCCT → std conversions
extrema/ distance/proximity helpers (parallel ExtCC)
gbs/ GBS ↔ OCCT B-spline conversions
geometry/ Geom_* utilities
render/ tessellation + export
topology/ shape enumeration / exploration
stubs/mod3d/ auto-generated by pybind11-stubgen during install
tests/ pytest, mirrors module structure
Target OCCT 7.9.x and 8.0.x concurrently. Use OCC_VERSION_HEX guards
with <Standard_Version.hxx> for renamed APIs (example in
bind_geom2d_curves.cpp for Geom2dLProp_CLProps2d → GeomLProp_CLProps2d).
For broken transitive includes (e.g. gp_Ax1, TopTools_ListOfShape in 8.x),
add the explicit include directly — no guard needed.
cmake -B build -S . -G Ninja -DCMAKE_BUILD_TYPE=Release -DMOD3D_USE_GBS=OFF
cmake --build build --parallel
cmake --install build # regenerates stubs/
pytest tests/ -vCI runs Linux + Windows + macOS via mamba-org/setup-micromamba@v2. The
Windows job carries workarounds (init-shell: none, manual CONDA_PREFIX export)
because the windows-2025-vs2026 runner image's pre-installed micromamba
crashes on shell init.
Imperative present, no Co-Authored-By trailer. Explain why, not just what. For OCCT adaptations, name the breaking change and the OCCT version.
Loosely ranked by impact-for-target-audience. Items aren't commitments; they describe direction. Pick one and open an issue/branch.
-
extend/turbo/— turbomachinery helpers: leading/trailing edge detection onTopoDS_Face, hub/shroud surface extraction, meridional projection along agp_Ax1, blade-to-blade sections returningList[TopoDS_Wire]. Unique to Mod3D's domain — no other Python lib does this from OCCT shapes directly. -
extend/section/— cross-sectioning utilities: shape × plane → wires, shape × axis × N → ordered sections. Useful for CFD prep, visualization, and 3D-print slicing.
-
export_stl(shape, path, deflection=0.1, ascii=False)— wrapsBRepMesh_IncrementalMesh+StlAPI_Writerwith sane defaults. -
export_obj(shape, path, deflection=0.1)— same idea viaRWObj_CafWriteror manual triangulation walk. -
export_gltf(shape, path, deflection=0.1)—RWGltf_CafWriterwrapper. Useful for web viewers / pythreejs alternatives. - Common deflection/precision policy: helper that picks a sensible default from bounding-box diagonal.
-
ShapeFix: completeSetSurface, multi-argInit,ShapeAnalysis_Surfaceintegration (surfaced during OCCT 8.x migration). Also boundShapeAnalysis_Wirealong the way so theInit(saw)handoff is reachable. -
BRepFillet/BRepFilletAPI: variable-radius fillets, chamfers with selection by edge collection. -
BRepOffsetAPI: thickening, draft, shelling with face selection. - STEP entity hierarchy: named-entity access, assembly tree walk
(currently
StepControlis read/write-only on geometry).
- Typed Python exceptions for OCCT errors. Currently
Standard_Failuresurfaces asRuntimeError. Add amod3d.OcctErrorhierarchy that exposesExceptionType()andwhat(). Quick win, big readability gain. (Standard_Failure now derives from std::exception in 8.x — easier than before.) - Method-style binding for
extend/helpers. Where it makes sense, bindextend.brep.union_facesas a method onTopoDS.Shape(not only as a free function) so it appears in autocomplete onshape.. - Onboarding pass on
extend/: README section listing what's in there and when to reach for it vs. the core bindings. - Track the example notebooks currently untracked
(
examples/usage_examples.ipynb,examples/volute.ipynb,examples/vista.py) — decide what's reference material vs. scratch.
- Point cloud →
Geom_BSplineSurfacefitting via GBS, returning pure OCCT types. Capitalize on the user's GBS expertise. - Multi-curve lofting →
Geom_BSplineSurface. Same philosophy. - Free-Form Deformation (FFD) for shape morphing on
TopoDS_Shape.
- Retest Windows runner periodically to see if the broken
pre-installed micromamba is fixed upstream; remove the workarounds
(
micromamba-version: 1.5.10-0,init-shell: none, manual env activation) once it's safe. - Upgrade
actions/checkoutandmamba-org/setup-micromambaonce they support Node 24 (deprecation warning today). - Add OCCT 7.9 to the CI matrix as a compatibility check, or document the local-only validation policy.
- Clean up pre-existing clang-tidy warnings (unused-RAII at the top of
bind_brep_prim_api_sweep.cpp). - Investigate the harmless CMake warning "manually-specified variables not used: CMAKE_C_COMPILER" on Windows.