clean-rhino
Whole-document cleanup orchestrator (task 3). Chains the two validated selection skills over
the whole model, then does document-level housekeeping (purge + material). Two new scripts live
next to this file: cleanrhino_purge.py and cleanrhino_material.py — both non-destructive by
default (report), destructive only when you set APPLY=True.
Stages
- clean-similar — remove duplicates/overlaps. Curves:
clean-similar-curves. Non-curves (polysurface/brep/mesh/block):clean-similar-objectsdiagnose (report-only v1). - clean-geometry — CAD-clean curves:
clean-geometry. Polysurfaces:clean-geometry-solidsdiagnose (open-vs-closed + extrusion, report-only v1). - purge — unused block definitions, empty groups, empty layers (
cleanrhino_purge.py) +_-Purgefor linetypes/hatch/dimstyles/materials. - material — white matte PBR "plaster" named after the layer, onto every material-less layer
(
cleanrhino_material.py).
Procedure (do in order)
- Model safety — ask first. clean-rhino is irreversible (purge can't be undone, dedup deletes,
material writes). Use AskUserQuestion: work on a SaveAs copy (recommended —
-SaveAsa new.3dmviarun_command, then operate there) vs the current doc (mustSaveSmallfirst). - Select everything to feed the selection skills the whole model:
run_command("_SelAll")(or select by the layers/objects the user means). The sibling skills act on the current selection. - clean-similar. Glob + run
clean-similar-curves(itsdedup_dryrun.py→ confirm →dedup_delete.py, per that skill's own procedure). Then, if present, Glob + run**/clean-similar-objects/simobj_diagnose.pyand report non-curve duplicates (v1 = report only; no deletes without explicit per-item confirmation). - clean-geometry. Run
clean-geometry(its diagnose → set SHORT_LEN → confirm → apply order, per that skill). Then, if present, run**/clean-geometry-solids/cleangeosol_diagnose.pyand report open/burst polysurfaces + extrusion candidates (v1 = report only). - purge.
Report counts, confirm, then:exec(open(r"<ABS>\cleanrhino_purge.py").read()) # dry-run: counts
Then the remaining categories via command (verify tokens against the live echo first):PURGE_APPLY=True; exec(open(r"<ABS>\cleanrhino_purge.py").read()) # purgerun_command("_-Purge")toggling BlockDefinitions/DimStyles/Groups/HatchPatterns/Layers/ Linetypes/Materials. Purging all 7 is broader than the spec's layer/block/group — mention it and let the user opt out of the extra categories. - material. Do this AFTER purge (so unused materials are gone and empty layers won't get one):
exec(open(r"<ABS>\cleanrhino_material.py").read()) # dry-run: material-less layers MAT_APPLY=True; exec(open(r"<ABS>\cleanrhino_material.py").read()) # assign white plaster - Report per stage (deduped / cleaned / purged / materials assigned). Offer to save. Offer to
update the
rhino-clean-geometry-method/rhino-curve-dedup-methodmemories if anything new was learned.
Why this order
- selection skills before document housekeeping — dedup/clean can empty layers and orphan block defs, which purge then sweeps.
- purge before material — purge clears empty layers (so material-assign only touches real, surviving layers) and removes unused materials before new ones are added. Do not reorder.
Gotchas (baked in — do not "fix" out)
- Both new scripts are dry-run unless
APPLY=True. Always run the dry-run, report, confirm, then APPLY. Same diagnose→confirm→apply discipline as the sibling skills. InstanceDefinitions.Purge(i)self-checks — it only deletes a block def that is truly unused (returns False otherwise), so it is safe to loop over all indices.- Layer delete order —
cleanrhino_purge.pydeletes deepest-nested empty layers first so a parent isn't blocked by a child that was just emptied. - Material naming — the material is named after the layer's short
Name. White plaster = PBR BaseColor white / Metallic 0 / Roughness 1; legacy white-diffuse fallback if PBR is unavailable. PBR BaseColor is what maps cleanly to D5 albedo downstream. _-Purgeis not undoable and neither are table deletes — SaveSmall or work on a copy (step 0).run_commandcommand tokens vary by build/locale — prefer_Englishtokens and confirm the_-Purgeoption echo before committing a macro string.
Not yet implemented / pending
- Non-curve stages (2/3 of step 2–3) are report-only and depend on the sibling skills
clean-similar-objects/clean-geometry-solids(build separately). If they're absent, note it and continue with the curve + purge + material stages. - LIVE VERIFICATION PENDING.
cleanrhino_purge.py/cleanrhino_material.pyare written from the RhinoCommon API but were authored while the Rhino MCP server was offline. Before trusting them, run the in-doc synthetic test (a material-less layer, an unused block def, an empty group) and assert the counts + that each material-less layer receives a white-plaster material named after it.
Reference
Built 2026-07-01 (task 3 of the 6-task cleanup/export suite). Orchestrates clean-similar-curves
clean-geometry(validated) and the report-only non-curve siblings, plus purge + material. See the plan and memoriesrhino-clean-geometry-method/rhino-curve-dedup-method.