Skip to main content

PyVista

pyvista-cad

CI PyPI License: MIT

CAD format reading, writing, and CAD-style plotting for PyVista.

The same flange shown two ways: a generic mesh viewer drawing the raw triangulation on the left, and pyvista-cad drawing smoothly shaded faces with the model's topological edges on the right.

pyvista-cad adds CAD-format support to PyVista: STEP, IGES, BREP, DXF, 3MF, IFC, FreeCAD .fcstd, OpenSCAD .scad, and glTF. It registers a .cad accessor on every pv.DataSet / pv.MultiBlock and wires reader entries into pv.read(...). It also adds CAD-style rendering: smoothly shaded faces with the model's topological B-rep edges instead of triangle-mesh noise, via .cad.plot() and a plotter.cad component. No monkey-patching, no forks, no direct VTK calls.

Install matrix

Extra Adds Formats unlocked
(base) ezdxf DXF read + write, glTF read + write
[step] build123d, cadquery-ocp STEP, BREP, FCStd, IGES (ocp backend), build123d bridge
[step-light] cascadio STEP (read-only, faster, no colors)
[3mf] lib3mf 3MF read + write
[ifc] ifcopenshell IFC read (with property sets)
[iges] pyiges[full] IGES read (pyiges backend, default)
[openscad] (uses openscad CLI) SCAD read
[all] all of the above every supported format

[full] is kept as an alias of [all], so existing installs and pinned requirement files keep resolving.

Python support: 3.10 – 3.14.

trimesh interop is provided by pyvista core (pyvista.from_trimesh, pyvista.to_trimesh) and the pyvista-trimesh package's .trimesh accessor (install pyvista-cad[trimesh]); pyvista-cad does not duplicate it.

FEA meshing via gmsh is intentionally out of scope. gmsh is GPLv2+ and would virally license any closed-source product that linked it, so pyvista-cad's dependency set stays fully permissive (MIT / BSD / Apache, plus LGPL-with-exception for the OpenCascade and IFC backends). For CAD-to-tet workflows, drive gmsh directly and read the resulting .msh file back with pv.read (PyVista routes .msh through meshio); the scikit-gmsh package wraps the live-model API if you prefer that.

pip install pyvista-cad           # DXF and glTF only
pip install pyvista-cad[step]     # add STEP, BREP, FCStd
pip install pyvista-cad[all]      # everything

Quick start

import pyvista as pv
import pyvista_cad  # registers the .cad accessor and reader entries

mesh = pv.read('part.step')  # MultiBlock of parts with cad.color, cad.label
mesh.plot(show_edges=True)

floorplan = pv.read('floor.dxf')  # PolyData with Layer cell data
layers = floorplan.cad.split_by_layer()  # MultiBlock keyed on layer

Two independent example fixtures. Left: a STEP part read with pv.read, drawn CAD-style with shaded faces and topological edges. Right: a DXF drawing split into colored per-layer blocks (body, centerlines, dimensions, holes).

CAD-friendly plotting

A generic mesh viewer draws the triangulation. With show_edges=True you see every facet edge, an artifact of the tessellation tolerance. A CAD application instead shows smoothly shaded faces with the model's topological edges (the B-rep feature curves) on top. pyvista-cad reproduces that: analytic surface normals so a coarse mesh still shades round, topological edges recovered from the cached B-rep, triangle edges hidden.

import pyvista as pv
import pyvista_cad
from pyvista_cad.examples import downloads

mb = pyvista_cad.read_step(downloads.step_part_path())  # NIST AM Bench specimen

mb.cad.plot()  # shaded faces + topological edges

# Or compose it into a scene, color faces by a scalar, keep the edges:
part = mb[0]  # a cached block keeps its B-rep
part['height'] = part.points[:, 2]
pl = pv.Plotter()
pl.cad.add(part, scalars='height', cmap='viridis')
pl.show()

The NIST AM Bench specimen. Left: cad.plot draws shaded faces with topological B-rep edges. Right: the same cached block colored by a height scalar with the viridis colormap, the topological edges still drawn.

.cad.plot() and the plotter.cad component accept a MultiBlock, PolyData, raw TopoDS, or a build123d / cadquery object; a plain mesh with no B-rep origin degrades to crease feature edges.

Real-world workflow

Load a STEP assembly, locate a part, drive it through gmsh to a tetrahedral FEA mesh, then clip to expose the interior. pv.read handles the resulting .msh file natively via meshio, so no extra PyVista dependency is needed.

import gmsh
import pyvista as pv
import pyvista_cad
from pyvista_cad.examples import downloads

assembly = pv.read(downloads.step_assembly_path())  # 3-part NIST build assembly
print(assembly.cad.assembly_tree())  # nested dict of block names
matches = assembly.cad.find('*PartCAD')  # glob -> list of (path, block)
path, part = matches[0]

gmsh.initialize()
try:
    gmsh.model.occ.importShapes(downloads.step_part_path())
    gmsh.model.occ.synchronize()
    gmsh.option.setNumber('Mesh.MeshSizeMax', 2.0)
    gmsh.model.mesh.generate(3)
    gmsh.write('part.msh')
finally:
    gmsh.finalize()

grid = pv.read('part.msh')  # via meshio
grid = grid.extract_cells(grid.celltypes == 10)  # keep VTK_TETRA
clip = grid.clip(normal='x', crinkle=True)
clip.save('part_tets.vtu')  # full tet mesh round-trips

The Quick start uses bundled offline fixtures (bracket_step_path(), a parametric L-bracket committed as STEP; drawing_dxf_path(), a layered 2D drawing). The other examples pull real, openly licensed parts from pyvista_cad.examples.downloads (cached on first fetch) — the NIST AM Bench LPBF specimen and its 3-part build assembly.

Common tasks

Task How
Read a STEP assembly with per-part colors pv.read('a.step') returns a MultiBlock; each block has cad.color and cad.label
Split a DXF by layer pv.read('a.dxf').cad.split_by_layer()
Round-trip a 3MF print pyvista_cad.write_three_mf(mb, 'b.3mf') (object color + units kept)
Load an IFC building and filter walls mb = pv.read('b.ifc'); walls = mb.cad.find(ifc_type='IfcWall')
Read IFC property sets json.loads(block.field_data['cad.psets'][0]) returns the source Pset_* / Qto_* dict
Convert build123d to PyVista pyvista_cad.from_build123d(part) (preserves color, label, transform)
Mesh a STEP for FEA in gmsh Drive gmsh directly, gmsh.write('out.msh'), then pv.read('out.msh') (uses meshio)
Generate a signed distance field from CAD see examples/05_workflows/cad_to_signed_distance.py

Licensing

pyvista-cad is MIT. Every runtime dependency is either permissive (MIT / BSD / Apache) or LGPL with the OpenCascade exception. No GPL code is pulled in by any extra, which makes the package safe to use in closed-source / proprietary products subject to the standard LGPL dynamic-link obligations. See LICENSES.md for the full dependency-by-dependency breakdown, the LGPL compliance notes, and the rationale for not depending on gmsh.

IGES backends

read_iges has two readers behind it.

backend= Needs Trimmed surfaces IGES level metadata
'pyiges' (default) [iges] Ignored cad.level / cad.levels
'ocp' [step] Clipped to the trimming curves none
import pyvista_cad

mesh = pyvista_cad.read_iges('scan.igs', backend='ocp', linear_deflection=0.1)
mesh.cad.plot()

The default is unchanged, so pv.read('part.igs') still goes through pyiges. pv.read accepts no reader keywords, so selecting the OCCT backend means calling read_iges directly.

Speed

pyiges parses and evaluates surfaces in Python; OCCT does both in C++. Best of three warm runs on pyvista_cad.examples.downloads.iges_impeller_path() (4.0 MB, 4615 entities, a SolidWorks export):

Reader Setting Cells Time
pyiges delta=0.025 (default) 753,716 19.9 s
ocp linear_deflection=0.1 (default) 20,195 0.5 s
ocp linear_deflection=0.005 122,335 0.8 s
ocp linear_deflection=0.0005 716,465 4.0 s

The two defaults are not the same mesh density, so the 36x at defaults is partly a coarser mesh. Matched at roughly equal cell count the gap is about 5x, and it grows with file size because the Python-side cost scales with entity count. Numbers are from one machine; treat the ratios as the signal, not the absolute times.

Trimmed surfaces

pyiges dispatches IGES type 128 (rational B-spline surface) and has no handler for type 144 (trimmed parametric surface), so it tessellates the full underlying surface and ignores the trimming curves. OCCT applies them. On the impeller above that shows up in the extent:

Reader X bounds
pyiges -50.5 to 49.5
ocp -42.7 to 42.5

Files whose trimming curves follow the natural surface boundary read the same either way, which is why the small tests/data/impeller.iges fixture agrees between backends.

Reach for 'ocp' on anything from a scanner or a CMM. Use 'pyiges' when you need the per-entity level numbers.

Fidelity and limitations

Round-trip fidelity varies by format. Tessellated formats (STEP, IGES, BREP, FCStd) discretize analytic surfaces on read; the originating B-rep is cached so tessellate() can refine it. DXF and 3MF round-trip geometry and metadata within documented tolerances. IGES and SCAD are read-only.

Metadata

Release files for pyvista-cad 0.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyvista-cad 0.0.5
File Size Uploaded
pyvista_cad-0.0.5.tar.gz 1.0 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyvista-cad 0.0.5
File Interpreter ABI Platform
pyvista_cad-0.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 1.2 MB

Release files / pyvista_cad-0.0.5.tar.gz

Download URL pyvista_cad-0.0.5.tar.gz
Size 1.0 MB
Tags Source
SHA-256 checksum
How to use checksums
a36c49dabc6681506c35a8be9bdfa1f9bf565fd479345c8cdd0b0d1d9e7cb6cd
BLAKE2b-256 checksum
How to use checksums
f802fe19699ecda6ae16c2faeb93a3b718fa64b55c00ccc469333df74caf4f37
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release files / pyvista_cad-0.0.5-py3-none-any.whl

Download URL pyvista_cad-0.0.5-py3-none-any.whl
Size 139.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
809275385a318a91cd27812f193886e4a907fd2d6770e9901452a6fd965e21c5
BLAKE2b-256 checksum
How to use checksums
48f7da0061fac8c7ee74d44ba02f792b2ba3f666079a83520243b6b0b9a96eb3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.5 This release

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page