2.2 KiB
optimizer/redundancy/redundancy.ts — cross-layer redundancy elimination
(no submodules)
Purpose
This module owns eliminateRedundant, the final cross-layer optimisation
the converter runs after every layer's cover has been built. It removes
rectangles that produce no visible output: either because higher-z
rectangles of any colour overdraw them, or because sibling rectangles in
the same layer already cover the same cells. The pass operates in place
on the layer list and is the only pass that mutates layer.rects.
Features
- Composites every layer into a per-cell
targetgrid first (lower-z to higher-z), then walks rect by rect deciding whether removal would change the composited output. - A rect is removed iff every one of its required cells is either covered by a sibling rect at the same z-index or overdrawn by a higher-z rect of any colour.
- In-place mutation via
Array.prototype.splice— the converter calls this once per ordering, so the in-place form keeps allocations bounded.
Usage: Basic
import { eliminateRedundant } from "@suaveplan/emblem-solver";
eliminateRedundant(layers, width, height);
Usage: Advanced
import { eliminateRedundant } from "@suaveplan/emblem-solver";
const before = layers.reduce((s, l) => s + l.rects.length, 0);
eliminateRedundant(layers, width, height);
const after = layers.reduce((s, l) => s + l.rects.length, 0);
console.log(`pruned ${before - after} redundant rects`);
API Reference
| Symbol | Kind | Description |
|---|---|---|
eliminateRedundant(layers, width, height) |
fn | In-place prune of fully-occluded rects |
Implementation Notes
The compositing step builds a (string | null)[][] grid keyed by the
canonical colour key — using a string rather than a packed integer makes
the per-cell comparison a single === against the layer's fill string,
which V8 deduplicates aggressively. The two-pass design (composite first,
then walk rect by rect) avoids the quadratic blow-up of repeatedly
re-compositing after each removal. The removable indices are pushed in
ascending order and spliced in reverse, so we never break the index
correspondence mid-removal.