Files
OpenNest/OpenNest.Core/CNC/CuttingPlanning/ContourEntryCandidate.cs
T
ajandClaude Opus 5.5 4d55e11318 style: use one spelling across the codebase
The repo mixed variants such as center/centre and color/colour, so a
name could be spelled either way and searches missed half the hits.
Standardize on the US spelling, matching .NET's own APIs (Color, Center).

Wire values owned by other systems keep their spelling: the material
ledger's "Cancelled" hold status and GitHub's "cancelled" job status.

No behavior change beyond the spelling of a few status messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 16:11:30 -04:00

88 lines
3.5 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>
/// The perimeter point where a tab best keeps the part level on its support bed; only a
/// perimeter tabbed for support has it (see <see cref="PreparedContours.WithSupportTab"/>).
/// </summary>
SupportTab = 8,
/// <summary>
/// A cutout entry pierced where eroding the cutout leaves room (see
/// <see cref="PreparedContours.ErodedPierceEntries"/>): only offered once no configured
/// lead-in of the cutout fits.
/// </summary>
ErodedPierce = 9,
}
/// <summary>
/// Which automatic entries a perimeter tabbed for support offers (see
/// <see cref="PreparedContours.WithSupportTab"/>); every other contour offers its whole catalog.
/// </summary>
internal enum SupportEntries
{
/// <summary>Entries whose tab steadies the part, clear of inside corners, plus its best tab point.</summary>
Steadying,
/// <summary>Every entry clear of inside corners: the fallback when no steadying entry fits.</summary>
ClearOfInsideCorners,
/// <summary>Every entry: the last fallback, when nothing clear of inside corners fits.</summary>
Any,
}
/// <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. <paramref name="CornerReach"/>
/// is how far a corner fillet's joint lies from the sharp corner it rounds (0 otherwise), so
/// ranking can count it on both of that corner's sides.
/// </summary>
internal sealed record ContourEntryCandidate(ContourChoice Choice, AutomaticEntryKind Kind, double CornerReach = 0)
{
/// <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);
}