Skip to content

Implement a real skeletonize() — connectivity-preserving thinning peel, distinct from _layerize (needs the precise medial rule) #223

Description

@domattioli

Goal

After renaming the layer-peel to _layerize (#221, the rename PR), CHILmesh needs a genuine skeletonize(): an iterative inward peel that mimics the layerize machinery (peel, record what was peeled, repeat until you cannot peel) but with the skeletonization peel rule — keep peeling removable boundary elements until only the irreducible medial spine remains, tracking the peel order. Output: the skeleton elements + the per-element peel pass.

The distinction from _layerize (which removes the entire boundary ring each pass with no topology test and shrinks to empty) is documented in docs/CONCEPTS.md.

What I tried (and why a naive version is not enough)

Prototyped three peel rules on a triangulated L-shape (n ≈ 2,300–3,000 tri elements) and measured the result's element count, fraction of the mesh, and connected components of the resulting "skeleton" (a real skeleton should be ~1-wide and few components):

Rule Skeleton size Components Verdict
Local thinning — remove a boundary elem with ≥2 contiguous active neighbours, keep elems with <2 (endpoint retention) ~901 / 3044 (30%) 711 ❌ disconnected blobs — endpoint rule freezes interior spurs during the 2-D bulk phase
Global connectivity-preserving — remove a boundary elem only if the active dual graph stays connected 1 elem 1 ❌ collapses to a point — a simply-connected region thins to a single element with no endpoint preservation
Innermost layers (layer_index ≥ n_layers−1) 34 / 2276 (1.5%) 1 ✅ clean connected spine — but this is _layerize's output, not a distinct skeletonization peel

So: a correct mesh skeletonization needs both simple-element (topology-preserving) removal and proper endpoint preservation, applied with thinning-mask timing (à la Zhang–Suen, but defined on a 2-D face complex). The local/global shortcuts each fail one half. The innermost-layer derivation is clean and connected but does not satisfy "a distinct peel with skeletonization rules."

Decision needed (the precise rule)

Which semantics should skeletonize() implement?

  1. Front-collision medial extraction from the layer peel — the medial spine is where opposing peel fronts collide during _layerize (the thesis QuADMESH+ approach). Likely uses the IV/IE (inner vertex/element) collision data already recorded per layer. Connected + thin by construction.
  2. True 2-D face-complex thinning — simple-element removal + endpoint masks, tuned so it neither disconnects nor collapses. More work; needs a precise "simple element" + "endpoint element" definition for tri/quad faces.
  3. Innermost-layer derivation — accept the clean-but-not-a-separate-peel option (essentially skeleton = elements in the deepest k layers).

My read is (1) matches the thesis and the "skeletonization version of the peel" framing best, and reuses the layer-collision data. But this is the author's specialized algorithm — please confirm the exact rule before implementation so we don't ship a third wrong version.

Until then, skeletonize() is intentionally not added (the broken prototype was reverted); _layerize + its _skeletonize compat alias remain.

[model: claude-opus-4-8, repo: CHILmesh, session: 2026-06-16T08Z]

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: normalDefault importance.request: researchRequest for an investigation; deliverable is a report.status: brainstormingDesign phase; not yet implementable. Agents do NOT open a PR while in this state.type: featNew capability or skill.

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions