From aeeb2e40747d598602410c18b4390c0aa8426ca3 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Mon, 23 Mar 2026 12:14:58 -0400 Subject: [PATCH] fix: treat cut-offs as area selection boundaries with proper spacing Cut-off parts use absolute coordinates in their programs, causing Program.BoundingBox() to span from the origin to the cut-off position. This made cut-offs invisible to GetLargestBoxVertically/Horizontally since the oversized box straddled the cursor instead of acting as a boundary. Derive thin obstacle boxes directly from CutOff definitions and apply PartSpacing offset so fills respect spacing from cut lines. Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest/Actions/ActionClone.cs | 18 ++++++++++++++++++ OpenNest/Actions/ActionSelectArea.cs | 24 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/OpenNest/Actions/ActionClone.cs b/OpenNest/Actions/ActionClone.cs index 89b4ee8..663175a 100644 --- a/OpenNest/Actions/ActionClone.cs +++ b/OpenNest/Actions/ActionClone.cs @@ -187,7 +187,25 @@ namespace OpenNest.Actions var boxes = new List(); foreach (var part in plate.Parts) + { + if (part.BaseDrawing.IsCutOff) + continue; + boxes.Add(part.BoundingBox.Offset(plate.PartSpacing)); + } + + var plateBounds = plate.BoundingBox(includeParts: false); + foreach (var cutoff in plate.CutOffs) + { + Box cutoffBox; + + if (cutoff.Axis == CutOffAxis.Vertical) + cutoffBox = new Box(cutoff.Position.X, plateBounds.Y, 0, plateBounds.Length); + else + cutoffBox = new Box(plateBounds.X, cutoff.Position.Y, plateBounds.Width, 0); + + boxes.Add(cutoffBox.Offset(plate.PartSpacing)); + } var pt = plateView.CurrentPoint; var vertical = SpatialQuery.GetLargestBoxVertically(pt, bounds, boxes); diff --git a/OpenNest/Actions/ActionSelectArea.cs b/OpenNest/Actions/ActionSelectArea.cs index 542ed8c..c86710f 100644 --- a/OpenNest/Actions/ActionSelectArea.cs +++ b/OpenNest/Actions/ActionSelectArea.cs @@ -157,7 +157,31 @@ namespace OpenNest.Actions public void Update() { foreach (var part in plateView.Plate.Parts) + { + if (part.BaseDrawing.IsCutOff) + continue; + boxes.Add(part.BoundingBox.Offset(plateView.Plate.PartSpacing)); + } + + // Add thin obstacle boxes from cutoff definitions so that + // the area selection correctly treats cutoffs as boundaries. + // Cutoff Parts have inflated bounding boxes (their programs use + // absolute coordinates, causing BoundingBox to span from origin) + // so we derive the position directly from the CutOff definition. + var plateBounds = plateView.Plate.BoundingBox(includeParts: false); + + foreach (var cutoff in plateView.Plate.CutOffs) + { + Box cutoffBox; + + if (cutoff.Axis == CutOffAxis.Vertical) + cutoffBox = new Box(cutoff.Position.X, plateBounds.Y, 0, plateBounds.Length); + else + cutoffBox = new Box(plateBounds.X, cutoff.Position.Y, plateBounds.Width, 0); + + boxes.Add(cutoffBox.Offset(plateView.Plate.PartSpacing)); + } Bounds = plateView.Plate.WorkArea(); }