using System; using OpenNest.CNC.CuttingPlanning; using OpenNest.CNC.CuttingStrategy; namespace OpenNest.Support { /// /// Which parts tabs (docs/support-tabs.md): the /// parts the plate's support bed cannot hold level or, by size (, /// or a plate with no bed), the parts whose width is in the settings' size range. Also the cutting settings for a lead-in /// placed by hand: the tool cuts where it is clicked, so the part is tabbed there. Plan /// Cutting chooses the tab point itself. /// public static class SupportTabSettings { /// /// The widest part a migrated "Tab every part" setting tabs by size: wider than any sheet, /// so the same parts stay tabbed. It is also the cutting panel's largest range value. /// public const double TabEveryPartMaxWidth = 9999; /// /// Whether support tabs judge parts by the plate's support bed: they are on, not by size, /// and the plate has a bed. Otherwise they go by the size range. /// public static bool UsesBed(CuttingParameters parameters, SupportBed bed) => parameters?.SupportTabs == true && !parameters.TabBySize && bed != null; /// /// Whether support tabs are on and can tab a part on a plate with : /// by the bed, or by a usable size range. /// public static bool CanTab(CuttingParameters parameters, SupportBed bed) => parameters?.SupportTabs == true && (UsesBed(parameters, bed) || parameters.HasTabSizeRange()); /// /// The analysis that tabs a part, or null when support tabs are off or the part is /// outside the rule: by the bed, the bed's analysis, held by its tab alone /// () when the bed cannot hold it level and its /// length is within ; by size (no bed, or /// ), a no-bed analysis /// () of a part whose width is in /// 's range. The part needs a tab when /// the result is complete and not supported; an incomplete result could not be read. /// /// /// How far a tab point keeps from an inside corner; 0 keeps it off the corner only. /// public static PartSupport Analyze(CuttingParameters parameters, SupportBed bed, int quadrant, SupportMaterial material, double insideCornerClearance = 0) { ArgumentNullException.ThrowIfNull(material); if (parameters?.SupportTabs != true) return null; if (UsesBed(parameters, bed)) { var support = SupportAnalyzer.Analyze(bed, quadrant, material, insideCornerClearance); return support is { IsComplete: true, IsSupported: false } && parameters.TabHoldsAt(SupportAnalyzer.Length(material)) ? SupportAnalyzer.HeldByTab(support, material) : support; } if (!parameters.HasTabSizeRange()) return null; if (!material.IsComplete) return SupportAnalyzer.AnalyzeWithoutBed(material, insideCornerClearance); return parameters.TabsBySizeAt(SupportAnalyzer.Width(material)) ? SupportAnalyzer.AnalyzeWithoutBed(material, insideCornerClearance) : null; } /// /// Whether support tabs are on but can tab nothing: they go by size (no bed, or /// ) and the settings set no size range. /// public static bool SkipsForNoRange(CuttingParameters parameters, SupportBed bed) => parameters?.SupportTabs == true && !CanTab(parameters, bed); /// /// itself, or a copy with tabs enabled when support tabs are /// on, a tab size is set and needs a tab (see ). /// The caller's settings are never changed. /// public static CuttingParameters ForManualLeadIn(CuttingParameters parameters, Plate plate, Part part) { ArgumentNullException.ThrowIfNull(parameters); if (parameters.TabsEnabled || parameters.TabConfig == null || plate == null || part == null || !CanTab(parameters, plate.SupportBed)) return parameters; var support = Analyze(parameters, plate.SupportBed, plate.Quadrant, SupportMaterial.FromPart(part)); if (support is not { IsComplete: true, IsSupported: false }) return parameters; var tabbed = OwnedCuttingParameters.Copy(parameters); tabbed.TabsEnabled = true; return tabbed; } /// /// Moves the user's cutting settings off the retired "Tab every part" choice /// ( on with support tabs off): they become tabs /// by size from 0 to , which tabs the same parts. Returns /// whether it changed . Only for the settings the user edits, /// never a plate's recorded parameters or a drawing pin's, which replay as planned. /// public static bool MigrateTabEveryPart(CuttingParameters parameters) { if (parameters is not { TabsEnabled: true, SupportTabs: false }) return false; parameters.TabsEnabled = false; parameters.SupportTabs = true; parameters.TabBySize = true; parameters.TabSizeMinWidth = 0; parameters.TabSizeMaxWidth = TabEveryPartMaxWidth; return true; } } }