From a3ae61d993c82699b2c667822f3d385893ffa58a Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sun, 12 Apr 2026 22:37:56 -0400 Subject: [PATCH] fix(cutting): emit open contours raw instead of applying lead-in/lead-out Open (non-closed) shapes like scribe lines or partial cuts don't have a meaningful pierce point or closing segment, so applying lead-in/out would produce invalid toolpaths. Skip the lead-in/out logic and emit them as raw contours in both Apply and ApplySingle paths. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../CuttingStrategy/ContourCuttingStrategy.cs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/OpenNest.Core/CNC/CuttingStrategy/ContourCuttingStrategy.cs b/OpenNest.Core/CNC/CuttingStrategy/ContourCuttingStrategy.cs index 6cc402b..d8d360f 100644 --- a/OpenNest.Core/CNC/CuttingStrategy/ContourCuttingStrategy.cs +++ b/OpenNest.Core/CNC/CuttingStrategy/ContourCuttingStrategy.cs @@ -69,9 +69,17 @@ namespace OpenNest.CNC.CuttingStrategy EmitScribeContours(result, scribeEntities); foreach (var entry in cutoutEntries) - EmitContour(result, entry.Shape, entry.Point, entry.Entity); + { + if (!entry.Shape.IsClosed()) + EmitRawContour(result, entry.Shape); + else + EmitContour(result, entry.Shape, entry.Point, entry.Entity); + } - EmitContour(result, profile.Perimeter, perimeterPt, perimeterEntity, ContourType.External); + if (!profile.Perimeter.IsClosed()) + EmitRawContour(result, profile.Perimeter); + else + EmitContour(result, profile.Perimeter, perimeterPt, perimeterEntity, ContourType.External); result.Mode = Mode.Incremental; @@ -99,10 +107,14 @@ namespace OpenNest.CNC.CuttingStrategy // Find the target shape that contains the clicked entity var (targetShape, matchedEntity) = FindTargetShape(profile, point, entity); - // Emit cutouts — only the target gets lead-in/out + // Emit cutouts — only the target gets lead-in/out (skip open contours) foreach (var cutout in profile.Cutouts) { - if (cutout == targetShape) + if (!cutout.IsClosed()) + { + EmitRawContour(result, cutout); + } + else if (cutout == targetShape) { var ct = DetectContourType(cutout); EmitContour(result, cutout, point, matchedEntity, ct); @@ -114,7 +126,11 @@ namespace OpenNest.CNC.CuttingStrategy } // Emit perimeter - if (profile.Perimeter == targetShape) + if (!profile.Perimeter.IsClosed()) + { + EmitRawContour(result, profile.Perimeter); + } + else if (profile.Perimeter == targetShape) { EmitContour(result, profile.Perimeter, point, matchedEntity, ContourType.External); }