# Clean Geometry Solids

> clean-geometry-solids

- Skill: `hongikarchi/clean-geometry-solids` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add hongikarchi/clean-geometry-solids`
- Raw SKILL.md: https://api.skillmd.com/api/skills/hongikarchi/clean-geometry-solids/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: hongikarchi (https://skillmd.com/u/hongikarchi)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/hongikarchi/clean-geometry-solids

---


# clean-geometry-solids

Diagnose the **currently selected** polysurfaces/extrusions. Sibling to `clean-geometry` (curves).
One script next to this file, `cleangeosol_diagnose.py`, via the usual one-line loader. **v1 is
REPORT-ONLY** — reports counts and stashes a plan in `sc.sticky["cleangeosol_plan"]`; a v2 apply is
deferred.

## Checks
- **A. Open vs closed** — `Brep.IsSolid` → closed. Else count naked edges (`Edge.Valence ==
  EdgeAdjacency.Naked`) + total naked length, and classify **burst (fixable)** vs **open (intentional)**
  by testing whether `JoinNakedEdges(JOIN_TOL)` on a *duplicate* closes it or shrinks the naked count.
  Burst = the surfaces touch but aren't joined (repairable); intentional = large isolated naked loops.
- **B. Extrusion-convertibility** — for closed solids: find two parallel planar caps + confirm every
  side face normal is ⊥ to the sweep direction (prismatic). **Right prism → convertible**; a sheared
  cap offset → **oblique**, flagged NOT convertible (`Extrusion.Create` is perpendicular-only). Objects
  already `Rhino.Geometry.Extrusion` are skipped (already light).

## Procedure
1. **Resolve path.** Glob `**/clean-geometry-solids/cleangeosol_diagnose.py`. Do NOT hardcode.
2. **Diagnose.**
   ```python
   exec(open(r"<ABS>\cleangeosol_diagnose.py").read())
   ```
   Prints: closed/open/already-extrusion counts; burst-fixable vs intentional-open (with examples:
   id, naked-edge count, naked length, burst?); extrusion convertible vs oblique.
3. **Report.** v1 stops here. For a fix now, do it explicitly per object with confirmation.

## Gotchas (baked in)
- **Selection excludes locked/hidden.** Only selectable objects are scanned (e.g. 50 of 340 breps on
  the test model — the rest were on locked layers). Unlock/show layers to include them.
- **Burst test is on a DUPLICATE** (`DuplicateBrep().JoinNakedEdges`) so nothing is modified.
  `JOIN_TOL = 1000×tol` is a generous *detection* threshold — the v2 fix should use a tighter,
  confirmed value so it never welds truly-separate shells.
- **Oblique gate is essential.** A sheared prism looks convertible but `Extrusion.Create` (perpendicular
  extrude only) would silently build a *different* solid — so oblique prisms are reported as skip, not
  convertible. v2 must re-validate any rebuild by volume+centroid before replacing.
- **Complex breps skipped** for extrusion analysis (`Faces.Count > 400`) — a prism has few faces.
- **`EdgeAdjacency.Naked`** and `Surface.TryGetPlane` (tuple `[0]`=bool `[1]`=plane) are RhinoCommon;
  `Vector3d * Vector3d` is the dot product in IronPython.

## Not yet implemented (deferred to v2)
- **Apply.** v1 reports only. v2: `JoinNakedEdges(tol)` / `CapPlanarHoles` to close confirmed bursts;
  rebuild right prisms as `Extrusion.Create(profile, signedHeight, cap)` (holes via `SetOuterProfile`
  + `AddInnerProfile`) with post-convert volume/centroid validation before `Objects.Replace`.
- Distinguishing intentional-open more finely (paired-naked-edge fraction, planarity of the missing cap).
- Non-brep surfaces / meshes.

## Reference
Built 2026-07-01 (task 2 non-curve half of the 6-task suite). Diagnose validated on the live model
`260629 main ms.3dm` (50 selectable breps → 28 solid / 22 open-intentional / 23 extrusion-convertible /
1 oblique). See memory `rhino-clean-rhino-method` and the plan.

