Files
OpenNest/OpenNest.Engine/Jobs/NestTolerances.cs
T
896ed2026a fix(engine): leave scribe marks out of layout bounds and salvage
The job runner already checked sheet bounds on material contours only,
but the benchmark validator and salvage scoring used Part.BoundingBox,
which includes scribe/etch moves. A PEP bend tick that ends a hair past
the part's edge passed the runner yet failed the benchmark when placed
flush to the sheet edge, and it could shrink the credited offcut. Marks
only mark the surface, so bounds and salvage now use material only.

Benchmark before/after (all five built-in engines, local fixtures,
salvage 0.5): no job changed validity or cost. Regression tests pin the
new rule: a protruding tick flush to the sheet edge is valid in all four
quadrants, and a tick past the parts envelope no longer shrinks salvage
(targeted fixture cost 130 -> 120).

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 08:56:49 -04:00

32 lines
1.6 KiB
C#

using System;
using OpenNest.Geometry;
namespace OpenNest.Engine.Jobs;
/// <summary>Shared numerical contract for layout validation.
/// Only material contours (SpecialLayers.IsMaterial) count for bounds, clearance and scoring.
/// Scribe/etch marks never affect these checks or salvage envelopes, even outside the sheet.</summary>
public static class NestTolerances
{
/// <summary>Arc chord tolerance used by both validators. The layout check circumscribes
/// perimeter arcs and inscribes cutouts; the placement validator uses inscribed arcs.</summary>
public const double ValidationOutline = 0.001;
/// <summary>Clipper decimal precision (a 1e-4 coordinate grid).</summary>
public const int ClipperPrecision = ClipperBridge.Precision;
/// <summary>Extra pair clearance for an engine whose outline error is bounded by t.
/// Each of two boundaries contributes ValidationOutline from validator flattening,
/// one Clipper grid unit from rounding, and t from engine flattening: therefore
/// 2 * ValidationOutline + 2 * 10^(-ClipperPrecision) + 2 * t.
/// This budget assumes valid material geometry and bounded chord error on both sides.</summary>
/// <exception cref="ArgumentOutOfRangeException">Tolerance is negative or non-finite.</exception>
public static double SafeClearanceMargin(double engineChordTolerance)
{
if (!double.IsFinite(engineChordTolerance) || engineChordTolerance < 0)
throw new ArgumentOutOfRangeException(nameof(engineChordTolerance));
return 2 * ValidationOutline + 2 * System.Math.Pow(10, -ClipperPrecision)
+ 2 * engineChordTolerance;
}
}