Files
2026-05-27 23:47:53 +01:00

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 target grid 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.