mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-13 19:21:55 -04:00
AutomaticEntryCandidatesWithFallbacks completes the uncapped catalogue with tier-3 fallbacks after the preferred points: native arc midpoints, the eight compass points of a whole circle (a pure-circle contour is now usable instead of refusing), near-convex-corner points on each incident straight edge back from the corner by 2 x the applicable lead-in length using the emitter's own SelectLeadIn semantics (non-length lead-in styles contribute 0 and the fallback is omitted, never approximated), and the exact target-facing closest point toward the caller's look-ahead. Every fallback runs through the same reflex/cusp exclusion — a raw closest point or an inset landing on a forbidden inside corner is dropped — and the same geometric duplicate merge; short edges omit an out-of-segment inset by projection parameter instead of extrapolating. No ranking and no lead-safety verdict yet.
54 lines
2.1 KiB
C#
54 lines
2.1 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>
|
|
/// 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);
|
|
}
|