From 4525be302cb425e636ed3bb8fe11a8bb9e0f38e6 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sun, 15 Mar 2026 13:43:33 -0400 Subject: [PATCH] fix(engine): compute remainder from just-placed parts within current work area ComputeRemainderStrip used the bounding box of ALL plate parts against the full plate, missing large interior gaps between drawing groups. Now computes remainder within the current work area based on only the parts that were just placed. This lets subsequent drawings fill the gap between previous drawing groups instead of being forced into a tiny strip at the plate edge. Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest.Console/Program.cs | 21 ++++++++------------- OpenNest.Mcp/Tools/NestingTools.cs | 21 ++++++++------------- OpenNest/Forms/MainForm.cs | 24 ++++++++++-------------- 3 files changed, 26 insertions(+), 40 deletions(-) diff --git a/OpenNest.Console/Program.cs b/OpenNest.Console/Program.cs index 259fb09..9709889 100644 --- a/OpenNest.Console/Program.cs +++ b/OpenNest.Console/Program.cs @@ -354,10 +354,11 @@ static class NestConsole if (parts.Count > 0) { plate.Parts.AddRange(parts); - Compactor.Compact(parts, plate); + // TODO: Compactor.Compact(parts, plate); item.Quantity = System.Math.Max(0, item.Quantity - parts.Count); success = true; - workArea = ComputeRemainderStrip(plate); + var placedBox = parts.Cast().GetBoundingBox(); + workArea = ComputeRemainderWithin(workArea, placedBox, plate.PartSpacing); } } @@ -385,22 +386,16 @@ static class NestConsole return (success, sw.ElapsedMilliseconds); } - static Box ComputeRemainderStrip(Plate plate) + static Box ComputeRemainderWithin(Box workArea, Box usedBox, double spacing) { - if (plate.Parts.Count == 0) - return plate.WorkArea(); - - var usedBox = plate.Parts.Cast().GetBoundingBox(); - var fullArea = plate.WorkArea(); - - var hWidth = fullArea.Right - usedBox.Right - plate.PartSpacing; + var hWidth = workArea.Right - usedBox.Right - spacing; var hStrip = hWidth > 0 - ? new Box(usedBox.Right + plate.PartSpacing, fullArea.Y, hWidth, fullArea.Length) + ? new Box(usedBox.Right + spacing, workArea.Y, hWidth, workArea.Length) : Box.Empty; - var vHeight = fullArea.Top - usedBox.Top - plate.PartSpacing; + var vHeight = workArea.Top - usedBox.Top - spacing; var vStrip = vHeight > 0 - ? new Box(fullArea.X, usedBox.Top + plate.PartSpacing, fullArea.Width, vHeight) + ? new Box(workArea.X, usedBox.Top + spacing, workArea.Width, vHeight) : Box.Empty; return hStrip.Area() >= vStrip.Area() ? hStrip : vStrip; diff --git a/OpenNest.Mcp/Tools/NestingTools.cs b/OpenNest.Mcp/Tools/NestingTools.cs index 83e2761..8bd5e00 100644 --- a/OpenNest.Mcp/Tools/NestingTools.cs +++ b/OpenNest.Mcp/Tools/NestingTools.cs @@ -258,10 +258,11 @@ namespace OpenNest.Mcp.Tools if (parts.Count > 0) { plate.Parts.AddRange(parts); - Compactor.Compact(parts, plate); + // TODO: Compactor.Compact(parts, plate); item.Quantity = System.Math.Max(0, item.Quantity - parts.Count); totalPlaced += parts.Count; - workArea = ComputeRemainderStrip(plate); + var placedBox = parts.Cast().GetBoundingBox(); + workArea = ComputeRemainderWithin(workArea, placedBox, plate.PartSpacing); } } @@ -289,22 +290,16 @@ namespace OpenNest.Mcp.Tools return sb.ToString(); } - private static Box ComputeRemainderStrip(Plate plate) + private static Box ComputeRemainderWithin(Box workArea, Box usedBox, double spacing) { - if (plate.Parts.Count == 0) - return plate.WorkArea(); - - var usedBox = plate.Parts.Cast().GetBoundingBox(); - var fullArea = plate.WorkArea(); - - var hWidth = fullArea.Right - usedBox.Right - plate.PartSpacing; + var hWidth = workArea.Right - usedBox.Right - spacing; var hStrip = hWidth > 0 - ? new Box(usedBox.Right + plate.PartSpacing, fullArea.Y, hWidth, fullArea.Length) + ? new Box(usedBox.Right + spacing, workArea.Y, hWidth, workArea.Length) : Box.Empty; - var vHeight = fullArea.Top - usedBox.Top - plate.PartSpacing; + var vHeight = workArea.Top - usedBox.Top - spacing; var vStrip = vHeight > 0 - ? new Box(fullArea.X, usedBox.Top + plate.PartSpacing, fullArea.Width, vHeight) + ? new Box(workArea.X, usedBox.Top + spacing, workArea.Width, vHeight) : Box.Empty; return hStrip.Area() >= vStrip.Area() ? hStrip : vStrip; diff --git a/OpenNest/Forms/MainForm.cs b/OpenNest/Forms/MainForm.cs index e970615..a90a5e7 100644 --- a/OpenNest/Forms/MainForm.cs +++ b/OpenNest/Forms/MainForm.cs @@ -807,14 +807,16 @@ namespace OpenNest.Forms if (parts.Count > 0) { plate.Parts.AddRange(parts); - Compactor.Compact(parts, plate); + // TODO: Compactor.Compact(parts, plate); activeForm.PlateView.Invalidate(); anyPlaced = true; item.Quantity = System.Math.Max(0, item.Quantity - parts.Count); - // Compute remainder strip for the next drawing. - workArea = ComputeRemainderStrip(plate); + // Compute remainder within the current work area based on + // what was just placed — not the full plate bounding box. + var placedBox = parts.Cast().GetBoundingBox(); + workArea = ComputeRemainderWithin(workArea, placedBox, plate.PartSpacing); } } @@ -867,22 +869,16 @@ namespace OpenNest.Forms } } - private static Box ComputeRemainderStrip(Plate plate) + private static Box ComputeRemainderWithin(Box workArea, Box usedBox, double spacing) { - if (plate.Parts.Count == 0) - return plate.WorkArea(); - - var usedBox = plate.Parts.Cast().GetBoundingBox(); - var fullArea = plate.WorkArea(); - - var hWidth = fullArea.Right - usedBox.Right - plate.PartSpacing; + var hWidth = workArea.Right - usedBox.Right - spacing; var hStrip = hWidth > 0 - ? new Box(usedBox.Right + plate.PartSpacing, fullArea.Y, hWidth, fullArea.Length) + ? new Box(usedBox.Right + spacing, workArea.Y, hWidth, workArea.Length) : Box.Empty; - var vHeight = fullArea.Top - usedBox.Top - plate.PartSpacing; + var vHeight = workArea.Top - usedBox.Top - spacing; var vStrip = vHeight > 0 - ? new Box(fullArea.X, usedBox.Top + plate.PartSpacing, fullArea.Width, vHeight) + ? new Box(workArea.X, usedBox.Top + spacing, workArea.Width, vHeight) : Box.Empty; return hStrip.Area() >= vStrip.Area() ? hStrip : vStrip;