From a7c2fcffe6c9c866f4fbcd6837900568cf61f400 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sun, 29 Mar 2026 09:43:31 -0400 Subject: [PATCH] test: add edge case tests for Collision; update CLAUDE.md --- CLAUDE.md | 2 +- OpenNest.Tests/CollisionTests.cs | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 87d39b4..81ddec6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,7 +25,7 @@ Domain model, geometry, and CNC primitives organized into namespaces: - **Root** (`namespace OpenNest`): Domain model — `Nest` → `Plate[]` → `Part[]` → `Drawing` → `Program`. A `Nest` is the top-level container. Each `Plate` has a size, material, quadrant, spacing, and contains placed `Part` instances. Each `Part` references a `Drawing` (the template) and has its own location/rotation. A `Drawing` wraps a CNC `Program`. Also contains utilities: `PartGeometry`, `Align`, `Sequence`, `Timing`. - **CNC** (`CNC/`, `namespace OpenNest.CNC`): `Program` holds a list of `ICode` instructions (G-code-like: `RapidMove`, `LinearMove`, `ArcMove`, `SubProgramCall`). Programs support absolute/incremental mode conversion, rotation, offset, bounding box calculation, and cloning. -- **Geometry** (`Geometry/`, `namespace OpenNest.Geometry`): Spatial primitives (`Vector`, `Box`, `Size`, `Spacing`, `BoundingBox`, `IBoundable`) and higher-level shapes (`Line`, `Arc`, `Circle`, `Polygon`, `Shape`) used for intersection detection, area calculation, and DXF conversion. Also contains `Intersect` (intersection algorithms), `ShapeBuilder` (entity chaining), `GeometryOptimizer` (line/arc merging), `SpatialQuery` (directional distance, ray casting, box queries), `ShapeProfile` (perimeter/area analysis), `NoFitPolygon`, `InnerFitPolygon`, `ConvexHull`, `ConvexDecomposition`, and `RotatingCalipers`. +- **Geometry** (`Geometry/`, `namespace OpenNest.Geometry`): Spatial primitives (`Vector`, `Box`, `Size`, `Spacing`, `BoundingBox`, `IBoundable`) and higher-level shapes (`Line`, `Arc`, `Circle`, `Polygon`, `Shape`) used for intersection detection, area calculation, and DXF conversion. Also contains `Intersect` (intersection algorithms), `ShapeBuilder` (entity chaining), `GeometryOptimizer` (line/arc merging), `SpatialQuery` (directional distance, ray casting, box queries), `ShapeProfile` (perimeter/area analysis), `NoFitPolygon`, `InnerFitPolygon`, `ConvexHull`, `ConvexDecomposition`, `RotatingCalipers`, and `Collision` (overlap detection with Sutherland-Hodgman polygon clipping and hole subtraction). - **Converters** (`Converters/`, `namespace OpenNest.Converters`): Bridges between CNC and Geometry — `ConvertProgram` (CNC→Geometry), `ConvertGeometry` (Geometry→CNC), `ConvertMode` (absolute↔incremental). - **Math** (`Math/`, `namespace OpenNest.Math`): `Angle` (radian/degree conversion), `Tolerance` (floating-point comparison), `Trigonometry`, `Generic` (swap utility), `EvenOdd`, `Rounding` (factor-based rounding). Note: `OpenNest.Math` shadows `System.Math` — use `System.Math` fully qualified where both are needed. - **CNC/CuttingStrategy** (`CNC/CuttingStrategy/`, `namespace OpenNest.CNC`): `ContourCuttingStrategy` orchestrates cut ordering, lead-ins/lead-outs, and tabs. Includes `LeadIn`/`LeadOut` hierarchies (line, arc, clean-hole variants), `Tab` hierarchy (normal, machine, breaker), and `CuttingParameters`/`AssignmentParameters`/`SequenceParameters` configuration. diff --git a/OpenNest.Tests/CollisionTests.cs b/OpenNest.Tests/CollisionTests.cs index 153dd2c..7c93b76 100644 --- a/OpenNest.Tests/CollisionTests.cs +++ b/OpenNest.Tests/CollisionTests.cs @@ -179,6 +179,31 @@ public class CollisionTests Assert.False(Collision.HasAnyOverlap(new List { a, b })); } + [Fact] + public void Check_IdenticalSquares_FullOverlap() + { + var a = MakeSquare(0, 0, 1, 1); + var b = MakeSquare(0, 0, 1, 1); + + var result = Collision.Check(a, b); + + Assert.True(result.Overlaps); + Assert.True(result.OverlapArea > 0.99 && result.OverlapArea < 1.01); + } + + [Fact] + public void HasAnyOverlap_SinglePolygon_ReturnsFalse() + { + var a = MakeSquare(0, 0, 1, 1); + Assert.False(Collision.HasAnyOverlap(new List { a })); + } + + [Fact] + public void HasAnyOverlap_EmptyList_ReturnsFalse() + { + Assert.False(Collision.HasAnyOverlap(new List())); + } + private static Polygon MakeSquare(double left, double bottom, double right, double top) { var p = new Polygon();