test: add hole subtraction and batch collision tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenNest.Tests;
|
||||
|
||||
@@ -85,6 +86,99 @@ public class CollisionTests
|
||||
Assert.True(result.OverlapArea > 0.49 && result.OverlapArea < 0.51);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Square A has a hole. Square B overlaps only the hole area.
|
||||
/// This should NOT be a collision — B fits inside A's cutout.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Check_OverlapInsideHole_ReturnsNone()
|
||||
{
|
||||
var a = MakeSquare(0, 0, 4, 4);
|
||||
var holeA = new List<Polygon> { MakeSquare(1, 1, 3, 3) };
|
||||
|
||||
// B fits entirely inside the hole
|
||||
var b = MakeSquare(1.5, 1.5, 2.5, 2.5);
|
||||
|
||||
var result = Collision.Check(a, b, holesA: holeA);
|
||||
|
||||
Assert.False(result.Overlaps);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Square A has a hole. Square B partially overlaps the hole and
|
||||
/// partially overlaps solid material. Should still be a collision.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Check_PartialOverlapWithHole_StillOverlaps()
|
||||
{
|
||||
var a = MakeSquare(0, 0, 4, 4);
|
||||
var holeA = new List<Polygon> { MakeSquare(1, 1, 3, 3) };
|
||||
|
||||
// B extends beyond the hole into solid material
|
||||
var b = MakeSquare(2, 2, 5, 5);
|
||||
|
||||
var result = Collision.Check(a, b, holesA: holeA);
|
||||
|
||||
// Hole subtraction uses a conservative approach (keeps partial overlaps),
|
||||
// so we only verify that a collision is still detected for solid material.
|
||||
Assert.True(result.Overlaps);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// HasOverlap with holes returns false when overlap is inside cutout.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void HasOverlap_InsideHole_ReturnsFalse()
|
||||
{
|
||||
var a = MakeSquare(0, 0, 4, 4);
|
||||
var holeA = new List<Polygon> { MakeSquare(1, 1, 3, 3) };
|
||||
var b = MakeSquare(1.5, 1.5, 2.5, 2.5);
|
||||
|
||||
Assert.False(Collision.HasOverlap(a, b, holesA: holeA));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckAll_MultiplePolygons_FindsAllOverlaps()
|
||||
{
|
||||
var a = MakeSquare(0, 0, 1, 1);
|
||||
var b = MakeSquare(0.5, 0, 1.5, 1); // overlaps A
|
||||
var c = MakeSquare(5, 5, 6, 6); // overlaps nobody
|
||||
|
||||
var results = Collision.CheckAll(new List<Polygon> { a, b, c });
|
||||
|
||||
Assert.Single(results);
|
||||
Assert.True(results[0].Overlaps);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckAll_NoOverlaps_ReturnsEmpty()
|
||||
{
|
||||
var a = MakeSquare(0, 0, 1, 1);
|
||||
var b = MakeSquare(3, 3, 4, 4);
|
||||
|
||||
var results = Collision.CheckAll(new List<Polygon> { a, b });
|
||||
|
||||
Assert.Empty(results);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasAnyOverlap_WithOverlap_ReturnsTrue()
|
||||
{
|
||||
var a = MakeSquare(0, 0, 1, 1);
|
||||
var b = MakeSquare(0.5, 0, 1.5, 1);
|
||||
|
||||
Assert.True(Collision.HasAnyOverlap(new List<Polygon> { a, b }));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HasAnyOverlap_NoOverlap_ReturnsFalse()
|
||||
{
|
||||
var a = MakeSquare(0, 0, 1, 1);
|
||||
var b = MakeSquare(3, 3, 4, 4);
|
||||
|
||||
Assert.False(Collision.HasAnyOverlap(new List<Polygon> { a, b }));
|
||||
}
|
||||
|
||||
private static Polygon MakeSquare(double left, double bottom, double right, double top)
|
||||
{
|
||||
var p = new Polygon();
|
||||
|
||||
Reference in New Issue
Block a user