From d4d907e56fd6e1bf94d1e52e76ed23efd2084579 Mon Sep 17 00:00:00 2001 From: Ahmed Alshaybani Date: Tue, 20 Oct 2026 05:52:11 +0200 Subject: [PATCH] fix: coalesce outline grid coordinates within EPS --- .../computeInverseRects.ts | 23 +++++++++++++-- .../compute-inverse-rects-board109.snap.svg | 4 +-- ...mpute-inverse-rects-narrow-feature.test.ts | 29 +++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 tests/compute-inverse-rects-narrow-feature.test.ts diff --git a/lib/solvers/RectDiffSeedingSolver/computeInverseRects.ts b/lib/solvers/RectDiffSeedingSolver/computeInverseRects.ts index fe81a07..587db69 100644 --- a/lib/solvers/RectDiffSeedingSolver/computeInverseRects.ts +++ b/lib/solvers/RectDiffSeedingSolver/computeInverseRects.ts @@ -8,6 +8,22 @@ type ComputeInverseRectsOptions = { minGridSize?: number } +/** Merge grid lines separated only by floating-point roundoff. */ +function getUniqueGridCoordinates(coordinates: Set): number[] { + const sortedCoordinates = Array.from(coordinates).sort((a, b) => a - b) + const uniqueCoordinates: number[] = [] + for (const coordinate of sortedCoordinates) { + const previousCoordinate = uniqueCoordinates.at(-1) + if ( + previousCoordinate === undefined || + coordinate - previousCoordinate > EPS + ) { + uniqueCoordinates.push(coordinate) + } + } + return uniqueCoordinates +} + /** * Simplify a polygon by reducing coordinate precision to avoid excessive grid cells. * This rounds coordinates to a grid and removes duplicates. @@ -121,8 +137,11 @@ export function computeInverseRects( Math.max(bounds.width, bounds.height) / MAX_DIAGONAL_SUBDIVISIONS, ), }) - const xSorted = Array.from(xs).sort((a, b) => a - b) - const ySorted = Array.from(ys).sort((a, b) => a - b) + // Symmetric diagonal edges can produce coordinates that differ only by + // floating-point roundoff. Treat them as the same grid line before forming + // cells; otherwise slivers fragment the subsequent merge passes. + const xSorted = getUniqueGridCoordinates(xs) + const ySorted = getUniqueGridCoordinates(ys) // 2. Generate grid cells and classify them const rawRects: XYRect[] = [] diff --git a/tests/__snapshots__/compute-inverse-rects-board109.snap.svg b/tests/__snapshots__/compute-inverse-rects-board109.snap.svg index 08713be..a7b9891 100644 --- a/tests/__snapshots__/compute-inverse-rects-board109.snap.svg +++ b/tests/__snapshots__/compute-inverse-rects-board109.snap.svg @@ -1,4 +1,4 @@ -Board 109: 19985 void rectangles14696 slivers at or below EPS (1e-9 mm)Upper-right detail: 39 intersecting rectangles