From abc707f1d938f5e8bccf086f7bbeabbfa240b343 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sat, 28 Mar 2026 15:36:35 -0400 Subject: [PATCH] fix: allow line-on-line contact and remove extra spacing gap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Part.Intersects: filter intersection points at a vertex of either shape (was both), so edge-touching parts are not flagged as overlapping - NestEngineBase.HasOverlaps: use epsilon-based bounding box pre-filter consistent with FillExtents and Plate.HasOverlappingParts - PartGeometry.GetOffsetPartLines: remove extra chordTolerance added to spacing offset — was causing 0.002" gap beyond the intended part spacing Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest.Core/Part.cs | 7 ++++--- OpenNest.Core/PartGeometry.cs | 6 +++--- OpenNest.Engine/NestEngineBase.cs | 9 +++++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/OpenNest.Core/Part.cs b/OpenNest.Core/Part.cs index 1bfdd7f..edf64da 100644 --- a/OpenNest.Core/Part.cs +++ b/OpenNest.Core/Part.cs @@ -177,15 +177,16 @@ namespace OpenNest if (!perimeter1.Intersects(perimeter2, out var rawPts)) return false; - // Exclude intersection points that coincide with vertices of BOTH - // perimeters — these are touch points (shared corners/endpoints), + // Exclude intersection points that coincide with a vertex of either + // perimeter — these are boundary contact points (shared corners, + // endpoints, or a corner touching an edge) with zero area overlap, // not actual crossings where one shape enters the other's interior. var verts1 = CollectVertices(perimeter1); var verts2 = CollectVertices(perimeter2); foreach (var pt in rawPts) { - if (IsNearAnyVertex(pt, verts1) && IsNearAnyVertex(pt, verts2)) + if (IsNearAnyVertex(pt, verts1) || IsNearAnyVertex(pt, verts2)) continue; pts.Add(pt); } diff --git a/OpenNest.Core/PartGeometry.cs b/OpenNest.Core/PartGeometry.cs index 43bdfb4..ce68f53 100644 --- a/OpenNest.Core/PartGeometry.cs +++ b/OpenNest.Core/PartGeometry.cs @@ -45,7 +45,7 @@ namespace OpenNest var profile = new ShapeProfile( entities.Where(e => e.Layer != SpecialLayers.Rapid).ToList()); var lines = new List(); - var totalSpacing = spacing + chordTolerance; + var totalSpacing = spacing; AddOffsetLines(lines, profile.Perimeter.OffsetOutward(totalSpacing), chordTolerance, part.Location); @@ -63,7 +63,7 @@ namespace OpenNest var profile = new ShapeProfile( entities.Where(e => e.Layer != SpecialLayers.Rapid).ToList()); var lines = new List(); - var totalSpacing = spacing + chordTolerance; + var totalSpacing = spacing; AddOffsetDirectionalLines(lines, profile.Perimeter.OffsetOutward(totalSpacing), chordTolerance, part.Location, facingDirection); @@ -97,7 +97,7 @@ namespace OpenNest var profile = new ShapeProfile( entities.Where(e => e.Layer != SpecialLayers.Rapid).ToList()); var lines = new List(); - var totalSpacing = spacing + chordTolerance; + var totalSpacing = spacing; AddOffsetDirectionalLines(lines, profile.Perimeter.OffsetOutward(totalSpacing), chordTolerance, part.Location, facingDirection); diff --git a/OpenNest.Engine/NestEngineBase.cs b/OpenNest.Engine/NestEngineBase.cs index b60fd0d..f9a5f9e 100644 --- a/OpenNest.Engine/NestEngineBase.cs +++ b/OpenNest.Engine/NestEngineBase.cs @@ -2,6 +2,7 @@ using OpenNest.Engine; using OpenNest.Engine.Fill; using OpenNest.Engine.Strategies; using OpenNest.Geometry; +using OpenNest.Math; using System; using System.Collections.Generic; using System.Diagnostics; @@ -275,8 +276,12 @@ namespace OpenNest { var box2 = parts[j].BoundingBox; - if (box1.Right < box2.Left || box2.Right < box1.Left || - box1.Top < box2.Bottom || box2.Top < box1.Bottom) + var overlapX = System.Math.Min(box1.Right, box2.Right) + - System.Math.Max(box1.Left, box2.Left); + var overlapY = System.Math.Min(box1.Top, box2.Top) + - System.Math.Max(box1.Bottom, box2.Bottom); + + if (overlapX <= Tolerance.Epsilon || overlapY <= Tolerance.Epsilon) continue; List pts;