Skip to content

visualdynamics.io.step

step

STEP and IGES — B-rep CAD, tessellated here by OpenCASCADE.

Unlike STL and 3MF these files hold mathematics rather than triangles, so reading them takes a geometry kernel: OCP (Apache-2.0 bindings) over OpenCASCADE (LGPL-2.1 with exception — the same replaceable-library posture as Qt; see NOTICE.md). The kernel ships in every packaged build, because a frozen application cannot grow it later; the pip install keeps it optional (visualdynamics[step]) and this module refuses with the install command when it is absent.

What comes out matches the 3MF importer's contract: the assembly's named parts become named blocks, each instance placed by its own transform, coordinates in metres. This is the importer that takes a McMaster-Carr download directly — their STEP and IGES both land here.

Functions:

Name Description
load

Read a STEP or IGES file as a geometry — parts as named blocks.

Classes

Functions:

load

load(path: str | PathLike) -> Geometry

Read a STEP or IGES file as a geometry — parts as named blocks.

Parameters:

Name Type Description Default
path str or path - like

The .step/.stp or .iges/.igs file.

required

Returns:

Type Description
Geometry

Triangle face elements in metres, tessellated by the kernel — one named block per free shape the file holds.

Source code in src/visualdynamics/io/step.py
def load(path: str | os.PathLike) -> Geometry:
    """Read a STEP or IGES file as a geometry — parts as named blocks.

    Parameters
    ----------
    path : str or path-like
        The ``.step``/``.stp`` or ``.iges``/``.igs`` file.

    Returns
    -------
    Geometry
        Triangle face elements in metres, tessellated by the kernel —
        one named block per free shape the file holds.
    """
    _require_kernel()
    from OCP.TDataStd import TDataStd_Name
    from OCP.XCAFDoc import XCAFDoc_DocumentTool

    try:
        from OCP.TDF import TDF_LabelSequence
    except ImportError:
        # the 8.0 binding names the sequence for what it is; 7.9 kept
        # the kernel's typedef (2026-09-13: Linux resolved 8.0.1 while
        # the Mac still had 7.9.3, and the reader has to take both)
        from OCP.collections import Sequence_TDF_Label as TDF_LabelSequence

    from .stl import mesh_geometry

    document = _document(str(path))
    tool = XCAFDoc_DocumentTool.ShapeTool_s(document.Main())
    labels = TDF_LabelSequence()
    tool.GetFreeShapes(labels)
    parts: list[tuple[str, np.ndarray]] = []
    stem = os.path.splitext(os.path.basename(str(path)))[0]
    for index in range(1, labels.Length() + 1):
        label = labels.Value(index)
        name_holder = TDataStd_Name()
        name = (name_holder.Get().ToExtString()
                if label.FindAttribute(TDataStd_Name.GetID_s(),
                                       name_holder) else '')
        corners = _shape_triangles(tool.GetShape_s(label))
        if len(corners):
            parts.append((name or stem, corners))
    if not parts:
        raise ValueError(f'{path} holds no shapes that tessellate')
    return mesh_geometry(parts, length_unit='m')