pyvista-cad

pyvista-cad#

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

pyvista-cad adds STEP, IGES, BREP, DXF, 3MF, IFC, FreeCAD .fcstd, OpenSCAD .scad, and glTF support to PyVista. It registers a .cad accessor plus reader entries on pv.read(...). No monkey-patching. No forks. No direct VTK calls.

The .cad accessor is dual: on a pv.DataSet it resolves to CadDataSetAccessor, and on a pv.MultiBlock to CadMultiBlockAccessor. PyVista picks the right one by object type, so mesh.cad and assembly.cad both work and expose the surface appropriate to that object (the MultiBlock accessor adds assembly-tree traversal). See the API reference.

import build123d as b3d
import pyvista as pv

import pyvista_cad

with b3d.BuildPart() as fp:
    b3d.Cylinder(radius=50, height=10)
    with b3d.Locations((0, 0, 5)):
        b3d.Cylinder(
            radius=26,
            height=14,
            align=(b3d.Align.CENTER, b3d.Align.CENTER, b3d.Align.MIN),
        )
    b3d.Cylinder(radius=17, height=80, mode=b3d.Mode.SUBTRACT)
    with b3d.PolarLocations(radius=38, count=6):
        b3d.Cylinder(radius=4, height=80, mode=b3d.Mode.SUBTRACT)
    _top = fp.edges().filter_by(b3d.GeomType.CIRCLE).group_by(b3d.Axis.Z)[-1]
    b3d.chamfer(_top, length=1.5)
part = fp.part

face_color = '#4a7fb5'
camera = [(150.0, -130.0, 175.0), (0.0, 0.0, 2.0), (0.0, 0.0, 1.0)]

pl = pv.Plotter(shape=(1, 2), window_size=(1680, 760), border=False)
pl.background_color = 'white'

pl.subplot(0, 0)
pl.add_mesh(
    pyvista_cad.from_build123d(part).extract_surface(algorithm='dataset_surface'),
    color=face_color,
    show_edges=True,
    edge_color='#8a8a8a',
    line_width=1,
)
pl.add_text('generic mesh viewer\nshow_edges=True', font_size=12, color='#555555', position='lower_edge')
pl.camera_position = camera

pl.subplot(0, 1)
pl.cad.add(part, color=face_color, edge_color='black', line_width=3)
pl.add_text('pyvista-cad\nshaded faces + topological edges', font_size=12, color='#555555', position='lower_edge')
pl.camera_position = camera

pl.link_views()
pl.show()
_images/index-58ea0d2682021ee4-md_00_00.png