feat: add configurable chord tolerance for offset drawing and push geometry

Replace hardcoded PushChordTolerance constant with a configurable
OffsetTolerance property on PlateView (default 0.001), giving smoother
arc profiles in offset drawing and push-to-part collision detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 17:48:05 -04:00
parent df283d15dc
commit d1353d58e5
2 changed files with 17 additions and 17 deletions

View File

@@ -739,9 +739,7 @@ namespace OpenNest
return pts.Count > 0; return pts.Count > 0;
} }
private const double PushChordTolerance = 0.01; public static List<Line> GetPartLines(Part part, double chordTolerance = 0.001)
public static List<Line> GetPartLines(Part part)
{ {
var entities = ConvertProgram.ToGeometry(part.Program); var entities = ConvertProgram.ToGeometry(part.Program);
var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid)); var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
@@ -749,7 +747,7 @@ namespace OpenNest
foreach (var shape in shapes) foreach (var shape in shapes)
{ {
var polygon = shape.ToPolygonWithTolerance(PushChordTolerance); var polygon = shape.ToPolygonWithTolerance(chordTolerance);
polygon.Offset(part.Location); polygon.Offset(part.Location);
lines.AddRange(polygon.ToLines()); lines.AddRange(polygon.ToLines());
} }
@@ -757,7 +755,7 @@ namespace OpenNest
return lines; return lines;
} }
public static List<Line> GetPartLines(Part part, PushDirection facingDirection) public static List<Line> GetPartLines(Part part, PushDirection facingDirection, double chordTolerance = 0.001)
{ {
var entities = ConvertProgram.ToGeometry(part.Program); var entities = ConvertProgram.ToGeometry(part.Program);
var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid)); var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
@@ -765,7 +763,7 @@ namespace OpenNest
foreach (var shape in shapes) foreach (var shape in shapes)
{ {
var polygon = shape.ToPolygonWithTolerance(PushChordTolerance); var polygon = shape.ToPolygonWithTolerance(chordTolerance);
polygon.Offset(part.Location); polygon.Offset(part.Location);
lines.AddRange(GetDirectionalLines(polygon, facingDirection)); lines.AddRange(GetDirectionalLines(polygon, facingDirection));
} }
@@ -773,7 +771,7 @@ namespace OpenNest
return lines; return lines;
} }
public static List<Line> GetOffsetPartLines(Part part, double spacing) public static List<Line> GetOffsetPartLines(Part part, double spacing, double chordTolerance = 0.001)
{ {
var entities = ConvertProgram.ToGeometry(part.Program); var entities = ConvertProgram.ToGeometry(part.Program);
var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid)); var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
@@ -783,12 +781,12 @@ namespace OpenNest
{ {
// Add chord tolerance to compensate for inscribed polygon chords // Add chord tolerance to compensate for inscribed polygon chords
// being inside the actual offset arcs. // being inside the actual offset arcs.
var offsetEntity = shape.OffsetEntity(spacing + PushChordTolerance, OffsetSide.Left) as Shape; var offsetEntity = shape.OffsetEntity(spacing + chordTolerance, OffsetSide.Left) as Shape;
if (offsetEntity == null) if (offsetEntity == null)
continue; continue;
var polygon = offsetEntity.ToPolygonWithTolerance(PushChordTolerance); var polygon = offsetEntity.ToPolygonWithTolerance(chordTolerance);
polygon.RemoveSelfIntersections(); polygon.RemoveSelfIntersections();
polygon.Offset(part.Location); polygon.Offset(part.Location);
lines.AddRange(polygon.ToLines()); lines.AddRange(polygon.ToLines());
@@ -797,7 +795,7 @@ namespace OpenNest
return lines; return lines;
} }
public static List<Line> GetOffsetPartLines(Part part, double spacing, PushDirection facingDirection) public static List<Line> GetOffsetPartLines(Part part, double spacing, PushDirection facingDirection, double chordTolerance = 0.001)
{ {
var entities = ConvertProgram.ToGeometry(part.Program); var entities = ConvertProgram.ToGeometry(part.Program);
var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid)); var shapes = GetShapes(entities.Where(e => e.Layer != SpecialLayers.Rapid));
@@ -805,12 +803,12 @@ namespace OpenNest
foreach (var shape in shapes) foreach (var shape in shapes)
{ {
var offsetEntity = shape.OffsetEntity(spacing + PushChordTolerance, OffsetSide.Left) as Shape; var offsetEntity = shape.OffsetEntity(spacing + chordTolerance, OffsetSide.Left) as Shape;
if (offsetEntity == null) if (offsetEntity == null)
continue; continue;
var polygon = offsetEntity.ToPolygonWithTolerance(PushChordTolerance); var polygon = offsetEntity.ToPolygonWithTolerance(chordTolerance);
polygon.RemoveSelfIntersections(); polygon.RemoveSelfIntersections();
polygon.Offset(part.Location); polygon.Offset(part.Location);
lines.AddRange(GetDirectionalLines(polygon, facingDirection)); lines.AddRange(GetDirectionalLines(polygon, facingDirection));

View File

@@ -99,6 +99,8 @@ namespace OpenNest.Controls
public bool DrawOffset { get; set; } public bool DrawOffset { get; set; }
public double OffsetTolerance { get; set; } = 0.001;
public bool FillParts { get; set; } public bool FillParts { get; set; }
public double RotateIncrementAngle { get; set; } public double RotateIncrementAngle { get; set; }
@@ -491,7 +493,7 @@ namespace OpenNest.Controls
if (offsetEntity == null) if (offsetEntity == null)
continue; continue;
var polygon = offsetEntity.ToPolygonWithTolerance(0.01); var polygon = offsetEntity.ToPolygonWithTolerance(OffsetTolerance);
polygon.RemoveSelfIntersections(); polygon.RemoveSelfIntersections();
polygon.Offset(part.Location); polygon.Offset(part.Location);
@@ -861,8 +863,8 @@ namespace OpenNest.Controls
foreach (var part in stationaryParts) foreach (var part in stationaryParts)
{ {
stationaryLines.Add(halfSpacing > 0 stationaryLines.Add(halfSpacing > 0
? Helper.GetOffsetPartLines(part.BasePart, halfSpacing, opposite) ? Helper.GetOffsetPartLines(part.BasePart, halfSpacing, opposite, OffsetTolerance)
: Helper.GetPartLines(part.BasePart, opposite)); : Helper.GetPartLines(part.BasePart, opposite, OffsetTolerance));
stationaryBoxes.Add(part.BoundingBox); stationaryBoxes.Add(part.BoundingBox);
} }
@@ -873,8 +875,8 @@ namespace OpenNest.Controls
{ {
// Get offset lines for the moving part (half-spacing, symmetric with stationary). // Get offset lines for the moving part (half-spacing, symmetric with stationary).
var movingLines = halfSpacing > 0 var movingLines = halfSpacing > 0
? Helper.GetOffsetPartLines(selected.BasePart, halfSpacing, direction) ? Helper.GetOffsetPartLines(selected.BasePart, halfSpacing, direction, OffsetTolerance)
: Helper.GetPartLines(selected.BasePart, direction); : Helper.GetPartLines(selected.BasePart, direction, OffsetTolerance);
var movingBox = selected.BoundingBox; var movingBox = selected.BoundingBox;