mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 09:21:05 -04:00
A library drawing can say how individual contours must be cut. A `ContourCutPin` holds the entry point in the drawing's source frame plus the lead-in, lead-out and optional tab used there; `Drawing.CutPins` lists them. Nothing plans with pins yet (Slice 5). - Pins accept only the exact built-in lead and tab types, copied through the same owned copiers the planner uses, so a pin cannot carry a type the emitter would not certify. Properties return copies: the pin is immutable. - A tab requires no lead-out, because the planner refuses a lead-out after an open contour. - The source frame is the frame of the source entities. It does not move when BuildDrawing re-origins the program at its first rapid, so pins survive converter edits that change Source.Offset. `CutPinResolver` maps pins to (contour ordinal, entity ordinal, local point) for a placement rotation, using the same `PreparedContours` ordinals Plan Cutting will use. It never guesses: a pin must lie within the contour closure tolerance of exactly one contour that no other pin claims, otherwise it is reported unresolved with a typed reason. A drawing program rotated in place (a canonical copy) is not the source frame and resolves nothing; canonical copies and split pieces carry no pins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
56 lines
2.6 KiB
C#
56 lines
2.6 KiB
C#
using System;
|
|
using OpenNest.CNC.CuttingPlanning;
|
|
using OpenNest.Diagnostics;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.CNC.CuttingStrategy
|
|
{
|
|
/// <summary>
|
|
/// How one contour of a drawing must be cut: where it is entered and the lead-in,
|
|
/// lead-out and optional tab used there. <see cref="Point"/> is in the drawing's source
|
|
/// frame (the frame of <see cref="Drawing.SourceEntities"/>), which does not move when the
|
|
/// program is re-origined; <see cref="CutPinResolver"/> maps it to a placed contour.
|
|
/// Immutable: only the exact built-in lead and tab types are accepted, they are copied
|
|
/// in, and every property returns a fresh copy.
|
|
/// </summary>
|
|
public sealed class ContourCutPin
|
|
{
|
|
private readonly LeadIn leadIn;
|
|
private readonly LeadOut leadOut;
|
|
private readonly Tab tab;
|
|
|
|
/// <exception cref="ArgumentException">A missing or invalid lead, a nonfinite point, or a tab with a lead-out.</exception>
|
|
/// <exception cref="NotSupportedException">A lead or tab that is not an exact built-in type.</exception>
|
|
public ContourCutPin(Vector point, LeadIn leadIn, LeadOut leadOut, Tab tab = null)
|
|
{
|
|
PostVerificationGeometry.Validate(point);
|
|
var ownedLeadIn = OwnedCuttingParameters.CopyLeadIn(leadIn);
|
|
var ownedLeadOut = OwnedCuttingParameters.CopyLeadOut(leadOut);
|
|
var ownedTab = tab == null ? null : OwnedCuttingParameters.CopyTab(tab);
|
|
// A tab leaves the contour open at its end; a lead-out after an open contour is
|
|
// refused by the planner, so the pin cannot ask for both.
|
|
if (ownedTab != null && ownedLeadOut.GetType() != typeof(NoLeadOut))
|
|
throw new ArgumentException("A pin with a tab cannot have a lead-out.", nameof(leadOut));
|
|
|
|
Point = point;
|
|
this.leadIn = ownedLeadIn;
|
|
this.leadOut = ownedLeadOut;
|
|
this.tab = ownedTab;
|
|
}
|
|
|
|
/// <summary>The contour entry in the drawing's source frame.</summary>
|
|
public Vector Point { get; }
|
|
|
|
/// <summary>A copy of the pinned lead-in.</summary>
|
|
public LeadIn LeadIn => OwnedCuttingParameters.CopyLeadIn(leadIn);
|
|
|
|
/// <summary>A copy of the pinned lead-out; always <see cref="NoLeadOut"/> when <see cref="HasTab"/>.</summary>
|
|
public LeadOut LeadOut => OwnedCuttingParameters.CopyLeadOut(leadOut);
|
|
|
|
/// <summary>A copy of the pinned tab, or null for a closed contour.</summary>
|
|
public Tab Tab => tab == null ? null : OwnedCuttingParameters.CopyTab(tab);
|
|
|
|
public bool HasTab => tab != null;
|
|
}
|
|
}
|