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; } }