mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-11 15:41:14 -05:00
PreparedContours.Capture(program, parameters, pins) takes CutPinResolver results for the same contours and fixes every resolved pin's contour: its one and only entry is the pin's point, and it is emitted through the existing emitter with the pin's own lead-in, lead-out and tab (angle rounding off, so the entry never moves). Every catalogue returns the pinned entry alone and emission refuses any other entry for that contour, so no search path can relocate it. The certified tab size is the pinned outside's own, so a pinned tab gap is genuine and replay certifies it. Unpinned contours keep the shared settings and automatic selection; without pins the existing preparation is untouched (5.1 digests unchanged). Capture now resolves a regenerated part's drawing pins. A pin that does not resolve (not on a contour, on several, sharing one, or unplaceable) is never guessed: its contour stays automatic and the plate gets a FixedLead warning naming the pin, making the proposal UNVERIFIED. A tab pinned on an internal contour cannot be cut as pinned (only the outside is tabbed) and warns the same way. Pins-off, locked parts with pins and freshness follow in 5.4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
2.2 KiB
C#
57 lines
2.2 KiB
C#
using System;
|
|
using OpenNest.Diagnostics;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.CNC.CuttingPlanning;
|
|
|
|
/// <summary>Automatic start preference, ordered: a lower value is more preferred.</summary>
|
|
internal enum AutomaticEntryKind
|
|
{
|
|
/// <summary>A convex turn of the contour's own travel, classified exactly as emission classifies it.</summary>
|
|
ConvexCorner = 0,
|
|
|
|
/// <summary>The midpoint of a straight edge.</summary>
|
|
StraightMidpoint = 1,
|
|
|
|
/// <summary>A tangent line/arc joint. A collinear line/line split is not a joint and never appears.</summary>
|
|
TangentJoint = 2,
|
|
|
|
/// <summary>
|
|
/// Tier 3 (fallback): a point on a straight edge meeting a convex corner, back from the
|
|
/// corner by about twice the applicable lead-in length, strictly inside the edge.
|
|
/// </summary>
|
|
NearCorner = 3,
|
|
|
|
/// <summary>
|
|
/// Tier 3 (fallback): the exact native closest point facing the caller's look-ahead
|
|
/// position (pass the arrival there when there is no next cut). Never a reflex/cusp vertex.
|
|
/// </summary>
|
|
TargetFacing = 4,
|
|
|
|
/// <summary>Tier 3 (fallback): the native midpoint of an arc entity.</summary>
|
|
ArcMidpoint = 5,
|
|
|
|
/// <summary>Tier 3 (fallback): one of the eight compass points of a whole circle.</summary>
|
|
CircleCompass = 6,
|
|
|
|
/// <summary>A drawing pin's own entry: the one and only candidate of a pinned contour.</summary>
|
|
Pinned = 7,
|
|
}
|
|
|
|
/// <summary>
|
|
/// One automatic start candidate: the owned contour choice plus its preference kind and a
|
|
/// stable geometry tie key for deterministic ranking. The choice keeps this preparation as
|
|
/// owner; nothing here exposes or mutates the underlying shape.
|
|
/// </summary>
|
|
internal sealed record ContourEntryCandidate(ContourChoice Choice, AutomaticEntryKind Kind)
|
|
{
|
|
/// <summary>
|
|
/// Stable geometric tie key: the point quantized to the preparation epsilon grid, so
|
|
/// equal points rank together regardless of the entity that produced them.
|
|
/// </summary>
|
|
internal (long X, long Y) GeometryKey => (Quantize(Choice.Point.X), Quantize(Choice.Point.Y));
|
|
|
|
private static long Quantize(double value) =>
|
|
(long)System.Math.Round(value / PostVerificationGeometry.Epsilon);
|
|
}
|