[framework] bench2 preview-parts: reproducible assembly component previews - #116
Conversation
…views Named-Assembly families had no framework command for preview_parts.png: the STEP path folds an Assembly to a compound, so component names and hierarchy never reach the renderer and every assembly family hand-rolled its own render script. - execute_cq_to_parts: run the DERIVED program (the same artifact every other preview renders) with an export harness that keeps the tree — one STEP per shape-bearing node plus its absolute 3x4 world transform in manifest.json. - render_actors: the single-mesh VTK pipeline generalized to styled multi-actor scenes (shared frame, camera fitted over the union of all actors, z-buffer depth occlusion); render_iso is now the one-actor teal case — same pipeline, same bytes. - preview_parts.build_preview_parts: deterministic hard / seed 0 -> one four-view row per semantic component (own frame, bbox in mm), the complete assembly in its true pose, then red-on-gray highlight rows in family.json components order; repeated instances group with quantity=N, --per-instance splits them. Contract violations fail clearly instead of rendering a misleading image. - naming contract: exact component name, or <component>_<NN> for repeated instances; exact declared names win; semantically distinct components stay separate. family.json solids must equal the components quantity sum — now also checked by bench2 validate. - bench2 preview invokes the same render automatically when build() returns a named Assembly; single-part families are unchanged. - tests/: hermetic fixture families through the real pipeline (nested locations, rotation, repeated instances, grouped vs per-instance, metadata drift, byte determinism) plus a CI step that runs them. Closes #95 Signed-off-by: BenchCAD <benchcad@users.noreply.github.com>
bench2 validateclevis_fork_headset_screw_shaft_collarslotted_din_railspeaker_pole_mount_socketPreviews: the |
The hosted runner has no display, EGL, or OSMesa, so any VTK offscreen render segfaults (exit 139) — the new framework tests hit it, and it is also why the existing 'render previews' step never actually rendered (its || true swallowed the crash and the artifact just re-uploaded the committed PNGs). The vtk wheel dlopens the system libOSMesa at runtime; installing libosmesa6 gives it a software offscreen backend, making the framework tests and real CI preview renders work. Also guard the preview step against a missing /tmp/fams.txt: with always() it runs even when a step failed before family scoping wrote the list. Signed-off-by: BenchCAD <benchcad@users.noreply.github.com>
The maintainer is dropping askable from the public contract (#121); this PR moved cli._param_caption into preview_parts, so adopt the same semantics here — caption every declared parameter instead of filtering on askable/feature — and drop the inert askable key from the test fixture. Keeps the eventual rebase of either PR onto the other purely mechanical. Signed-off-by: BenchCAD <benchcad@users.noreply.github.com>
…o framework/preview-parts Signed-off-by: BenchCAD <benchcad@users.noreply.github.com> # Conflicts: # framework/bench2/cli.py
…o framework/preview-parts Signed-off-by: BenchCAD <benchcad@users.noreply.github.com> # Conflicts: # framework/bench2/cli.py
Reviewers judge a render feature by its images, so the repo now ships a complete example: docs/examples/preview_parts_demo (a pillow-block-style assembly — block, flanged bushing, and a bolt_01/bolt_02 pair in a nested, 30-deg-rotated sub-assembly) with both artifacts committed (grouped and --per-instance) and a README covering what it demonstrates and how to regenerate. DESIGN_SPEC embeds the grouped image next to the naming contract, and a framework test keeps the example runnable. Lives outside designs/ on purpose: it is documentation, not a benchmark family. Signed-off-by: BenchCAD <benchcad@users.noreply.github.com>
|
Added the reviewable evidence this PR was missing: a committed, runnable example under |
Maintainer request on the example: keep the opaque highlight rows and add a transparent variant. Non-highlighted components can hide the very part being highlighted (a bushing pressed into its bore, a bolt shank inside its hole); --transparent renders them ghosted (opacity 0.22, faint edges) so the red component reads through the assembly. Styles gain an opacity channel (existing styles stay fully opaque — default output is byte-identical), the demo commits preview_parts_transparent.png, and DESIGN_SPEC/README/tests cover the mode. Signed-off-by: BenchCAD <benchcad@users.noreply.github.com>
|
Added |
sunzhenchuan007
left a comment
There was a problem hiding this comment.
An old preview_parts.png might be left behind after failing
Signed-off-by: BenchCAD <benchcad@users.noreply.github.com> # Conflicts: # framework/bench2/render.py
sunzhenchuan007's approval note: a failed run could leave the previous preview_parts.png in place, reading as current evidence. The artifact is now removed at the start of every run — a failed run leaves nothing, and a family that stopped being an assembly sheds its obsolete artifact on the next preview. Tests cover both paths, and the demo artifacts are regenerated on the merged renderer (centered framing from #115). Signed-off-by: BenchCAD <benchcad@users.noreply.github.com>
|
@sunzhenchuan007 good catch on the stale artifact — fixed in f396456: Also resolved the merge conflict with main: #115's centered-framing fix is ported into the multi-actor |
build() now returns a named cq.Assembly with components built in their local frames and placed by Location: body, cover, scroll_plate (key position applied as its Location), jaw_1/jaw_2/jaw_3 as three declared components (a matched set with distinct P/3 tooth phases, like the real 1/2/3-marked jaws), and pinion x3 as repeated instances of one local shape. family.json declares the components (quantity sum = solids = 9) and preview_parts.png is now the framework bench2 preview-parts output: per-component four-view rows in one comparable frame, the assembly in pose, and per-component highlight rows. World geometry is unchanged - probes reproduce identical intersection and gap numbers; validate passes the new components gate. Signed-off-by: BenchCAD <benchcad@users.noreply.github.com>
What changed
uv run bench2 preview-parts <family>rendersdesigns/<family>/preview_parts.pngfor named-cq.Assemblyfamilies: one four-view row per semantic component (own frame, bounding box in mm), the complete assembly in its true pose, then red-on-gray component highlight rows infamily.jsoncomponentsorder — repeated instances grouped withquantity=Nby default,--per-instancefor one row per instance.uv run bench2 preview <family>runs the same render automatically whenbuild(**params)returns a named Assembly; single-part families are unchanged.execute_cq_to_parts) executes it in the usual subprocess and walks the Assembly exactly like cq'stoCompound(), exporting each shape-bearing node's raw local shape plus its absolute 3x4 world transform, so nested parent/childLocationtransforms survive without parsing STEP product structure.render_iso's VTK pipeline is generalized to styled multi-actor scenes (render_actors): shared normalized frame, camera fitted over the union of all actors, z-buffer depth occlusion.render_isois now the one-actor teal case — same pipeline, same bytes.docs/DESIGN_SPEC.md: name every shape-bearing node exactly after its component (quantity 1) or<component>_<NN>for repeated instances; exact declared names win over suffix stripping; semantically distinct components stay separate even with identical geometry.family.jsonmust declarecomponentswithsolidsequal to the quantity sum —bench2 validatenow checks that consistency, and every violation (non-Assembly result, unmatched or duplicate instance names, quantity drift) fails clearly instead of producing a misleading image.tests/(new, wired intovalidate.yml): hermetic fixture families through the real derive -> subprocess -> manifest -> VTK pipeline — nested locations, translation + rotation, repeated instances, grouped vs--per-instancerow layout, metadata mismatches, single-part skip/fail, and byte-determinism of the output PNG.Example — what it renders (in-repo, committed)
docs/examples/preview_parts_demo/is a runnable demo assembly — block, flanged bushing, and abolt_01/bolt_02pair in a nested, 30-deg-rotated sub-assembly — with both artifacts committed, embedded in DESIGN_SPEC, and kept runnable by a framework test.Grouped default — one four-view row per component (bbox in mm), the complete assembly in pose, then red-on-gray highlight rows in
componentsorder (bolthighlights both instances,quantity=2):--per-instance—bolt_01andbolt_02each get their own highlight row:--transparent— non-highlighted components ghosted (see-through): the bushing shaft buried in its bore and both bolt shanks stay visible when highlighted. The opaque modes above are unchanged (styles gained an opacity channel; existing output is byte-identical):Why
Multi-component families had no reproducible framework command for
preview_parts.png: the STEP path folds an Assembly into a compound, so component names and hierarchy never reach the renderer, and each assembly family hand-rolled its own render script.family-pr-checksand the dossier close-out already expect the artifact; this makes it a one-command, deterministic framework output (hard/ seed 0) for any unrelated named-Assembly family.Draft #96 explores the same surface and its layout is kept here (it matches the reviewer-approved artifact in #80); the framework difference is that this implementation renders the derived program via the standard subprocess harness rather than calling
part.build()in-process, so component evidence traces to the exact program the benchmark asks a model to produce.Validation
uv run ruff check framework tests— passuv run python -m unittest discover -s tests)bench2 validateon all three merged families — PASS (validate gate addition is inert for single-part families)bench2 preview-parts safety_swivel_load_ring(sources from [family] safety_swivel_load_ring #80, run in a scratch tree — that family and its PR are untouched) renders the 5-component grid; two consecutive runs produce byte-identical PNGs (same SHA-256),--per-instancedegenerates to the grouped layout as expected since every quantity is 1vtkFeatureEdgesdefaults; that is main's existing single-part behavior (visible in every committedpreview.png) and is deliberately preserved byte-for-byte here rather than restyled in the same PRFramework-only change: no file under
designs/is touched.Closes #95