From a9af5effc58e341a6a211217293b53f5f7cd5358 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sun, 8 Mar 2026 15:43:27 -0400 Subject: [PATCH] feat: add Plate.GetRemnants() for finding empty edge strips Co-Authored-By: Claude Opus 4.6 --- OpenNest.Core/Plate.cs | 82 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/OpenNest.Core/Plate.cs b/OpenNest.Core/Plate.cs index 5e01d5b..2614922 100644 --- a/OpenNest.Core/Plate.cs +++ b/OpenNest.Core/Plate.cs @@ -473,5 +473,87 @@ namespace OpenNest return pts.Count > 0; } + + /// + /// Finds rectangular remnant (empty) regions on the plate. + /// Returns strips along edges that are clear of parts. + /// + public List GetRemnants() + { + var work = WorkArea(); + var results = new List(); + + if (Parts.Count == 0) + { + results.Add(work); + return results; + } + + var obstacles = new List(); + foreach (var part in Parts) + obstacles.Add(part.BoundingBox.Offset(PartSpacing)); + + // Right strip: from the rightmost part edge to the work area right edge + var maxRight = double.MinValue; + foreach (var box in obstacles) + { + if (box.Right > maxRight) + maxRight = box.Right; + } + + if (maxRight < work.Right) + { + var strip = new Box(maxRight, work.Bottom, work.Right - maxRight, work.Height); + if (strip.Area() > 1.0) + results.Add(strip); + } + + // Top strip: from the topmost part edge to the work area top edge + var maxTop = double.MinValue; + foreach (var box in obstacles) + { + if (box.Top > maxTop) + maxTop = box.Top; + } + + if (maxTop < work.Top) + { + var strip = new Box(work.Left, maxTop, work.Width, work.Top - maxTop); + if (strip.Area() > 1.0) + results.Add(strip); + } + + // Bottom strip: from work area bottom to the lowest part edge + var minBottom = double.MaxValue; + foreach (var box in obstacles) + { + if (box.Bottom < minBottom) + minBottom = box.Bottom; + } + + if (minBottom > work.Bottom) + { + var strip = new Box(work.Left, work.Bottom, work.Width, minBottom - work.Bottom); + if (strip.Area() > 1.0) + results.Add(strip); + } + + // Left strip: from work area left to the leftmost part edge + var minLeft = double.MaxValue; + foreach (var box in obstacles) + { + if (box.Left < minLeft) + minLeft = box.Left; + } + + if (minLeft > work.Left) + { + var strip = new Box(work.Left, work.Bottom, minLeft - work.Left, work.Height); + if (strip.Area() > 1.0) + results.Add(strip); + } + + return results; + } } }