3. Geometry kernel APIs and Python bindings

Automated model preparation is only as capable as the geometry kernel underneath it. A kernel provides the mathematical and topological services that let a script create solids, heal gaps, imprint features, and query mass properties. Python rarely talks to a kernel directly; it goes through a binding layer. Understanding which kernel you are driving, and how the binding exposes it, determines what your automation can and cannot do.

Three kernels dominate industrial CAE preprocessing: OpenCASCADE Technology (OCCT), ACIS, and Parasolid. OCCT is open source and reachable from Python through pythonocc-core. ACIS and Parasolid are commercial kernels owned by Spatial (Dassault Systèmes) and Siemens respectively, and their Python access is normally indirect — through a host application's scripting API, a vendor SDK wrapper, or a C++/C# bridge. This chapter compares their access patterns and shows how to write kernel-aware preparation code.

What a Kernel Actually Exposes

Every kernel separates geometry (curves and surfaces) from topology (vertices, edges, faces, shells, solids). The topology is a boundary representation (B-rep): a solid is a closed shell of faces, each face is trimmed by edges, and each edge is bounded by vertices. Preparation operations act on this structure:

  • Construction — extrude, revolve, loft, boolean union/cut/intersect.
  • Healing — sew faces, fix small edges, remove slivers, unify same-domain faces.
  • Defeaturing — suppress fillets, chamfers, holes, and bosses before meshing.
  • Query — bounding box, volume, surface area, point classification, face normal.
  • Translation — STEP, IGES, and native format read/write.

The binding's job is to map these C++ classes into Python objects with reference counting and exception translation. That mapping is where the three access patterns diverge.

OpenCASCADE via pythonocc-core

pythonocc-core is a SWIG-generated binding that mirrors OCCT's class names almost one-to-one. A face is TopoDS_Face, a solid is TopoDS_Solid, and algorithms live in packages such as BRepAlgoAPI, BRepBuilderAPI, and ShapeFix. Because the naming is faithful, OCCT documentation transfers directly to Python.

from OCC.Core.STEPControl import STEPControl_Reader
from OCC.Core.ShapeFix import ShapeFix_Shape
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Fuse
from OCC.Core.GProp import GProp_GProps
from OCC.Core.BRepGProp import brepgprop_VolumeProperties

reader = STEPControl_Reader()
reader.ReadFile("bracket.step")
reader.TransferRoots()
shape = reader.OneShape()

fixer = ShapeFix_Shape(shape)
fixer.Perform()
healed = fixer.Shape()

props = GProp_GProps()
brepgprop_VolumeProperties(healed, props)
print("volume =", props.Mass())

Two practical notes. First, OCCT algorithms return a new shape; they do not mutate in place, so you must rebind your variable. Second, many operations report status through a boolean or an error code rather than raising, so check IsDone() after boolean and healing calls. A silent failure that returns the original shape is a common source of downstream meshing errors.

ACIS and Parasolid Access Patterns

ACIS and Parasolid are not distributed as standalone Python packages. Their Python access follows three patterns:

PatternHow it worksTypical use
Host application APIThe CAD/CAE tool embeds the kernel and exposes a Python or macro APIScripting inside the vendor tool
Vendor SDK wrapperA C++ SDK is wrapped with pybind11 or SWIG by the integratorCustom preprocessing pipelines
Inter-process bridgePython calls a compiled service over a socket or COM/.NET boundaryMixed-language enterprise stacks

In ACIS, the core object is ENTITY, and a solid body is a BODY containing LUMP, SHELL, FACE, EDGE, and VERTEX entities. Healing is done through the api_* function family, for example api_clean_entity and api_fix_face. Parasolid uses a tagged-entity model: every object carries a PK_ENTITY_t tag, and functions are prefixed PK_, such as PK_BODY_fix and PK_FACE_find_gaps. Parasolid's session model requires you to start a session, create a partition, and roll back on failure — a pattern that must be respected in any wrapper.

When wrapping ACIS or Parasolid yourself, keep the kernel session alive for the whole script. Creating and destroying a session per operation is slow and can leak tags.

Choosing an Access Path

For a pure-Python automation stack with no commercial CAD dependency, pythonocc-core is the pragmatic default: it installs from conda-forge, reads STEP and IGES, and exposes healing and defeaturing. Choose ACIS or Parasolid access when your models are native to those kernels and round-tripping through STEP would lose tolerant topology or feature history. In that case, drive the kernel through the host application's Python API rather than reimplementing a wrapper.

The diagram below contrasts the three access paths and the layer at which Python code meets each kernel.

Python Access Paths to Geometry Kernels Python Automation Script healing · defeaturing · boolean ops · mass properties · STEP I/O pythonocc-core (SWIG) TopoDS_Shape · BRepAlgoAPI ShapeFix_Shape direct in-process binding ACIS (Spatial) ENTITY · BODY · api_* functions host API or pybind11 wrapper api_clean_entity · api_fix_face Parasolid (Siemens) PK_ENTITY_t tags · session PK_BODY_fix · PK_FACE_find_gaps bridge or vendor SDK Geometry Kernel — B-rep Topology + NURBS Geometry vertices · edges · faces · shells · solids · tolerant modeling Clean solid → mesh-ready model for CAE

A Reproducible Healing Example

Consider a STEP bracket that imports with two free edges along a seam. The goal is a watertight solid suitable for tetrahedral meshing. Using pythonocc-core, the workflow is: read, inspect, sew, fix, verify.

from OCC.Core.STEPControl import STEPControl_Reader
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_Sewing
from OCC.Core.ShapeFix import ShapeFix_Shape, ShapeFix_Solid
from OCC.Core.TopAbs import TopAbs_SOLID
from OCC.Core.TopExp import TopExp_Explorer

reader = STEPControl_Reader()
reader.ReadFile("bracket.step")
reader.TransferRoots()
shape = reader.OneShape()

sewer = BRepBuilderAPI_Sewing(1e-4)   # tolerance in model units
sewer.Add(shape)
sewer.Perform()
sewn = sewer.SewedShape()

fixer = ShapeFix_Shape(sewn)
fixer.SetPrecision(1e-4)
fixer.Perform()
fixed = fixer.Shape()

solid_fixer = ShapeFix_Solid(fixed)
solid = solid_fixer.SolidFromShell(fixed)

exp = TopExp_Explorer(solid, TopAbs_SOLID)
count = 0
while exp.More():
    count += 1
    exp.Next()
print("solids:", count)

Expected observable result: solids: 1 and a volume that matches the CAD reference within the sewing tolerance. If solids: 0, the shell is still open — lower the sewing tolerance or inspect free edges with BRepBuilderAPI_Sewing's NbFreeEdges(). If the volume is far off, the fixer likely merged distinct faces; reduce SetPrecision and re-run.

Tolerance is the single most common failure cause. A tolerance larger than the smallest feature will collapse thin walls; a tolerance smaller than the import error will leave gaps. Start at 1e-4 and adjust in one order of magnitude steps.

Practical Guidance

  • Keep kernel calls in a thin adapter module so you can swap OCCT for ACIS or Parasolid without rewriting preparation logic.
  • Always check operation status (IsDone(), return codes, or exception) before consuming a result shape.
  • Log the shape type and solid count after every healing step; silent topology changes are the hardest bugs to trace.
  • For ACIS and Parasolid, respect session and tag lifetimes; never hold a tag across a rollback.

With the access patterns clear, the next step is to apply them to concrete preparation tasks — importing, healing, and simplifying real models at scale.