# `grid/analyse/analyse.ts` — colour groups, islands, and shape stats _(no submodules)_ ## Purpose This module owns `analyseGrid`, the diagnostic phase of the conversion pipeline. It walks an RGBA grid once, buckets opaque pixels by colour, runs a 4-connected flood-fill on each bucket to recover the islands, and computes per-colour `density` (`pixels / bbox area`) and `fragmentation` (`islands / pixels`). The result feeds the layer-ordering heuristics and the per-island cover strategy in the solver pipeline. ## Features - Single linear pass over the grid to populate `opaquePixels` and the colour buckets. - 4-connected BFS flood-fill — diagonals are treated as separate islands, matching the upstream reference and the convention used by every pixel-art tool. - Density and fragmentation are pure functions of the bucket and its bounding box; the solver uses both to score the `island-aware` ordering. - Output is structurally shared with the rest of the package via `GridAnalysis` — solver kernels consume `colourGroups`/`colourAnalysis` directly. ## Usage: Basic ```ts import { analyseGrid } from "@suaveplan/emblem-solver"; const { colourGroups, colourAnalysis } = analyseGrid(pixels, w, h); console.log("colours:", colourGroups.size); ``` ## Usage: Advanced ```ts import { analyseGrid } from "@suaveplan/emblem-solver"; function pickBackgroundColour(pixels, w, h) { const a = analyseGrid(pixels, w, h); let best = ""; let bestScore = -Infinity; for (const [key, info] of a.colourAnalysis) { const score = info.totalPixels * info.density; if (score > bestScore) { best = key; bestScore = score; } } return best; } ``` ## API Reference | Symbol | Kind | Description | |---|---|---| | `analyseGrid(pixels, w, h)` | fn | Returns `GridAnalysis` | ## Implementation Notes The flood-fill uses an explicit stack (`pop()`) rather than recursion to avoid blowing the call stack on large emblems. We `add` to `visited` *before* enqueueing the neighbour, which guarantees each pixel is touched at most twice (once when discovered, once when its packed index is popped). The neighbour set is computed as a small inline array of `-1`-sentinel checks for the four cardinal directions; benchmarks against a `for (const [dx,dy] …)` form showed the inline form measurably faster in V8 and Bun. The `Map>` colour-group layout is intentional: the string key is the canonical colour identity, while the packed-index `Set` gives O(1) `has`/`add`/`delete` for the cover strategies.