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