first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
# `optimizer/merge/merge.ts` — adjacent-rect merge pass
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module owns `mergeAdjacentRects`, the post-processing pass that
combines pairs of edge-sharing same-extent rectangles into a single larger
rectangle, provided the merged span lies entirely inside the available
mask. It is the cheapest of the optimiser passes and runs after every
covering strategy in the layer pipeline.
## Features
- Merges along both axes: two rects with the same `y` and `h` merge
horizontally when adjacent; two rects with the same `x` and `w` merge
vertically when adjacent.
- Iterates until a full pass produces no merges, so chains of three or
more rects collapse to one in `O(n²)` per pass and `O(k · n²)` overall
for `k` passes (bounded by the rect count).
- Available-mask check (`isFullyAvailable`) guarantees the merged span
never paints transparent cells.
## Usage: Basic
```ts
import { mergeAdjacentRects } from "@suaveplan/emblem-solver";
const merged = mergeAdjacentRects(
[
{ x: 0, y: 0, w: 1, h: 1 },
{ x: 1, y: 0, w: 1, h: 1 },
],
fullyAvailableGrid
);
// merged === [{ x: 0, y: 0, w: 2, h: 1 }]
```
## Usage: Advanced
```ts
import { mergeAdjacentRects } from "@suaveplan/emblem-solver";
let rects = greedyCover;
rects = mergeAdjacentRects(rects, available);
rects = mergeAdjacentRects(rects, available); // idempotent — no further change
```
## API Reference
| Symbol | Kind | Description |
|---|---|---|
| `mergeAdjacentRects(rects, available)` | fn | Greedily merge edge-sharing same-extent rects |
## Implementation Notes
The inner `tryMerge` first tests the horizontal merge (same `y`, same
`h`, sharing an edge in `x`), then the vertical merge (same `x`, same
`w`, sharing an edge in `y`). Either form checks the combined rectangle
against `available` before accepting; this avoids painting through
transparent pixels. The outer loop terminates when a full pass produces
zero merges, so each call is idempotent. We deliberately do not try
*non*-same-extent merges here — that is the job of `optimiseOverlap`,
which can produce overlapping output and is therefore a strictly stronger
(but more expensive) operation.