From 4cecaba83a58861e719bb933c4debe0a6c2b9777 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Thu, 23 Apr 2026 08:50:38 -0400 Subject: [PATCH] fix(core): emit line instead of arc for near-zero sweep to avoid full-circle misinterpretation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Near-zero-sweep arcs with large radius (e.g. from ellipse converter) have nearly-coincident start/end points. Downstream code (ConvertProgram, Program BoundingBox) treats coincident start/end as a full 360° circle, inflating the bounding box and rendering wrong geometry. Emit a LinearMove when sweep is negligible — geometrically equivalent and avoids the ambiguity. Also fix the ellipse converter to produce lines instead of degenerate arcs at the source. Co-Authored-By: Claude Opus 4.6 --- OpenNest.Core/Converters/ConvertGeometry.cs | 12 +++++++++++- OpenNest.Core/Geometry/EllipseConverter.cs | 6 +++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/OpenNest.Core/Converters/ConvertGeometry.cs b/OpenNest.Core/Converters/ConvertGeometry.cs index 6620025..728c2ae 100644 --- a/OpenNest.Core/Converters/ConvertGeometry.cs +++ b/OpenNest.Core/Converters/ConvertGeometry.cs @@ -1,5 +1,6 @@ using OpenNest.CNC; using OpenNest.Geometry; +using OpenNest.Math; using System.Collections.Generic; namespace OpenNest.Converters @@ -86,7 +87,16 @@ namespace OpenNest.Converters lastpt = endpt; - pgm.ArcTo(endpt, arc.Center, arc.IsReversed ? RotationType.CW : RotationType.CCW); + var sweep = System.Math.Abs(arc.SweepAngle()); + if (sweep < Tolerance.Epsilon || sweep.IsEqualTo(Angle.TwoPI)) + { + pgm.LineTo(endpt); + } + else + { + pgm.ArcTo(endpt, arc.Center, arc.IsReversed ? RotationType.CW : RotationType.CCW); + } + return lastpt; } diff --git a/OpenNest.Core/Geometry/EllipseConverter.cs b/OpenNest.Core/Geometry/EllipseConverter.cs index 9642520..005d0fd 100644 --- a/OpenNest.Core/Geometry/EllipseConverter.cs +++ b/OpenNest.Core/Geometry/EllipseConverter.cs @@ -173,7 +173,11 @@ namespace OpenNest.Geometry if (maxDev <= tolerance) { - results.Add(CreateArc(arcCenter, radius, center, semiMajor, semiMinor, rotation, t0, t1)); + var arc = CreateArc(arcCenter, radius, center, semiMajor, semiMinor, rotation, t0, t1); + if (arc.SweepAngle() < Tolerance.Epsilon) + results.Add(new Line(p0, p1)); + else + results.Add(arc); } else {