pyvista-cad 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyvista_cad-0.0.1/.gitattributes +19 -0
- pyvista_cad-0.0.1/.github/FUNDING.yml +1 -0
- pyvista_cad-0.0.1/.github/dependabot.yml +11 -0
- pyvista_cad-0.0.1/.github/workflows/ci.yml +171 -0
- pyvista_cad-0.0.1/.github/workflows/docs.yml +87 -0
- pyvista_cad-0.0.1/.gitignore +60 -0
- pyvista_cad-0.0.1/.pre-commit-config.yaml +79 -0
- pyvista_cad-0.0.1/LICENSE +21 -0
- pyvista_cad-0.0.1/PKG-INFO +219 -0
- pyvista_cad-0.0.1/README.md +142 -0
- pyvista_cad-0.0.1/assets/render_hero.py +78 -0
- pyvista_cad-0.0.1/assets/render_readme.py +196 -0
- pyvista_cad-0.0.1/cspell.json +330 -0
- pyvista_cad-0.0.1/doc/Makefile +21 -0
- pyvista_cad-0.0.1/doc/_static/hero.png +0 -0
- pyvista_cad-0.0.1/doc/_static/pyvista_logo.svg +6161 -0
- pyvista_cad-0.0.1/doc/_static/readme_cad_plotting.png +0 -0
- pyvista_cad-0.0.1/doc/_static/readme_quickstart.png +0 -0
- pyvista_cad-0.0.1/doc/_static/readme_workflow.png +0 -0
- pyvista_cad-0.0.1/doc/_static/theme_overrides.css +1 -0
- pyvista_cad-0.0.1/doc/api/index.rst +225 -0
- pyvista_cad-0.0.1/doc/conf.py +165 -0
- pyvista_cad-0.0.1/doc/index.md +86 -0
- pyvista_cad-0.0.1/doc/make.bat +29 -0
- pyvista_cad-0.0.1/doc/user_guide/cad_visualization.md +144 -0
- pyvista_cad-0.0.1/doc/user_guide/interop_with_build123d.md +82 -0
- pyvista_cad-0.0.1/examples/01_readers/README.rst +8 -0
- pyvista_cad-0.0.1/examples/01_readers/read_3mf.py +34 -0
- pyvista_cad-0.0.1/examples/01_readers/read_brep.py +47 -0
- pyvista_cad-0.0.1/examples/01_readers/read_dxf.py +48 -0
- pyvista_cad-0.0.1/examples/01_readers/read_fcstd.py +40 -0
- pyvista_cad-0.0.1/examples/01_readers/read_ifc.py +53 -0
- pyvista_cad-0.0.1/examples/01_readers/read_iges.py +64 -0
- pyvista_cad-0.0.1/examples/01_readers/read_scad.py +44 -0
- pyvista_cad-0.0.1/examples/01_readers/read_step.py +35 -0
- pyvista_cad-0.0.1/examples/02_writers/README.rst +7 -0
- pyvista_cad-0.0.1/examples/02_writers/write_3mf.py +54 -0
- pyvista_cad-0.0.1/examples/02_writers/write_brep.py +47 -0
- pyvista_cad-0.0.1/examples/02_writers/write_dxf.py +53 -0
- pyvista_cad-0.0.1/examples/02_writers/write_step_faceted.py +58 -0
- pyvista_cad-0.0.1/examples/03_bridges/README.rst +9 -0
- pyvista_cad-0.0.1/examples/03_bridges/from_build123d_box.py +63 -0
- pyvista_cad-0.0.1/examples/03_bridges/from_build123d_compound.py +66 -0
- pyvista_cad-0.0.1/examples/03_bridges/from_cadquery_workplane.py +65 -0
- pyvista_cad-0.0.1/examples/03_bridges/to_build123d.py +57 -0
- pyvista_cad-0.0.1/examples/03_bridges/to_topods.py +67 -0
- pyvista_cad-0.0.1/examples/03_bridges/via_gmsh.py +51 -0
- pyvista_cad-0.0.1/examples/04_metadata/README.rst +8 -0
- pyvista_cad-0.0.1/examples/04_metadata/assembly_tree_walk.py +74 -0
- pyvista_cad-0.0.1/examples/04_metadata/color_aware_3mf.py +57 -0
- pyvista_cad-0.0.1/examples/04_metadata/inspect_step_assembly.py +72 -0
- pyvista_cad-0.0.1/examples/04_metadata/split_by_layer_dxf.py +54 -0
- pyvista_cad-0.0.1/examples/04_metadata/units_and_conversion.py +68 -0
- pyvista_cad-0.0.1/examples/05_workflows/README.rst +7 -0
- pyvista_cad-0.0.1/examples/05_workflows/as_designed_vs_scan.py +88 -0
- pyvista_cad-0.0.1/examples/05_workflows/cad_to_fea_tet_mesh.py +68 -0
- pyvista_cad-0.0.1/examples/05_workflows/cad_to_signed_distance.py +73 -0
- pyvista_cad-0.0.1/examples/05_workflows/parametric_to_3d_print.py +65 -0
- pyvista_cad-0.0.1/examples/06_advanced/README.rst +7 -0
- pyvista_cad-0.0.1/examples/06_advanced/cad_friendly_plot.py +70 -0
- pyvista_cad-0.0.1/examples/06_advanced/custom_tessellation.py +58 -0
- pyvista_cad-0.0.1/examples/06_advanced/ifc_to_unstructured_grid.py +69 -0
- pyvista_cad-0.0.1/examples/06_advanced/multiblock_walk.py +65 -0
- pyvista_cad-0.0.1/examples/README.rst +9 -0
- pyvista_cad-0.0.1/justfile +62 -0
- pyvista_cad-0.0.1/pyproject.toml +329 -0
- pyvista_cad-0.0.1/setup.cfg +4 -0
- pyvista_cad-0.0.1/src/pyvista_cad/__init__.py +248 -0
- pyvista_cad-0.0.1/src/pyvista_cad/__init__.pyi +44 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_accessor.py +2369 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/__init__.py +5 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_build123d.py +418 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_cascadio.py +101 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_ezdxf.py +383 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_freecad.py +347 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_gltf.py +227 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_ifcopenshell.py +400 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_lib3mf.py +420 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_openscad.py +85 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_backends/_pyiges.py +174 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_bridges/__init__.py +6 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_bridges/build123d.py +200 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_bridges/cadquery.py +123 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_bridges/gmsh.py +175 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_bridges/topods.py +113 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_cad_view.py +1186 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_conversion.py +327 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_errors.py +138 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_metadata.py +378 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/__init__.py +6 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/brep.py +136 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/dxf.py +172 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/fcstd.py +51 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/gltf.py +52 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/ifc.py +59 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/iges.py +66 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/scad.py +51 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/step.py +443 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_readers/three_mf.py +81 -0
- pyvista_cad-0.0.1/src/pyvista_cad/_version.py +24 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/__init__.py +94 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/_generate.py +376 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/data/SOURCES.md +24 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/data/assembly.3mf +0 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/data/bracket.step +705 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/data/cube.step +415 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/data/drawing.dxf +13378 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/data/plate.dxf +3208 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/data/small_building.ifc +103 -0
- pyvista_cad-0.0.1/src/pyvista_cad/examples/downloads.py +286 -0
- pyvista_cad-0.0.1/src/pyvista_cad/py.typed +0 -0
- pyvista_cad-0.0.1/src/pyvista_cad.egg-info/PKG-INFO +219 -0
- pyvista_cad-0.0.1/src/pyvista_cad.egg-info/SOURCES.txt +186 -0
- pyvista_cad-0.0.1/src/pyvista_cad.egg-info/dependency_links.txt +1 -0
- pyvista_cad-0.0.1/src/pyvista_cad.egg-info/entry_points.txt +16 -0
- pyvista_cad-0.0.1/src/pyvista_cad.egg-info/requires.txt +56 -0
- pyvista_cad-0.0.1/src/pyvista_cad.egg-info/top_level.txt +1 -0
- pyvista_cad-0.0.1/tests/__init__.py +0 -0
- pyvista_cad-0.0.1/tests/conftest.py +86 -0
- pyvista_cad-0.0.1/tests/data/README.md +138 -0
- pyvista_cad-0.0.1/tests/data/_generate_fixtures.py +821 -0
- pyvista_cad-0.0.1/tests/data/assembly_two_parts.step +585 -0
- pyvista_cad-0.0.1/tests/data/building.ifc +45 -0
- pyvista_cad-0.0.1/tests/data/dxf_r12.dxf +1224 -0
- pyvista_cad-0.0.1/tests/data/dxf_r2018.dxf +3298 -0
- pyvista_cad-0.0.1/tests/data/external.brep +303 -0
- pyvista_cad-0.0.1/tests/data/impeller.iges +92 -0
- pyvista_cad-0.0.1/tests/data/multimaterial.3mf +0 -0
- pyvista_cad-0.0.1/tests/image_cache/asymmetric_part_image.png +0 -0
- pyvista_cad-0.0.1/tests/image_cache/cad_view_faces_and_topological_edges.png +0 -0
- pyvista_cad-0.0.1/tests/image_cache/cad_view_image_regression.png +0 -0
- pyvista_cad-0.0.1/tests/image_cache/filleted_box_image_regression.png +0 -0
- pyvista_cad-0.0.1/tests/image_cache/read_dxf_image.png +0 -0
- pyvista_cad-0.0.1/tests/image_cache/read_step_image.png +0 -0
- pyvista_cad-0.0.1/tests/perf/__init__.py +0 -0
- pyvista_cad-0.0.1/tests/perf/conftest.py +76 -0
- pyvista_cad-0.0.1/tests/perf/test_3mf_read.py +61 -0
- pyvista_cad-0.0.1/tests/perf/test_dxf_read.py +36 -0
- pyvista_cad-0.0.1/tests/perf/test_import_cold.py +72 -0
- pyvista_cad-0.0.1/tests/perf/test_multiblock_walk.py +43 -0
- pyvista_cad-0.0.1/tests/perf/test_split_by_layer.py +39 -0
- pyvista_cad-0.0.1/tests/perf/test_step_read.py +81 -0
- pyvista_cad-0.0.1/tests/test_accessor.py +142 -0
- pyvista_cad-0.0.1/tests/test_accessor_coverage.py +1286 -0
- pyvista_cad-0.0.1/tests/test_bridges/__init__.py +0 -0
- pyvista_cad-0.0.1/tests/test_bridges/test_bridge_paths.py +302 -0
- pyvista_cad-0.0.1/tests/test_bridges/test_build123d.py +42 -0
- pyvista_cad-0.0.1/tests/test_bridges/test_cadquery.py +24 -0
- pyvista_cad-0.0.1/tests/test_bridges/test_gmsh.py +24 -0
- pyvista_cad-0.0.1/tests/test_bridges/test_import_errors.py +74 -0
- pyvista_cad-0.0.1/tests/test_bridges/test_topods.py +53 -0
- pyvista_cad-0.0.1/tests/test_cad_view.py +136 -0
- pyvista_cad-0.0.1/tests/test_cad_view_branches.py +796 -0
- pyvista_cad-0.0.1/tests/test_conversion.py +403 -0
- pyvista_cad-0.0.1/tests/test_coverage_contract.py +202 -0
- pyvista_cad-0.0.1/tests/test_errors.py +96 -0
- pyvista_cad-0.0.1/tests/test_examples.py +380 -0
- pyvista_cad-0.0.1/tests/test_image_regression.py +151 -0
- pyvista_cad-0.0.1/tests/test_lazy_imports.py +278 -0
- pyvista_cad-0.0.1/tests/test_metadata.py +280 -0
- pyvista_cad-0.0.1/tests/test_multiblock_methods.py +122 -0
- pyvista_cad-0.0.1/tests/test_packaging_contract.py +98 -0
- pyvista_cad-0.0.1/tests/test_plugin_registration.py +207 -0
- pyvista_cad-0.0.1/tests/test_properties.py +205 -0
- pyvista_cad-0.0.1/tests/test_readers/__init__.py +0 -0
- pyvista_cad-0.0.1/tests/test_readers/test_brep.py +95 -0
- pyvista_cad-0.0.1/tests/test_readers/test_cascadio.py +64 -0
- pyvista_cad-0.0.1/tests/test_readers/test_dxf.py +112 -0
- pyvista_cad-0.0.1/tests/test_readers/test_fcstd.py +84 -0
- pyvista_cad-0.0.1/tests/test_readers/test_gltf.py +160 -0
- pyvista_cad-0.0.1/tests/test_readers/test_ifc.py +259 -0
- pyvista_cad-0.0.1/tests/test_readers/test_iges.py +58 -0
- pyvista_cad-0.0.1/tests/test_readers/test_scad.py +70 -0
- pyvista_cad-0.0.1/tests/test_readers/test_step.py +163 -0
- pyvista_cad-0.0.1/tests/test_readers/test_three_mf.py +146 -0
- pyvista_cad-0.0.1/tests/test_roundtrip/__init__.py +0 -0
- pyvista_cad-0.0.1/tests/test_roundtrip/test_brep_roundtrip.py +47 -0
- pyvista_cad-0.0.1/tests/test_roundtrip/test_dxf_roundtrip.py +72 -0
- pyvista_cad-0.0.1/tests/test_roundtrip/test_gltf_roundtrip.py +140 -0
- pyvista_cad-0.0.1/tests/test_roundtrip/test_ifc_roundtrip.py +165 -0
- pyvista_cad-0.0.1/tests/test_roundtrip/test_iges_roundtrip.py +35 -0
- pyvista_cad-0.0.1/tests/test_roundtrip/test_step_roundtrip.py +129 -0
- pyvista_cad-0.0.1/tests/test_roundtrip/test_three_mf_roundtrip.py +161 -0
- pyvista_cad-0.0.1/tests/test_writers/__init__.py +0 -0
- pyvista_cad-0.0.1/tests/test_writers/test_brep.py +80 -0
- pyvista_cad-0.0.1/tests/test_writers/test_dxf.py +45 -0
- pyvista_cad-0.0.1/tests/test_writers/test_step.py +353 -0
- pyvista_cad-0.0.1/tests/test_writers/test_three_mf.py +63 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# CAD / mesh fixtures are opaque payloads. Treat them as binary so git
|
|
2
|
+
# never does EOL conversion, diff, or merge text munging on them.
|
|
3
|
+
*.step binary
|
|
4
|
+
*.stp binary
|
|
5
|
+
*.dxf binary
|
|
6
|
+
*.brep binary
|
|
7
|
+
*.iges binary
|
|
8
|
+
*.igs binary
|
|
9
|
+
*.3mf binary
|
|
10
|
+
*.ifc binary
|
|
11
|
+
*.scad binary
|
|
12
|
+
*.glb binary
|
|
13
|
+
*.gltf binary
|
|
14
|
+
*.stl binary
|
|
15
|
+
*.obj binary
|
|
16
|
+
*.ply binary
|
|
17
|
+
*.vtk binary
|
|
18
|
+
*.vtu binary
|
|
19
|
+
*.vtp binary
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
github: [banesullivan]
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0
|
|
21
|
+
- uses: astral-sh/setup-uv@v6
|
|
22
|
+
- run: uv sync --extra dev
|
|
23
|
+
- run: uv run ruff check .
|
|
24
|
+
- run: uv run ruff format --check .
|
|
25
|
+
- run: uv run mypy src/pyvista_cad
|
|
26
|
+
|
|
27
|
+
test:
|
|
28
|
+
runs-on: ${{ matrix.os }}
|
|
29
|
+
strategy:
|
|
30
|
+
fail-fast: false
|
|
31
|
+
matrix:
|
|
32
|
+
os: [ubuntu-latest, macos-14, windows-latest]
|
|
33
|
+
# 3.14 is intentionally absent: every test extra transitively
|
|
34
|
+
# pulls `cadquery` (dev -> docs -> full -> cadquery), and
|
|
35
|
+
# `cadquery-ocp` ships no cp314 wheel for any platform/version,
|
|
36
|
+
# so the env is uninstallable on 3.14. Re-add once cadquery-ocp
|
|
37
|
+
# publishes cp314 wheels. requires-python stays `>=3.10`.
|
|
38
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
39
|
+
# `dev,full` carries `step-light` (cascadio) so the cascadio STEP
|
|
40
|
+
# backend E2E runs in CI; `openscad` is installed via apt on Linux
|
|
41
|
+
# so the SCAD reader E2E runs there too. One combination gaining
|
|
42
|
+
# these is enough — the matrix shape is unchanged.
|
|
43
|
+
extras: ["dev", "dev,step", "dev,full,step-light"]
|
|
44
|
+
exclude:
|
|
45
|
+
- os: windows-latest
|
|
46
|
+
extras: "dev,full,step-light"
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v4
|
|
49
|
+
with:
|
|
50
|
+
fetch-depth: 0
|
|
51
|
+
- uses: astral-sh/setup-uv@v6
|
|
52
|
+
with:
|
|
53
|
+
python-version: ${{ matrix.python-version }}
|
|
54
|
+
- name: Set up headless display
|
|
55
|
+
uses: pyvista/setup-headless-display-action@v4
|
|
56
|
+
- name: Install system packages for OCCT / gmsh backends
|
|
57
|
+
if: runner.os == 'Linux'
|
|
58
|
+
run: |
|
|
59
|
+
sudo apt-get update
|
|
60
|
+
sudo apt-get install -y \
|
|
61
|
+
libgl1-mesa-dev libglu1 libxft2 libxcursor-dev libxinerama1 \
|
|
62
|
+
libocct-data-exchange-dev libocct-foundation-dev xvfb openscad
|
|
63
|
+
- name: Install dependencies
|
|
64
|
+
run: uv sync --extra ${{ matrix.extras }}
|
|
65
|
+
- name: Run tests
|
|
66
|
+
run: uv run pytest tests/ --cov --cov-report=xml -v
|
|
67
|
+
- name: Upload coverage
|
|
68
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13' && matrix.extras == 'dev,full,step-light'
|
|
69
|
+
uses: codecov/codecov-action@v5
|
|
70
|
+
with:
|
|
71
|
+
files: coverage.xml
|
|
72
|
+
fail_ci_if_error: false
|
|
73
|
+
- name: Upload image-cache failures
|
|
74
|
+
if: failure()
|
|
75
|
+
uses: actions/upload-artifact@v4
|
|
76
|
+
with:
|
|
77
|
+
name: image-cache-failures-${{ matrix.os }}-py${{ matrix.python-version }}-${{ matrix.extras }}
|
|
78
|
+
path: tests/image_cache_failures/
|
|
79
|
+
if-no-files-found: ignore
|
|
80
|
+
|
|
81
|
+
lazy-imports:
|
|
82
|
+
# Mission goal #4: `import pyvista_cad` must not import build123d,
|
|
83
|
+
# cascadio, OCP, lib3mf, ifcopenshell, gmsh, FreeCAD, pyiges, geomdl.
|
|
84
|
+
# This job installs ONLY the core package (DXF-only via ezdxf) so a
|
|
85
|
+
# leaked import would actually be detectable (modules aren't on the
|
|
86
|
+
# path, ImportError would surface). The matrix-`test` job above runs
|
|
87
|
+
# with `[full]` and so cannot enforce this invariant.
|
|
88
|
+
name: Lazy-imports guardrail (minimal extras)
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/checkout@v4
|
|
92
|
+
with:
|
|
93
|
+
fetch-depth: 0
|
|
94
|
+
- uses: astral-sh/setup-uv@v6
|
|
95
|
+
with:
|
|
96
|
+
python-version: "3.13"
|
|
97
|
+
- name: Install minimal (core + pytest only, no optional backends)
|
|
98
|
+
# pytest-pyvista is a test plugin (not a CAD backend); it owns
|
|
99
|
+
# the `image_cache_dir` pytest ini option, so omitting it makes
|
|
100
|
+
# pytest fail at config time with strict-warnings enabled.
|
|
101
|
+
run: |
|
|
102
|
+
uv venv
|
|
103
|
+
uv pip install -e . pytest pytest-pyvista
|
|
104
|
+
- name: Run lazy-imports guardrail
|
|
105
|
+
run: uv run pytest tests/test_lazy_imports.py -v
|
|
106
|
+
|
|
107
|
+
benchmark:
|
|
108
|
+
# Ubuntu-only because cross-platform timing is noisy. The first
|
|
109
|
+
# green run on `main` establishes the baseline; the 5% regression
|
|
110
|
+
# gate lands in a follow-up once `bench.json` has been compared
|
|
111
|
+
# across at least two runs.
|
|
112
|
+
name: Benchmark (perf regression gate)
|
|
113
|
+
runs-on: ubuntu-latest
|
|
114
|
+
# Informational until the cross-run 5% regression gate lands: absolute
|
|
115
|
+
# wall-clock budgets are too noisy on shared runners to block CI.
|
|
116
|
+
continue-on-error: true
|
|
117
|
+
steps:
|
|
118
|
+
- uses: actions/checkout@v4
|
|
119
|
+
with:
|
|
120
|
+
fetch-depth: 0
|
|
121
|
+
- uses: astral-sh/setup-uv@v6
|
|
122
|
+
with:
|
|
123
|
+
python-version: "3.13"
|
|
124
|
+
- uses: pyvista/setup-headless-display-action@v4
|
|
125
|
+
- name: Install [dev,full] for end-to-end perf cases
|
|
126
|
+
run: uv sync --extra dev --extra full
|
|
127
|
+
- name: Run benchmarks
|
|
128
|
+
# Absolute wall-clock budgets flake on shared runners; soft mode
|
|
129
|
+
# records breaches without failing the job. bench.json is still
|
|
130
|
+
# emitted for the planned cross-run regression gate.
|
|
131
|
+
env:
|
|
132
|
+
PYVISTA_CAD_PERF_SOFT: "1"
|
|
133
|
+
run: |
|
|
134
|
+
uv run pytest tests/perf/ \
|
|
135
|
+
--benchmark-only \
|
|
136
|
+
--benchmark-json=bench.json \
|
|
137
|
+
-v
|
|
138
|
+
- name: Upload benchmark JSON
|
|
139
|
+
uses: actions/upload-artifact@v4
|
|
140
|
+
with:
|
|
141
|
+
name: bench-json
|
|
142
|
+
path: bench.json
|
|
143
|
+
if-no-files-found: error
|
|
144
|
+
|
|
145
|
+
build:
|
|
146
|
+
runs-on: ubuntu-latest
|
|
147
|
+
needs: [lint, test]
|
|
148
|
+
steps:
|
|
149
|
+
- uses: actions/checkout@v4
|
|
150
|
+
with:
|
|
151
|
+
fetch-depth: 0
|
|
152
|
+
- uses: astral-sh/setup-uv@v6
|
|
153
|
+
- run: uv build
|
|
154
|
+
- uses: actions/upload-artifact@v4
|
|
155
|
+
with:
|
|
156
|
+
name: dist
|
|
157
|
+
path: dist/
|
|
158
|
+
|
|
159
|
+
publish:
|
|
160
|
+
runs-on: ubuntu-latest
|
|
161
|
+
needs: [build]
|
|
162
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
163
|
+
environment: release
|
|
164
|
+
permissions:
|
|
165
|
+
id-token: write
|
|
166
|
+
steps:
|
|
167
|
+
- uses: actions/download-artifact@v4
|
|
168
|
+
with:
|
|
169
|
+
name: dist
|
|
170
|
+
path: dist/
|
|
171
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
pages: write
|
|
18
|
+
id-token: write
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build:
|
|
22
|
+
name: Build Sphinx docs + gallery
|
|
23
|
+
runs-on: ubuntu-24.04
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
|
|
29
|
+
- uses: astral-sh/setup-uv@v6
|
|
30
|
+
with:
|
|
31
|
+
python-version: "3.13"
|
|
32
|
+
|
|
33
|
+
- name: Set up headless display
|
|
34
|
+
uses: pyvista/setup-headless-display-action@v4
|
|
35
|
+
|
|
36
|
+
- name: Install system packages for OCCT-backed examples
|
|
37
|
+
run: |
|
|
38
|
+
sudo apt-get update
|
|
39
|
+
sudo apt-get install -y \
|
|
40
|
+
libgl1-mesa-dev libglu1 libxft2 libxcursor-dev libxinerama1 \
|
|
41
|
+
libocct-data-exchange-dev libocct-foundation-dev xvfb pandoc openscad
|
|
42
|
+
|
|
43
|
+
- name: Install with [docs]
|
|
44
|
+
run: uv sync --extra docs
|
|
45
|
+
|
|
46
|
+
- name: Build documentation
|
|
47
|
+
run: uv run make -C doc html
|
|
48
|
+
|
|
49
|
+
- name: Prevent Jekyll processing on GH Pages
|
|
50
|
+
run: touch doc/_build/html/.nojekyll
|
|
51
|
+
|
|
52
|
+
- name: Upload Pages artifact
|
|
53
|
+
uses: actions/upload-pages-artifact@v3
|
|
54
|
+
with:
|
|
55
|
+
path: doc/_build/html/
|
|
56
|
+
|
|
57
|
+
deploy:
|
|
58
|
+
name: Deploy to GitHub Pages
|
|
59
|
+
needs: build
|
|
60
|
+
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
|
61
|
+
runs-on: ubuntu-24.04
|
|
62
|
+
environment:
|
|
63
|
+
name: github-pages
|
|
64
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
65
|
+
steps:
|
|
66
|
+
- name: Deploy to GitHub Pages
|
|
67
|
+
id: deployment
|
|
68
|
+
uses: actions/deploy-pages@v4
|
|
69
|
+
|
|
70
|
+
doctest:
|
|
71
|
+
name: Doctest
|
|
72
|
+
runs-on: ubuntu-24.04
|
|
73
|
+
needs: build
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@v4
|
|
76
|
+
- uses: astral-sh/setup-uv@v6
|
|
77
|
+
with:
|
|
78
|
+
python-version: "3.13"
|
|
79
|
+
- uses: pyvista/setup-headless-display-action@v4
|
|
80
|
+
- name: Install system packages for OCCT-backed examples
|
|
81
|
+
run: |
|
|
82
|
+
sudo apt-get update
|
|
83
|
+
sudo apt-get install -y \
|
|
84
|
+
libgl1-mesa-dev libglu1 libxft2 libxcursor-dev libxinerama1 \
|
|
85
|
+
libocct-data-exchange-dev libocct-foundation-dev xvfb pandoc openscad
|
|
86
|
+
- run: uv sync --extra docs
|
|
87
|
+
- run: uv run make -C doc doctest
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
*.egg
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv/
|
|
11
|
+
|
|
12
|
+
# uv lockfile (library: resolve fresh, do not pin)
|
|
13
|
+
uv.lock
|
|
14
|
+
|
|
15
|
+
# Testing / coverage / benchmarks
|
|
16
|
+
.coverage
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.benchmarks/
|
|
19
|
+
.hypothesis/
|
|
20
|
+
htmlcov/
|
|
21
|
+
coverage.xml
|
|
22
|
+
|
|
23
|
+
# Type checking / linting
|
|
24
|
+
.mypy_cache/
|
|
25
|
+
.ruff_cache/
|
|
26
|
+
|
|
27
|
+
# Profiling
|
|
28
|
+
*.prof
|
|
29
|
+
|
|
30
|
+
# OS
|
|
31
|
+
.DS_Store
|
|
32
|
+
|
|
33
|
+
# IDE
|
|
34
|
+
.idea/
|
|
35
|
+
.vscode/
|
|
36
|
+
*.swp
|
|
37
|
+
*.swo
|
|
38
|
+
|
|
39
|
+
# Agent / local tooling
|
|
40
|
+
.claude/
|
|
41
|
+
|
|
42
|
+
# Local-only notes, design docs, audits, benchmarks (not published)
|
|
43
|
+
notes/
|
|
44
|
+
|
|
45
|
+
# setuptools_scm-generated version file
|
|
46
|
+
src/pyvista_cad/_version.py
|
|
47
|
+
|
|
48
|
+
# Local env
|
|
49
|
+
.env
|
|
50
|
+
|
|
51
|
+
# pytest-pyvista regression failures
|
|
52
|
+
tests/image_cache_failures/
|
|
53
|
+
|
|
54
|
+
# Sphinx + Sphinx Gallery build artifacts
|
|
55
|
+
doc/_build/
|
|
56
|
+
doc/examples/
|
|
57
|
+
doc/sg_execution_times.rst
|
|
58
|
+
doc/api/_autosummary/
|
|
59
|
+
doc/api/_backrefs/
|
|
60
|
+
errors.txt
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
ci:
|
|
2
|
+
autoupdate_schedule: monthly
|
|
3
|
+
|
|
4
|
+
# CAD/mesh fixtures are opaque binary-ish payloads. Whitespace,
|
|
5
|
+
# end-of-file, line-ending, and spell hooks must never rewrite them.
|
|
6
|
+
exclude: |
|
|
7
|
+
(?x)^(
|
|
8
|
+
.*\.(step|stp|dxf|brep|iges|igs|3mf|ifc|scad|glb|gltf|stl|obj|ply|vtk|vtu|vtp)
|
|
9
|
+
)$
|
|
10
|
+
|
|
11
|
+
repos:
|
|
12
|
+
- repo: https://github.com/numpy/numpydoc
|
|
13
|
+
rev: v1.10.0
|
|
14
|
+
hooks:
|
|
15
|
+
- id: numpydoc-validation
|
|
16
|
+
files: ^src/pyvista_cad/
|
|
17
|
+
|
|
18
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
19
|
+
rev: v6.0.0
|
|
20
|
+
hooks:
|
|
21
|
+
- id: check-added-large-files
|
|
22
|
+
args: [--maxkb, "5000"]
|
|
23
|
+
- id: check-json
|
|
24
|
+
- id: check-merge-conflict
|
|
25
|
+
- id: check-shebang-scripts-are-executable
|
|
26
|
+
- id: check-toml
|
|
27
|
+
- id: check-yaml
|
|
28
|
+
- id: debug-statements
|
|
29
|
+
- id: detect-private-key
|
|
30
|
+
- id: trailing-whitespace
|
|
31
|
+
- id: check-docstring-first
|
|
32
|
+
- id: end-of-file-fixer
|
|
33
|
+
- id: mixed-line-ending
|
|
34
|
+
|
|
35
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
36
|
+
rev: v0.15.1
|
|
37
|
+
hooks:
|
|
38
|
+
- id: ruff-format
|
|
39
|
+
- id: ruff-check
|
|
40
|
+
args: ["--fix", "--show-fixes"]
|
|
41
|
+
|
|
42
|
+
- repo: https://github.com/rbubley/mirrors-prettier
|
|
43
|
+
rev: v3.8.1
|
|
44
|
+
hooks:
|
|
45
|
+
- id: prettier
|
|
46
|
+
types_or: [yaml, markdown, json]
|
|
47
|
+
|
|
48
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
49
|
+
rev: v8.30.0
|
|
50
|
+
hooks:
|
|
51
|
+
- id: gitleaks
|
|
52
|
+
|
|
53
|
+
- repo: https://github.com/python-jsonschema/check-jsonschema
|
|
54
|
+
rev: 0.36.1
|
|
55
|
+
hooks:
|
|
56
|
+
- id: check-github-workflows
|
|
57
|
+
|
|
58
|
+
- repo: https://github.com/ComPWA/taplo-pre-commit
|
|
59
|
+
rev: v0.9.3
|
|
60
|
+
hooks:
|
|
61
|
+
- id: taplo-format
|
|
62
|
+
|
|
63
|
+
- repo: https://github.com/streetsidesoftware/cspell-cli
|
|
64
|
+
rev: v9.2.0
|
|
65
|
+
hooks:
|
|
66
|
+
- id: cspell
|
|
67
|
+
# cspell-cli v9 needs Node >=20.18; pin so the hook does not
|
|
68
|
+
# fall back to whatever Node is on PATH (system Node may be 18).
|
|
69
|
+
language_version: "22.22.1"
|
|
70
|
+
args: ["--no-progress", "--no-summary"]
|
|
71
|
+
|
|
72
|
+
- repo: local
|
|
73
|
+
hooks:
|
|
74
|
+
- id: format-justfile
|
|
75
|
+
name: Format justfile
|
|
76
|
+
entry: just --fmt --unstable
|
|
77
|
+
language: system
|
|
78
|
+
files: "(^|/)justfile$|\\.just$"
|
|
79
|
+
pass_filenames: false
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The PyVista Developers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyvista-cad
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: PyVista accessor and reader-registry plugin for CAD formats (STEP, IGES, BREP, DXF, 3MF, IFC, FCStd) and bridges to build123d, cadquery, OCP, and gmsh.
|
|
5
|
+
Author-email: The PyVista Developers <info@pyvista.org>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/pyvista/pyvista-cad
|
|
8
|
+
Project-URL: Documentation, https://pyvista.github.io/pyvista-cad/
|
|
9
|
+
Project-URL: Issues, https://github.com/pyvista/pyvista-cad/issues
|
|
10
|
+
Project-URL: Repository, https://github.com/pyvista/pyvista-cad
|
|
11
|
+
Keywords: 3d,pyvista,cad,step,iges,brep,dxf,3mf,ifc,build123d,cadquery,opencascade
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: MacOS
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
25
|
+
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
|
|
26
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
27
|
+
Classifier: Typing :: Typed
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: ezdxf>=1.3
|
|
32
|
+
Requires-Dist: numpy>=1.24
|
|
33
|
+
Requires-Dist: pooch>=1.8
|
|
34
|
+
Requires-Dist: pyvista>=0.48.4
|
|
35
|
+
Provides-Extra: step
|
|
36
|
+
Requires-Dist: build123d>=0.7; extra == "step"
|
|
37
|
+
Provides-Extra: step-light
|
|
38
|
+
Requires-Dist: cascadio>=0.0.17; extra == "step-light"
|
|
39
|
+
Provides-Extra: 3mf
|
|
40
|
+
Requires-Dist: lib3mf>=2.3; extra == "3mf"
|
|
41
|
+
Provides-Extra: ifc
|
|
42
|
+
Requires-Dist: ifcopenshell>=0.7.0; extra == "ifc"
|
|
43
|
+
Provides-Extra: iges
|
|
44
|
+
Requires-Dist: pyiges[full]>=0.3; extra == "iges"
|
|
45
|
+
Provides-Extra: gmsh
|
|
46
|
+
Requires-Dist: gmsh>=4.13; extra == "gmsh"
|
|
47
|
+
Provides-Extra: cadquery
|
|
48
|
+
Requires-Dist: cadquery>=2.4; extra == "cadquery"
|
|
49
|
+
Provides-Extra: trimesh
|
|
50
|
+
Requires-Dist: pyvista-trimesh>=0.1; extra == "trimesh"
|
|
51
|
+
Provides-Extra: full
|
|
52
|
+
Requires-Dist: pyvista-cad[3mf,cadquery,gmsh,ifc,iges,step,trimesh]; extra == "full"
|
|
53
|
+
Provides-Extra: docs
|
|
54
|
+
Requires-Dist: pyvista-cad[full]; extra == "docs"
|
|
55
|
+
Requires-Dist: cadquery>=2.4; extra == "docs"
|
|
56
|
+
Requires-Dist: pandas>=2.0; extra == "docs"
|
|
57
|
+
Requires-Dist: sphinx>=8.0; extra == "docs"
|
|
58
|
+
Requires-Dist: sphinx-gallery>=0.18; extra == "docs"
|
|
59
|
+
Requires-Dist: sphinx-design>=0.6; extra == "docs"
|
|
60
|
+
Requires-Dist: sphinx-copybutton>=0.5; extra == "docs"
|
|
61
|
+
Requires-Dist: sphinx-book-theme>=1.1; extra == "docs"
|
|
62
|
+
Requires-Dist: myst-parser>=4.0; extra == "docs"
|
|
63
|
+
Requires-Dist: sphinx-notfound-page>=1.1; extra == "docs"
|
|
64
|
+
Requires-Dist: numpydoc>=1.10; extra == "docs"
|
|
65
|
+
Requires-Dist: pypandoc>=1.13; extra == "docs"
|
|
66
|
+
Requires-Dist: pyvista[jupyter]; extra == "docs"
|
|
67
|
+
Provides-Extra: dev
|
|
68
|
+
Requires-Dist: pyvista-cad[docs]; extra == "dev"
|
|
69
|
+
Requires-Dist: mypy==2.1.0; extra == "dev"
|
|
70
|
+
Requires-Dist: ruff==0.15.13; extra == "dev"
|
|
71
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
72
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == "dev"
|
|
73
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
74
|
+
Requires-Dist: pytest-pyvista>=0.2; extra == "dev"
|
|
75
|
+
Requires-Dist: hypothesis>=6.100; extra == "dev"
|
|
76
|
+
Dynamic: license-file
|
|
77
|
+
|
|
78
|
+
<p align="center">
|
|
79
|
+
<img src="https://github.com/pyvista/pyvista/raw/main/doc/source/_static/pyvista_logo.svg" alt="PyVista" width="400" />
|
|
80
|
+
</p>
|
|
81
|
+
|
|
82
|
+
# pyvista-cad
|
|
83
|
+
|
|
84
|
+
[](https://github.com/pyvista/pyvista-cad/actions/workflows/ci.yml)
|
|
85
|
+
[](https://pypi.org/project/pyvista-cad/)
|
|
86
|
+
[](LICENSE)
|
|
87
|
+
|
|
88
|
+
**CAD format reading, writing, and CAD-style plotting for [PyVista](https://github.com/pyvista/pyvista).**
|
|
89
|
+
|
|
90
|
+
<p align="center">
|
|
91
|
+
<img src="https://raw.githubusercontent.com/pyvista/pyvista-cad/main/doc/_static/hero.png" alt="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." width="90%">
|
|
92
|
+
</p>
|
|
93
|
+
|
|
94
|
+
`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.
|
|
95
|
+
|
|
96
|
+
## Install matrix
|
|
97
|
+
|
|
98
|
+
| Extra | Adds | Formats unlocked |
|
|
99
|
+
| -------------- | ----------------------- | ----------------------------------- |
|
|
100
|
+
| (base) | ezdxf | DXF read + write, glTF read + write |
|
|
101
|
+
| `[step]` | build123d, cadquery-ocp | STEP, BREP, FCStd, build123d bridge |
|
|
102
|
+
| `[step-light]` | cascadio | STEP (read-only, faster, no colors) |
|
|
103
|
+
| `[3mf]` | lib3mf | 3MF read + write |
|
|
104
|
+
| `[ifc]` | ifcopenshell | IFC read (with property sets) |
|
|
105
|
+
| `[iges]` | pyiges[full] | IGES read |
|
|
106
|
+
| `[gmsh]` | gmsh | gmsh bridge for FEA meshing |
|
|
107
|
+
| `[openscad]` | (uses `openscad` CLI) | SCAD read |
|
|
108
|
+
| `[full]` | all of the above | every supported format |
|
|
109
|
+
|
|
110
|
+
**Python support:** 3.10 – 3.13. Python 3.14 is not yet supported: the
|
|
111
|
+
`[step]`/`[full]` extras depend on `cadquery-ocp`, which publishes no
|
|
112
|
+
cp314 wheels for any platform. 3.14 will be added once those wheels ship.
|
|
113
|
+
|
|
114
|
+
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.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pip install pyvista-cad # DXF and glTF only
|
|
118
|
+
pip install pyvista-cad[step] # add STEP, BREP, FCStd
|
|
119
|
+
pip install pyvista-cad[full] # everything
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Quick start
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
import pyvista as pv
|
|
126
|
+
import pyvista_cad # registers the .cad accessor and reader entries
|
|
127
|
+
|
|
128
|
+
mesh = pv.read('part.step') # MultiBlock of parts with cad.color, cad.label
|
|
129
|
+
mesh.plot(show_edges=True)
|
|
130
|
+
|
|
131
|
+
floorplan = pv.read('floor.dxf') # PolyData with Layer cell data
|
|
132
|
+
layers = floorplan.cad.split_by_layer() # MultiBlock keyed on layer
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
<p align="center">
|
|
136
|
+
<img src="https://raw.githubusercontent.com/pyvista/pyvista-cad/main/doc/_static/readme_quickstart.png" alt="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)." width="90%">
|
|
137
|
+
</p>
|
|
138
|
+
|
|
139
|
+
## CAD-friendly plotting
|
|
140
|
+
|
|
141
|
+
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.
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
import pyvista as pv
|
|
145
|
+
import pyvista_cad
|
|
146
|
+
from pyvista_cad.examples import downloads
|
|
147
|
+
|
|
148
|
+
mb = pyvista_cad.read_step(downloads.step_part_path()) # NIST AM Bench specimen
|
|
149
|
+
|
|
150
|
+
mb.cad.plot() # shaded faces + topological edges
|
|
151
|
+
|
|
152
|
+
# Or compose it into a scene, color faces by a scalar, keep the edges:
|
|
153
|
+
part = mb[0] # a cached block keeps its B-rep
|
|
154
|
+
part['height'] = part.points[:, 2]
|
|
155
|
+
pl = pv.Plotter()
|
|
156
|
+
pl.cad.add(part, scalars='height', cmap='viridis')
|
|
157
|
+
pl.show()
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
<p align="center">
|
|
161
|
+
<img src="https://raw.githubusercontent.com/pyvista/pyvista-cad/main/doc/_static/readme_cad_plotting.png" alt="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." width="90%">
|
|
162
|
+
</p>
|
|
163
|
+
|
|
164
|
+
`.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.
|
|
165
|
+
|
|
166
|
+
## Real-world workflow
|
|
167
|
+
|
|
168
|
+
Load a STEP assembly, locate a part, drive it through gmsh to a
|
|
169
|
+
tetrahedral FEA mesh, then clip to expose the interior. Needs the
|
|
170
|
+
`[gmsh]` extra.
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
import gmsh
|
|
174
|
+
import pyvista as pv
|
|
175
|
+
import pyvista_cad
|
|
176
|
+
from pyvista_cad.examples import downloads
|
|
177
|
+
|
|
178
|
+
assembly = pv.read(downloads.step_assembly_path()) # 3-part NIST build assembly
|
|
179
|
+
print(assembly.cad.assembly_tree()) # nested dict of block names
|
|
180
|
+
matches = assembly.cad.find('*PartCAD') # glob -> list of (path, block)
|
|
181
|
+
path, part = matches[0]
|
|
182
|
+
|
|
183
|
+
gmsh.initialize()
|
|
184
|
+
try:
|
|
185
|
+
gmsh.model.occ.importShapes(downloads.step_part_path())
|
|
186
|
+
gmsh.model.occ.synchronize()
|
|
187
|
+
gmsh.option.setNumber('Mesh.MeshSizeMax', 2.0)
|
|
188
|
+
gmsh.model.mesh.generate(3)
|
|
189
|
+
grid = pyvista_cad.from_gmsh()
|
|
190
|
+
finally:
|
|
191
|
+
gmsh.finalize()
|
|
192
|
+
|
|
193
|
+
grid = grid.extract_cells(grid.celltypes == 10) # keep VTK_TETRA
|
|
194
|
+
clip = grid.clip(normal='x', crinkle=True)
|
|
195
|
+
clip.save('part_tets.vtu') # full tet mesh round-trips
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
<p align="center">
|
|
199
|
+
<img src="https://raw.githubusercontent.com/pyvista/pyvista-cad/main/doc/_static/readme_workflow.png" alt="A 3-part NIST build assembly. Three steps: the full assembly as read (CAD-style), the located PartCAD component highlighted against the muted rest, then that part meshed tetrahedrally with gmsh and crinkle-clipped to expose the colored tet interior." width="100%">
|
|
200
|
+
</p>
|
|
201
|
+
|
|
202
|
+
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.
|
|
203
|
+
|
|
204
|
+
## Common tasks
|
|
205
|
+
|
|
206
|
+
| Task | How |
|
|
207
|
+
| ----------------------------------------- | ----------------------------------------------------------------------------------------- |
|
|
208
|
+
| Read a STEP assembly with per-part colors | `pv.read('a.step')` returns a `MultiBlock`; each block has `cad.color` and `cad.label` |
|
|
209
|
+
| Split a DXF by layer | `pv.read('a.dxf').cad.split_by_layer()` |
|
|
210
|
+
| Round-trip a 3MF print | `pyvista_cad.write_three_mf(mb, 'b.3mf')` (object color + units kept) |
|
|
211
|
+
| Load an IFC building and filter walls | `mb = pv.read('b.ifc'); walls = mb.cad.find(ifc_type='IfcWall')` |
|
|
212
|
+
| Read IFC property sets | `json.loads(block.field_data['cad.psets'][0])` returns the source `Pset_*` / `Qto_*` dict |
|
|
213
|
+
| Convert build123d to PyVista | `pyvista_cad.from_build123d(part)` (preserves color, label, transform) |
|
|
214
|
+
| Mesh a STEP for FEA in gmsh | `pyvista_cad.to_gmsh(...)` then gmsh; see `examples/05_workflows/cad_to_fea_tet_mesh.py` |
|
|
215
|
+
| Generate a signed distance field from CAD | see `examples/05_workflows/cad_to_signed_distance.py` |
|
|
216
|
+
|
|
217
|
+
## Fidelity and limitations
|
|
218
|
+
|
|
219
|
+
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.
|