# Clean Similar Objects

> Find duplicate / near-identical NON-CURVE Rhino objects in the current selection — polysurfaces (Breps), extrusions, meshes, and block instances that are stacked in the same place, or the same shape stored as different types (a Brep vs an Extrusion of the same solid). Type-agnostic, catches what SelDup misses on solids. REPORT-ONLY in v1 (diagnoses + counts, deletes nothing); v2 will delete coincident duplicates and boolean-split partial overlaps after confirmation. Trigger when the user wants to dedup / clean duplicate solids, polysurfaces, meshes, or blocks (not curves). Fire on Korean or English requests, e.g. "중복 솔리드 정리", "겹친 폴리서피스", "중복 블록", "duplicate polysurfaces", "dedup solids / breps / blocks". For CURVE dedup use the sibling `clean-similar-curves`.

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

---


# clean-similar-objects

Dedup the **currently selected** NON-CURVE objects. Sibling to `clean-similar-curves` (curves) and
`clean-geometry` (curve cleanup). One script next to this file, `simobj_diagnose.py`, invoked by the
usual one-line loader. **v1 is REPORT-ONLY** — it never deletes; it reports groups and stashes a plan
in `sc.sticky["simobj_plan"]` for a future v2 apply.

## What it detects
- **COINCIDENT duplicates** — same shape (topology counts + bbox extents) AND same place (bbox
  center within `CEN_TOL`). This is the paste-in-place / stacked case → keep one. Type-agnostic:
  a Brep and an Extrusion of the same solid match (extrusions are compared via `.ToBrep()`).
- **CONGRUENT copies** — same shape/size but a DIFFERENT place. Reported separately because they are
  usually intentional copies (repeated members) — for the user to eyeball, not auto-delete.
- Kinds handled: Breps + Extrusions (as breps), Meshes (vertex/face counts + bbox), block instances
  (same `InstanceDefinition` + same instance transform = stacked block).

## Procedure
1. **Resolve path.** Glob `**/clean-similar-objects/simobj_diagnose.py`. Do NOT hardcode.
2. **Diagnose (non-destructive).**
   ```python
   exec(open(r"<ABS>\simobj_diagnose.py").read())
   ```
   Prints counts per kind: coincident duplicate groups (+ removable count = keep 1 each) and congruent
   groups. Changes nothing.
3. **Report** to the user. v1 stops here (report-only). If the user wants deletion now, do it
   explicitly and per-item with confirmation (there is no bulk apply script yet).

## Gotchas (baked in)
- **Cheap fingerprint by design.** Uses topology counts + bbox extents + bbox center — NOT
  `VolumeMassProperties`/`AreaMassProperties`, which timed out on a real 340-brep / 2000-block model.
  Volume/centroid confirmation is a v2 refinement (add it only for the delete step, on the small
  candidate set, never on the whole selection).
- **Selection excludes locked/hidden.** `_SelAll` / `Objects.Select` skip objects on locked or hidden
  layers, so the diagnose sees only the selectable subset (e.g. 573 of 2338 on the test model). That's
  correct for a selection-based skill — unlock/show layers first if you mean to include them.
- **Coincident vs congruent split** prevents nuking legitimate arrays: only same-place stacks are
  "duplicates"; moved copies are flagged for review, never counted as removable.
- **Blocks** compared by definition index + instance transform, never by exploded geometry.

## Not yet implemented (deferred to v2, by user decision)
- **Apply / delete.** v1 reports only. v2: delete coincident duplicates (keep 1) after confirm, with a
  volume+centroid or `GeometryEquals`/closest-point equivalence check before each delete (never delete
  on the cheap fingerprint alone).
- **Partial-overlap solids → 3-chunk boolean split** (`CreateBooleanDifference` A−B / B−A +
  `CreateBooleanIntersection` A∩B) with the boolean guardrails: `SolidOrientation`/`Flip`,
  `SplitKinkyFaces`, null-vs-empty, validate `IsValid`/`IsSolid`. See the plan.
- **Congruent (moved) auto-dedup** — left as report-only (usually intentional).

## Reference
Built 2026-07-01 (task 1b of the 6-task suite). Diagnose validated on the live production model
`260629 main ms.3dm` (50 breps/extrusions + 523 blocks selectable → 0 coincident, 4 congruent brep
groups, no false positives). See memory `rhino-clean-rhino-method` and the plan.

