Files
Kaz Walker fff3f983fc Cell Grid: cut a grid of hexagon, square, triangle, circle or polygon cells out of a part, inside a sketch's area (#14044) (#14045)
* claim: #14044

* solidcore: cell grid planner (which cells of a grid fit a closed region)

A kernel primitive for #14044: given closed 2D loops (the field, with
inner loops as keep-outs) and a grid spec (cell shape and size, web,
angle, anchor, clip mode), it returns the cells to cut.

- solidcore `cell_grid`: lattices for hexagon, square, triangle,
  circle and polygon cells; the region test; `snap` clips edge cells
  along the grid's own lines, `free` trims them to the drawn edge.
- solidcore-record and solidcore-convert: the spec and plan as records.
- solidcore-ops `plan_cell_grid`: the one call SolidCraft will make.

Nothing in SolidCraft uses it yet; the feature and command come next.

Co-Authored-By: Claude <noreply@anthropic.com>

* solidcore-ops: cell_regions turns a planned cell's loops into regions

A planned cell holds closed loops (counter-clockwise outer loops, clockwise
holes). Callers that build solids need them as regions: each outer loop with
the holes it contains. The grouping is the kernel's (`GridCell::regions`,
decided with the loops' signed areas and a point-in-loop test), the record
conversion is solidcore-convert's, and `solidcore_ops::cell_grid::cell_regions`
is the ops entry point.

Co-Authored-By: Claude <noreply@anthropic.com>

* Cell grid: solid.cell_grid cuts a grid of cells from a sketch's area (#14044)

A new feature and command fill the closed profiles of a sketch with cells of
one shape (hexagon, square, triangle, circle or polygon) and cut them out of
the bodies, to a depth or through all. An outer loop is the field, a loop
inside it a keep-out. Parameters: shape, sides, dot_grid, size, web, angle,
anchor (a 3D point projected onto the sketch plane, default the sketch
origin), clip (whole, snap or free), depth or through_all, direction, targets.
`mode` accepts only `cut` for now, so raised mode can follow.

The cells are planned by solidcore (`solidcore_ops::cell_grid`), each becomes
a prism along the sketch normal, and the prisms are one tool for one cut.
That cut and the check after it grow with the square of the cells (175 cells
15 s, 429 cells 86 s under load), so the feature refuses more than 250 cells
(`MAX_CUT_CELLS`) naming the count and the cap, and warns above 100. Sheet
metal is refused, pointing to sheet.perforate. The faces cut have no stable
names yet.

Command only: no dialog or ribbon entry yet. Adds the contract and reply
schema, the pending design-format note, the command label, the feature-walk
golden records and engine tests (exact volumes for depth and through all, a
keep-out, parameters, a sketch edit, the cap, sheet metal, refusals).

Co-Authored-By: Claude <noreply@anthropic.com>

* Cell grid: review fixes (reach, scope, nested holes, pitch, piece counts, snapping)

solid.cell_grid:
- A symmetric through-all cut takes the whole reach on each side; the reach was halved and
  left material on the far side of a plate whose face the sketch lies on.
- The through-all reach comes from each body's exact bounds, not its display mesh, and covers
  the bodies the cut really reaches (`targets: ["*"]` included).
- The sheet-metal refusal looks only at those bodies, so a solid in one component can be cut
  while another holds sheet metal.
- A grid that removes nothing says so, as other cuts do.
- A bare size or web is checked in the design's unit, and the anchor is read through the
  plane's own local-coordinates call.
- The schema text no longer states a cell limit that differs from MAX_CUT_CELLS.

solidcore cell grid planner:
- A hole of an island inside a hole goes to the island, the innermost outer loop around it.
- A loop's boundary pieces are counted once, so a valid loop of 632 pieces is not refused.
- Bezier degrees 1 to 3 are accepted; a curve needing more than 4096 pieces to stay within the
  tolerance is refused as too complex instead of followed loosely.
- Polygon cells keep the web to every neighbour: the pitch follows the polygon's width in each
  neighbour direction instead of its inscribed diameter.
- Triangle parity uses the low bits, so extreme indices cannot overflow.
- Loop and polygon areas are summed about a point of the loop, so a small loop far from the
  origin keeps its area.
- Collinear pieces and same-line edges merge in one pass round the ring, and two edges merge
  only when the vertex between them lies on the line, not when their angle is small.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-13 11:15:38 +00:00
..