using System;
using OpenNest.CNC.CuttingPlanning;
using OpenNest.Diagnostics;
using OpenNest.Geometry;
namespace OpenNest.CNC.CuttingStrategy
{
///
/// How one contour of a drawing must be cut: where it is entered and the lead-in,
/// lead-out and optional tab used there. is in the drawing's source
/// frame (the frame of ), which does not move when the
/// program is re-origined; 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.
///
public sealed class ContourCutPin
{
private readonly LeadIn leadIn;
private readonly LeadOut leadOut;
private readonly Tab tab;
/// A missing or invalid lead, a nonfinite point, or a tab with a lead-out.
/// A lead or tab that is not an exact built-in type.
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;
}
/// The contour entry in the drawing's source frame.
public Vector Point { get; }
/// A copy of the pinned lead-in.
public LeadIn LeadIn => OwnedCuttingParameters.CopyLeadIn(leadIn);
/// A copy of the pinned lead-out; always when .
public LeadOut LeadOut => OwnedCuttingParameters.CopyLeadOut(leadOut);
/// A copy of the pinned tab, or null for a closed contour.
public Tab Tab => tab == null ? null : OwnedCuttingParameters.CopyTab(tab);
public bool HasTab => tab != null;
}
}