CadQuery render — five-view preview
Purpose
Visual gate after every geometry change. The orchestrator must read the PNGs (Read tool) and decide pass / iterate — never assume success from exit code alone.
Renderer
Use cadquery.vis.show directly — it does its own tessellation, off-screen rendering, and PNG writing. No external snippets are needed.
from cadquery.vis import show
show(result, interact=False, screenshot="preview_isometric.png", gradient=False)
Python environment
Use the interpreter that has CadQuery installed with cadquery.vis available (VTK-backed):
PY=/Users/dimiasael/miniforge3/envs/dev_arm64_311/bin/python
If cadquery.vis import fails on the chosen interpreter, switch to the env above before re-running.
Camera angles for the five views
show() applies Roll → Elevation → Azimuth after ResetCamera() (default camera: position +Z, looking at origin, viewup +Y — i.e. the top view). The five canonical views map to:
| View | roll | elevation | azimuth |
|---|---|---|---|
preview_isometric.png |
-35 | -45 | 0 |
preview_isometric_rear.png |
-35 | -45 | 180 |
preview_top.png |
0 | 0 | 0 |
preview_front.png |
0 | -89.9 | 0 |
preview_right.png |
0 | -89.9 | 90 |
(Elevation is kept at -89.9 instead of -90 to avoid VTK's gimbal-lock guard. Front = camera at -Y; right = camera at +X; both with viewup +Z.)
Standard render command
Run from the project directory that contains the target .py file (so PNGs land next to it):
cd <project_dir> && $PY -c "
import runpy
from cadquery.vis import show
ns = runpy.run_path('<target.py>')
result = ns['result']
views = [
('preview_isometric.png', -35, -45.0, 0),
('preview_isometric_rear.png', -35, -45.0, 180),
('preview_top.png', 0, 0.0, 0),
('preview_front.png', 0, -89.9, 0),
('preview_right.png', 0, -89.9, 90),
]
for fname, roll, elev, az in views:
show(result, interact=False, screenshot=fname,
roll=roll, elevation=elev, azimuth=az, gradient=False)
"
Expected outputs (next to target file's directory)
preview_isometric.pngpreview_isometric_rear.pngpreview_top.pngpreview_right.pngpreview_front.png
Verify each file exists and size > 1 KB.
Pre-render smoke test
Before rendering, confirm the script executes and produces result:
cd <project_dir> && $PY -c "import runpy; ns=runpy.run_path('<target.py>'); assert ns.get('result') is not None"
If this fails, fix the CadQuery script — rendering will not help.
What to look for
| Symptom | Likely cause | Next skill |
|---|---|---|
| Part missing | Boolean tool had history; result inside branch |
cadquery-part |
| Part at global origin in assembly view | .translate() on empty WP; wrong loc= |
functional part / high-level |
| Sharp edges where fillets expected | Selector dropped fillet | cadquery-part-detailing |
| Overlapping solids | Clash | cadquery-interference-check |
| Appliance too short/tall vs spec | Envelope wrong in common.py |
cadquery-high-level-design |
| Empty / white PNG | Exec failed or null shape | fix script |
Assembly-specific checks
When rendering assembly.py or high_level_assembly.py:
- Count major envelopes in iso view vs decomposition table
- Compare overall bbox to
HOUSING_*(or equivalent) incommon.py:
python -c "
import runpy, cadquery as cq
ns = runpy.run_path('assembly.py')
# walk assembly for bbox ...
"
Report format (to orchestrator)
RENDER — <file>
Status: PASS | ITERATE
Findings: <1-3 bullets>
Next: <skill or file to edit>
Hand-off
This skill never edits geometry. Orchestrator routes failures to the correct pass.