fix(geometry): end PolyLabel's starting grid where steps stop advancing

Far from the origin a grid step smaller than the coordinate's
precision leaves x (or y) unchanged: at 1e16, 1e16 + 1 == 1e16. The
starting grid loop then never ended and allocated cells without limit,
even with the new maxCells budget (a hang dump reached 4.3 GB). Stop a
row or column once its step no longer advances.

Grids that advance are untouched, so the bit-identical differential
against the former sorted-list implementation still passes. Found by
the independent quality review of the Clipper2 overlap branch.
This commit is contained in:
aj committed 2026-10-15 23:31:14 -04:00
1 parent 80d01839bd
commit 83b606c486
2 files changed
+25

No files matched your search

+10
View File
@@ -73,8 +73,18 @@ namespace OpenNest.Geometry
var initial = new List<Cell>();
for (var x = minX; x < maxX; x += cellSize)
{
for (var y = minY; y < maxY; y += cellSize)
{
initial.Add(new Cell(x + halfCell, y + halfCell, halfCell, outer, holes));
// Far from the origin a step smaller than the coordinate's precision
// no longer advances; the grid would never end.
if (y + cellSize == y)
break;
}
if (x + cellSize == x)
break;
}
initial.Sort((a, b) => b.MaxDist.CompareTo(a.MaxDist));
@@ -68,6 +68,21 @@ public class PolyLabelDifferentialTests
Assert.True(Same(PolyLabel.Find(shape), PolyLabel.Find(shape, null, 0.5, int.MaxValue)));
}
// Quality review: at 1e16 a 1-unit grid step no longer changes x (1e16 + 1 == 1e16), and
// the starting grid loop never ended, allocating cells without limit even with a budget.
[Fact]
public async Task Find_FinishesWhenGridStepsStopAdvancingFarFromTheOrigin()
{
var far = Rectangle(1e16, 0, 8, 1);
var search = Task.Run(() => (PolyLabel.Find(far, null, 0.01, 4096), PolyLabel.Find(far, null, 0.01)));
Assert.Same(search, await Task.WhenAny(search, Task.Delay(TimeSpan.FromSeconds(20))));
var (bounded, unbounded) = await search;
Assert.InRange(bounded.Y, 0, 1);
Assert.InRange(unbounded.Y, 0, 1);
}
private static (Polygon outer, List<Polygon> holes) RandomShape(Random random)
{
var scale = System.Math.Pow(10, random.NextDouble() * 4 - 1);