Files
OpenNest/OpenNest.Engine/Jobs/NestTolerances.cs
T
ajandClaude Opus 5.5 5dc13a03ae feat(diagnostics): warn when parts are closer than the part spacing
Validate Nest, the posting review and console --post now report a
"Part spacing" finding for pairs of parts that do not overlap but sit
closer than the plate's part spacing. Before, only Auto Nest's
Keep/Discard review checked spacing, so hand-edited layouts could be
validated and posted with parts too close together.

Candidates are found with Auto Nest's own outline test, moved into Core
as SpacingOutline (NestLayoutCheck and NestTolerances now use it; Engine
tests unchanged). Because that outline circumscribes arcs by more than
the spacing slack, each candidate is confirmed on native contours
flattened 20x finer than the slack, so arcs placed exactly at the
spacing by interactive fills stay clear. The finding reports the
measured gap and marks the middle of the closest approach. Overlapping
pairs, cut-offs, zero spacing, the plate edge and clamps are not
reported as spacing findings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 01:56:27 -04:00

42 lines
2.3 KiB
C#

using System;
using OpenNest.Geometry;
using OpenNest.Math;
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 = SpacingOutline.ChordTolerance;
/// <summary>How far under the part spacing a gap may fall and still pass both validators
/// and the pre-post spacing review; see <see cref="SpacingOutline.SpacingSlack"/>.</summary>
public const double SpacingSlack = SpacingOutline.SpacingSlack;
/// <summary>How far material may extend past the work area and still pass the layout check's
/// bounds test. Matches the general geometry tolerance, so a part drawn a few millionths
/// larger than its sheet's work area (as exported dimensions often are) is still accepted.</summary>
public const double WorkAreaSlack = Tolerance.Epsilon;
/// <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;
}
}