fix(core): use chain tolerance for entity gap check to prevent spurious rapids
Ellipse-to-arc conversion creates tiny floating-point gaps (~0.00002") between consecutive arc segments. ShapeBuilder chains these with ChainTolerance (0.0001"), but ConvertGeometry checked gaps with Epsilon (0.00001"). Gaps between these thresholds generated spurious rapid moves that broke GraphicsPath figures, causing diagonal fill artifacts from GDI+'s implicit figure closing. Root cause fix: align ConvertGeometry's gap check with ShapeBuilder's ChainTolerance so precision gaps are absorbed instead of generating rapids. Defense-in-depth: GraphicsHelper no longer breaks figures at near-zero rapids, protecting against any programs with residual tiny rapids. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -82,7 +82,7 @@ namespace OpenNest.Converters
|
||||
var startpt = arc.StartPoint();
|
||||
var endpt = arc.EndPoint();
|
||||
|
||||
if (startpt != lastpt)
|
||||
if (startpt.DistanceTo(lastpt) > Tolerance.ChainTolerance)
|
||||
pgm.MoveTo(startpt);
|
||||
|
||||
lastpt = endpt;
|
||||
@@ -104,7 +104,7 @@ namespace OpenNest.Converters
|
||||
{
|
||||
var startpt = new Vector(circle.Center.X + circle.Radius, circle.Center.Y);
|
||||
|
||||
if (startpt != lastpt)
|
||||
if (startpt.DistanceTo(lastpt) > Tolerance.ChainTolerance)
|
||||
pgm.MoveTo(startpt);
|
||||
|
||||
pgm.ArcTo(startpt, circle.Center, circle.Rotation);
|
||||
@@ -115,7 +115,7 @@ namespace OpenNest.Converters
|
||||
|
||||
private static Vector AddLine(Program pgm, Vector lastpt, Line line)
|
||||
{
|
||||
if (line.StartPoint != lastpt)
|
||||
if (line.StartPoint.DistanceTo(lastpt) > Tolerance.ChainTolerance)
|
||||
pgm.MoveTo(line.StartPoint);
|
||||
|
||||
var move = new LinearMove(line.EndPoint);
|
||||
|
||||
@@ -138,9 +138,20 @@ namespace OpenNest
|
||||
break;
|
||||
|
||||
case CodeType.RapidMove:
|
||||
cutPath.StartFigure();
|
||||
leadPath.StartFigure();
|
||||
AddLine(cutPath, (RapidMove)code, mode, ref curpos);
|
||||
{
|
||||
var rapid = (RapidMove)code;
|
||||
var endpt = rapid.EndPoint;
|
||||
if (mode == Mode.Incremental)
|
||||
endpt += curpos;
|
||||
var dx = endpt.X - curpos.X;
|
||||
var dy = endpt.Y - curpos.Y;
|
||||
if (dx * dx + dy * dy > 0.001 * 0.001)
|
||||
{
|
||||
cutPath.StartFigure();
|
||||
leadPath.StartFigure();
|
||||
}
|
||||
curpos = endpt;
|
||||
}
|
||||
break;
|
||||
|
||||
case CodeType.SubProgramCall:
|
||||
@@ -300,8 +311,17 @@ namespace OpenNest
|
||||
break;
|
||||
|
||||
case CodeType.RapidMove:
|
||||
Flush();
|
||||
AddLine(path, (RapidMove)code, mode, ref curpos);
|
||||
{
|
||||
var rapid = (RapidMove)code;
|
||||
var endpt = rapid.EndPoint;
|
||||
if (mode == Mode.Incremental)
|
||||
endpt += curpos;
|
||||
var dx = endpt.X - curpos.X;
|
||||
var dy = endpt.Y - curpos.Y;
|
||||
if (dx * dx + dy * dy > 0.001 * 0.001)
|
||||
Flush();
|
||||
curpos = endpt;
|
||||
}
|
||||
break;
|
||||
|
||||
case CodeType.SubProgramCall:
|
||||
|
||||
Reference in New Issue
Block a user