Skip to content

Merge tied, nearly parallel plain edges in their exact order in no_fit_polygon - #73

Merged
fontanf merged 1 commit into
mainfrom
fix-nfp-nearly-parallel-edges
Sep 23, 2026
Merged

fontanf merged 1 commit into
mainfrom
fix-nfp-nearly-parallel-edges

Conversation

@fontanf

@fontanf fontanf commented Sep 23, 2026

Copy link
Copy Markdown
Owner

Fixes the cause of the failures remaining in fontanf/packingsolver#598 with the latest shape (after #71 and #72).

Problem

The convex no_fit_polygon merges the edges of both shapes in angular order. It compares directions with direction_strictly_lesser, whose tolerance is meant for the floating-point noise of arc tangents. But, on unit vectors, it also ties plain edges up to ~1e-6 rad apart. Tied plain edges were then always merged fixed first, which is the wrong order whenever the orbiting edge has the smaller direction: the vertex between them is replaced by one inside the actual Minkowski sum.

In packingsolver#598, instance B's hexagon has two edges ~9.5e-7 rad from parallel (edges 0 and 3). In its self-NFP, this happened on one side only:

  • the vertex (58.8411, -157.0224) was replaced by (130.8797, -104.8274), one edge length away;
  • the NFP was off the exact Minkowski sum by up to ~7e-5 (area 112131.8571 instead of 112131.8683), and was not centrally symmetric anymore.

The periodic packing then unions the inflated NFPs of a shape and of its half-turn. These should be identical, but differed by a few micro-units, and compute_union failed with "face area is not positive" or "outline area is not positive", or overflowed the stack.

Fix

Order tied plain edges by their exact directions (strictly_lesser_angle), and only merge the fixed one first if they are exactly parallel. Ties involving arcs are unchanged.

Testing

  • New NoFitPolygonConvexTest case: the self-NFP of that hexagon, against the exact Minkowski sum (computed with rational arithmetic). It fails on main and passes with the fix. Its grid-sampling oracle check takes ~4 s.
  • Issue558SawtoothSelfPairing: both expected_outputs variants are re-recorded, without and with fused multiply-adds. The result keeps the same structure (1 component, 883 elements, no self-intersection), with ~1.1e-4 more area, as expected since the old order put some vertices inside the actual Minkowski sums. Before re-recording them, I checked that a plain x86-64 build reproduces the old variant 0 exactly, and an x86-64 build with -mfma the old variant 1 (the AArch64 one).
  • All 497 tests pass, in both a plain and an -mfma build.
  • With packingsolver built against this branch, instances A, B and C of packingsolver#598 and 19 random perturbations of each (vertices moved by up to 1e-5) all solve: 60/60, against 42/60 with main.

…t_polygon

The convex no_fit_polygon merges the edges of both shapes in angular
order. It compares directions with direction_strictly_lesser, whose
tolerance is meant for the floating-point noise of arc tangents but, on
unit vectors, also ties plain edges up to ~1e-6 rad apart. Tied plain
edges were then always merged fixed first, which is the wrong order
whenever the orbiting edge has the smaller direction: the vertex
between them is replaced by one inside the actual Minkowski sum.

For the self-NFP of a hexagon whose edges 0 and 3 are ~9.5e-7 rad from
parallel (fontanf/packingsolver#598), this happened on one side only:
the NFP was off by up to ~7e-5, and not centrally symmetric anymore. The
periodic packing then unioned the (inflated) NFPs of a shape and of its
half-turn, which should be identical but differed by a few micro-units,
and compute_union failed ("face area is not positive", "outline area is
not positive") or overflowed the stack.

Order tied plain edges by their exact directions instead, and only
merge the fixed one first if they are exactly parallel.

New regression test: the self-NFP of that hexagon, against the exact
Minkowski sum. The two expected_outputs variants of
Issue558SawtoothSelfPairing are re-recorded (same structure, ~1.1e-4
more area).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant