Merge branch 'fix/bestfit-overlap-test'
Fixes BestFit overlap check to agree with the geometry BuildParts actually places, resolving BestFitOverlapTests.KeptPairs_NoOverlap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -58,19 +58,6 @@ namespace OpenNest.Engine.BestFit
|
|||||||
part2.Location = candidate.Part2Offset;
|
part2.Location = candidate.Part2Offset;
|
||||||
part2.UpdateBounds();
|
part2.UpdateBounds();
|
||||||
|
|
||||||
// Overlap check — perimeter vs perimeter. Uses Collision.HasOverlap (full polygon
|
|
||||||
// clip) rather than Shape.Intersects (edge-crossing only), which misses containment-
|
|
||||||
// style overlaps where one perimeter's boundary never crosses the other's.
|
|
||||||
var shape1 = GetPerimeterShape(part1);
|
|
||||||
var shape2 = GetPerimeterShape(part2);
|
|
||||||
var overlaps =
|
|
||||||
shape1 != null
|
|
||||||
&& shape2 != null
|
|
||||||
&& Collision.HasOverlap(
|
|
||||||
shape1.ToPolygonWithTolerance(OverlapChordTolerance),
|
|
||||||
shape2.ToPolygonWithTolerance(OverlapChordTolerance)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Convex hull vertices from perimeter polygons only
|
// Convex hull vertices from perimeter polygons only
|
||||||
var allPoints = GetPartVertices(part1);
|
var allPoints = GetPartVertices(part1);
|
||||||
allPoints.AddRange(GetPartVertices(part2));
|
allPoints.AddRange(GetPartVertices(part2));
|
||||||
@@ -106,7 +93,9 @@ namespace OpenNest.Engine.BestFit
|
|||||||
|
|
||||||
var trueArea = candidate.Drawing.Area * 2;
|
var trueArea = candidate.Drawing.Area * 2;
|
||||||
|
|
||||||
// Normalize to landscape (width >= height) for consistent display.
|
// Normalize to landscape (width >= height) for consistent display. Do this before
|
||||||
|
// the overlap check so bestRotation already matches the final OptimalRotation that
|
||||||
|
// BuildParts will apply.
|
||||||
if (bestHeight > bestWidth)
|
if (bestHeight > bestWidth)
|
||||||
{
|
{
|
||||||
var tmp = bestWidth;
|
var tmp = bestWidth;
|
||||||
@@ -115,6 +104,33 @@ namespace OpenNest.Engine.BestFit
|
|||||||
bestRotation += Angle.HalfPI;
|
bestRotation += Angle.HalfPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Overlap check — perimeter vs perimeter, in the same final orientation BuildParts
|
||||||
|
// uses downstream. Uses Collision.HasOverlap (full polygon clip) rather than
|
||||||
|
// Shape.Intersects (edge-crossing only), which misses containment-style overlaps
|
||||||
|
// where one perimeter's boundary never crosses the other's. Checking pre-rotation
|
||||||
|
// geometry here (rather than rotating part1/part2 first, matching BuildParts) would
|
||||||
|
// tessellate arcs at a different orientation than the geometry actually gets placed
|
||||||
|
// with, letting tangent-corner slivers slip through in one frame but not the other.
|
||||||
|
if (!bestRotation.IsEqualTo(0))
|
||||||
|
{
|
||||||
|
var pairBounds = (
|
||||||
|
(IEnumerable<IBoundable>)new IBoundable[] { part1, part2 }
|
||||||
|
).GetBoundingBox();
|
||||||
|
var center = pairBounds.Center;
|
||||||
|
part1.Rotate(-bestRotation, center);
|
||||||
|
part2.Rotate(-bestRotation, center);
|
||||||
|
}
|
||||||
|
|
||||||
|
var shape1 = GetPerimeterShape(part1);
|
||||||
|
var shape2 = GetPerimeterShape(part2);
|
||||||
|
var overlaps =
|
||||||
|
shape1 != null
|
||||||
|
&& shape2 != null
|
||||||
|
&& Collision.HasOverlap(
|
||||||
|
shape1.ToPolygonWithTolerance(OverlapChordTolerance),
|
||||||
|
shape2.ToPolygonWithTolerance(OverlapChordTolerance)
|
||||||
|
);
|
||||||
|
|
||||||
return new BestFitResult
|
return new BestFitResult
|
||||||
{
|
{
|
||||||
Candidate = candidate,
|
Candidate = candidate,
|
||||||
|
|||||||
Reference in New Issue
Block a user