From 0e299d7f6f36e425fa6bb785743b8c688846dbb4 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Wed, 15 Apr 2026 06:16:29 -0400 Subject: [PATCH] feat(cincinnati): seed material library defaults and add selector dropdown Adds the full Cincinnati material/etch library list as the committed default config (seeded into Posts/ on build only when no runtime config exists), plus a Selected Library override in the PropertyGrid backed by a TypeConverter that populates from MaterialLibraries. MainForm calls the new IPostProcessorNestAware hook before showing the config so the dropdown opens preselected to the best match by nest material and nearest thickness. Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest.Core/IPostProcessorNestAware.cs | 7 + .../CincinnatiPostConfig.cs | 20 +++ .../CincinnatiPostProcessor.cs | 12 +- .../MaterialLibraryNameConverter.cs | 31 ++++ .../MaterialLibraryResolver.cs | 5 + .../OpenNest.Posts.Cincinnati.csproj | 8 + .../OpenNest.Posts.Cincinnati.json | 163 ++++++++++++++++++ 7 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 OpenNest.Core/IPostProcessorNestAware.cs create mode 100644 OpenNest.Posts.Cincinnati/MaterialLibraryNameConverter.cs create mode 100644 OpenNest.Posts.Cincinnati/OpenNest.Posts.Cincinnati.json diff --git a/OpenNest.Core/IPostProcessorNestAware.cs b/OpenNest.Core/IPostProcessorNestAware.cs new file mode 100644 index 0000000..1670311 --- /dev/null +++ b/OpenNest.Core/IPostProcessorNestAware.cs @@ -0,0 +1,7 @@ +namespace OpenNest +{ + public interface IPostProcessorNestAware + { + void PrepareForNest(Nest nest); + } +} diff --git a/OpenNest.Posts.Cincinnati/CincinnatiPostConfig.cs b/OpenNest.Posts.Cincinnati/CincinnatiPostConfig.cs index d8ecf21..fa1783b 100644 --- a/OpenNest.Posts.Cincinnati/CincinnatiPostConfig.cs +++ b/OpenNest.Posts.Cincinnati/CincinnatiPostConfig.cs @@ -1,5 +1,7 @@ +using System; using System.Collections.Generic; using System.ComponentModel; +using System.Linq; namespace OpenNest.Posts.Cincinnati { @@ -277,6 +279,24 @@ namespace OpenNest.Posts.Cincinnati [DisplayName("Etch Libraries")] [Description("Gas-to-library mapping for etch operations.")] public List EtchLibraries { get; set; } = new(); + + [Category("B. Libraries")] + [DisplayName("Selected Library")] + [Description("Overrides Material/Thickness/Gas auto-resolution. Pick an existing entry from Material Libraries, or leave blank to auto-resolve.")] + [TypeConverter(typeof(MaterialLibraryNameConverter))] + public string SelectedLibrary { get; set; } = ""; + + public string FindBestLibrary(string materialName, double thickness) + { + if (MaterialLibraries == null || string.IsNullOrEmpty(materialName)) + return ""; + + return MaterialLibraries + .Where(e => string.Equals(e.Material, materialName, StringComparison.OrdinalIgnoreCase)) + .OrderBy(e => System.Math.Abs(e.Thickness - thickness)) + .Select(e => e.Library) + .FirstOrDefault() ?? ""; + } } public class MaterialLibraryEntry diff --git a/OpenNest.Posts.Cincinnati/CincinnatiPostProcessor.cs b/OpenNest.Posts.Cincinnati/CincinnatiPostProcessor.cs index 0567c28..c899ae6 100644 --- a/OpenNest.Posts.Cincinnati/CincinnatiPostProcessor.cs +++ b/OpenNest.Posts.Cincinnati/CincinnatiPostProcessor.cs @@ -9,7 +9,7 @@ using OpenNest.CNC; namespace OpenNest.Posts.Cincinnati { - public sealed class CincinnatiPostProcessor : IConfigurablePostProcessor, IMaterialProvidingPostProcessor + public sealed class CincinnatiPostProcessor : IConfigurablePostProcessor, IPostProcessorNestAware, IMaterialProvidingPostProcessor { private static readonly JsonSerializerOptions JsonOptions = new() { @@ -35,6 +35,13 @@ namespace OpenNest.Posts.Cincinnati .Where(s => !string.IsNullOrWhiteSpace(s)); } + public void PrepareForNest(Nest nest) + { + var materialName = nest?.Material?.Name ?? ""; + var thickness = nest?.Thickness ?? 0.0; + Config.SelectedLibrary = Config.FindBestLibrary(materialName, thickness); + } + public CincinnatiPostProcessor() { var configPath = GetConfigPath(); @@ -138,7 +145,8 @@ namespace OpenNest.Posts.Cincinnati // Part sub-programs (if enabled) if (subprogramEntries != null) { - var partSubWriter = new CincinnatiPartSubprogramWriter(Config); + var partSubWriter = new CincinnatiPartSubprogramWriter(Config, + holeMapping.Count > 0 ? holeMapping : null); var sheetDiagonal = firstPlate != null ? System.Math.Sqrt(firstPlate.Size.Width * firstPlate.Size.Width + firstPlate.Size.Length * firstPlate.Size.Length) diff --git a/OpenNest.Posts.Cincinnati/MaterialLibraryNameConverter.cs b/OpenNest.Posts.Cincinnati/MaterialLibraryNameConverter.cs new file mode 100644 index 0000000..1013b13 --- /dev/null +++ b/OpenNest.Posts.Cincinnati/MaterialLibraryNameConverter.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +namespace OpenNest.Posts.Cincinnati +{ + public sealed class MaterialLibraryNameConverter : StringConverter + { + public override bool GetStandardValuesSupported(ITypeDescriptorContext context) => true; + + public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) => false; + + public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) + { + var config = context?.Instance as CincinnatiPostConfig; + var names = new List { "" }; + + if (config?.MaterialLibraries != null) + { + names.AddRange(config.MaterialLibraries + .Select(e => e.Library) + .Where(s => !string.IsNullOrWhiteSpace(s)) + .Distinct(StringComparer.OrdinalIgnoreCase) + .OrderBy(s => s, StringComparer.OrdinalIgnoreCase)); + } + + return new StandardValuesCollection(names); + } + } +} diff --git a/OpenNest.Posts.Cincinnati/MaterialLibraryResolver.cs b/OpenNest.Posts.Cincinnati/MaterialLibraryResolver.cs index a42c2c4..82ee863 100644 --- a/OpenNest.Posts.Cincinnati/MaterialLibraryResolver.cs +++ b/OpenNest.Posts.Cincinnati/MaterialLibraryResolver.cs @@ -10,15 +10,20 @@ public sealed class MaterialLibraryResolver private readonly List _materialLibraries; private readonly List _etchLibraries; + private readonly string _selectedLibrary; public MaterialLibraryResolver(CincinnatiPostConfig config) { _materialLibraries = config.MaterialLibraries ?? new List(); _etchLibraries = config.EtchLibraries ?? new List(); + _selectedLibrary = config.SelectedLibrary ?? ""; } public string ResolveCutLibrary(string materialName, double thickness, string gas) { + if (!string.IsNullOrEmpty(_selectedLibrary)) + return EnsureLibExtension(_selectedLibrary); + var entry = _materialLibraries.FirstOrDefault(e => string.Equals(e.Material, materialName, StringComparison.OrdinalIgnoreCase) && System.Math.Abs(e.Thickness - thickness) <= ThicknessTolerance && diff --git a/OpenNest.Posts.Cincinnati/OpenNest.Posts.Cincinnati.csproj b/OpenNest.Posts.Cincinnati/OpenNest.Posts.Cincinnati.csproj index 1b60598..0109553 100644 --- a/OpenNest.Posts.Cincinnati/OpenNest.Posts.Cincinnati.csproj +++ b/OpenNest.Posts.Cincinnati/OpenNest.Posts.Cincinnati.csproj @@ -6,11 +6,19 @@ + + + PreserveNewest + + ..\OpenNest\bin\$(Configuration)\$(TargetFramework)\Posts\ + $(MSBuildProjectDirectory)\OpenNest.Posts.Cincinnati.json + $(PostsDir)OpenNest.Posts.Cincinnati.json + diff --git a/OpenNest.Posts.Cincinnati/OpenNest.Posts.Cincinnati.json b/OpenNest.Posts.Cincinnati/OpenNest.Posts.Cincinnati.json new file mode 100644 index 0000000..692d998 --- /dev/null +++ b/OpenNest.Posts.Cincinnati/OpenNest.Posts.Cincinnati.json @@ -0,0 +1,163 @@ +{ + "ConfigurationName": "CL940", + "PostedUnits": "Inches", + "PostedAccuracy": 4, + "UseLineNumbers": true, + "FeatureLineNumberStart": 1, + "UseSheetSubprograms": true, + "SheetSubprogramStart": 101, + "UsePartSubprograms": false, + "PartSubprogramStart": 200, + "VariableDeclarationSubprogram": 100, + "CoordModeBetweenParts": "G92", + "ProcessParameterMode": "LibraryFile", + "DefaultAssistGas": "O2", + "DefaultEtchGas": "N2", + "UseExactStopMode": false, + "UseSpeedGas": false, + "UseAntiDive": true, + "UseSmartRapids": false, + "KerfCompensation": "ControllerSide", + "DefaultKerfSide": "Left", + "InteriorM47": "Always", + "ExteriorM47": "Always", + "M47OverrideDistanceThreshold": null, + "SafetyHeadraiseDistance": 2000, + "PalletExchange": "EndOfSheet", + "LeadInFeedratePercent": 0.5, + "LeadInArcLine2FeedratePercent": 0.5, + "LeadOutFeedratePercent": 0.5, + "CircleFeedrateMultiplier": 0.8, + "ArcFeedrate": "None", + "ArcFeedrateRanges": [ + { "MaxRadius": 0.125, "FeedratePercent": 0.25, "VariableNumber": 123 }, + { "MaxRadius": 0.75, "FeedratePercent": 0.5, "VariableNumber": 124 }, + { "MaxRadius": 4.5, "FeedratePercent": 0.8, "VariableNumber": 125 } + ], + "UserVariableStart": 200, + "SheetWidthVariable": 110, + "SheetLengthVariable": 111, + "MaterialLibraries": [ + { "Material": "Aluminum", "Thickness": 0.032, "Gas": "AIR", "Library": "AL032AIR" }, + { "Material": "Aluminum", "Thickness": 0.032, "Gas": "N2", "Library": "AL032N2" }, + { "Material": "Aluminum", "Thickness": 0.032, "Gas": "O2", "Library": "AL032O2" }, + { "Material": "Aluminum", "Thickness": 0.050, "Gas": "AIR", "Library": "AL050AIR" }, + { "Material": "Aluminum", "Thickness": 0.050, "Gas": "N2", "Library": "AL050N2" }, + { "Material": "Aluminum", "Thickness": 0.050, "Gas": "O2", "Library": "AL050O2" }, + { "Material": "Aluminum", "Thickness": 0.063, "Gas": "AIR", "Library": "AL063AIR" }, + { "Material": "Aluminum", "Thickness": 0.063, "Gas": "N2", "Library": "AL063N2" }, + { "Material": "Aluminum", "Thickness": 0.063, "Gas": "O2", "Library": "AL063O2" }, + { "Material": "Aluminum", "Thickness": 0.080, "Gas": "AIR", "Library": "AL080AIR" }, + { "Material": "Aluminum", "Thickness": 0.080, "Gas": "N2", "Library": "AL080N2" }, + { "Material": "Aluminum", "Thickness": 0.080, "Gas": "O2", "Library": "AL080O2" }, + { "Material": "Aluminum", "Thickness": 0.090, "Gas": "AIR", "Library": "AL090AIR" }, + { "Material": "Aluminum", "Thickness": 0.090, "Gas": "N2", "Library": "AL090N2" }, + { "Material": "Aluminum", "Thickness": 0.090, "Gas": "O2", "Library": "AL090O2" }, + { "Material": "Aluminum", "Thickness": 0.100, "Gas": "AIR", "Library": "AL100AIR" }, + { "Material": "Aluminum", "Thickness": 0.100, "Gas": "N2", "Library": "AL100N2" }, + { "Material": "Aluminum", "Thickness": 0.100, "Gas": "O2", "Library": "AL100O2" }, + { "Material": "Aluminum", "Thickness": 0.125, "Gas": "AIR", "Library": "AL125AIR" }, + { "Material": "Aluminum", "Thickness": 0.125, "Gas": "N2", "Library": "AL125N2" }, + { "Material": "Aluminum", "Thickness": 0.125, "Gas": "O2", "Library": "AL125O2" }, + { "Material": "Aluminum", "Thickness": 0.190, "Gas": "AIR", "Library": "AL190AIR" }, + { "Material": "Aluminum", "Thickness": 0.190, "Gas": "N2", "Library": "AL190N2" }, + { "Material": "Aluminum", "Thickness": 0.190, "Gas": "O2", "Library": "AL190O2" }, + { "Material": "Aluminum", "Thickness": 0.250, "Gas": "AIR", "Library": "AL250AIR" }, + { "Material": "Aluminum", "Thickness": 0.250, "Gas": "N2", "Library": "AL250N2" }, + { "Material": "Aluminum", "Thickness": 0.250, "Gas": "O2", "Library": "AL250O2" }, + { "Material": "Aluminum", "Thickness": 0.375, "Gas": "AIR", "Library": "AL375AIR" }, + { "Material": "Aluminum", "Thickness": 0.375, "Gas": "N2", "Library": "AL375N2" }, + { "Material": "Aluminum", "Thickness": 0.375, "Gas": "O2", "Library": "AL375O2" }, + { "Material": "Aluminum", "Thickness": 0.500, "Gas": "AIR", "Library": "AL500AIR" }, + { "Material": "Aluminum", "Thickness": 0.500, "Gas": "N2", "Library": "AL500N2" }, + { "Material": "Aluminum", "Thickness": 0.500, "Gas": "O2", "Library": "AL500O2" }, + { "Material": "Aluminum", "Thickness": 0.625, "Gas": "N2", "Library": "AL625N2" }, + { "Material": "Aluminum", "Thickness": 0.750, "Gas": "AIR", "Library": "AL750AIR" }, + { "Material": "Aluminum", "Thickness": 0.750, "Gas": "N2", "Library": "AL750N2" }, + { "Material": "Aluminum", "Thickness": 0.750, "Gas": "O2", "Library": "AL750O2" }, + { "Material": "Aluminum", "Thickness": 1.000, "Gas": "AIR", "Library": "AL1000AIR" }, + { "Material": "Aluminum", "Thickness": 1.000, "Gas": "N2", "Library": "AL1000N2" }, + + { "Material": "Galvanized Steel", "Thickness": 0.135, "Gas": "N2", "Library": "GALV135N2" }, + { "Material": "Galvanized Steel", "Thickness": 0.188, "Gas": "N2", "Library": "GALV188N2" }, + + { "Material": "Carbon Steel", "Thickness": 0.036, "Gas": "AIR", "Library": "MS036AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.036, "Gas": "N2", "Library": "MS036N2" }, + { "Material": "Carbon Steel", "Thickness": 0.048, "Gas": "AIR", "Library": "MS048AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.048, "Gas": "N2", "Library": "MS048N2" }, + { "Material": "Carbon Steel", "Thickness": 0.060, "Gas": "AIR", "Library": "MS060AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.060, "Gas": "N2", "Library": "MS060N2" }, + { "Material": "Carbon Steel", "Thickness": 0.075, "Gas": "AIR", "Library": "MS075AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.075, "Gas": "N2", "Library": "MS075N2" }, + { "Material": "Carbon Steel", "Thickness": 0.075, "Gas": "N2", "Library": "MS075N2FE" }, + { "Material": "Carbon Steel", "Thickness": 0.090, "Gas": "N2", "Library": "MS090N2" }, + { "Material": "Carbon Steel", "Thickness": 0.105, "Gas": "AIR", "Library": "MS105AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.105, "Gas": "N2", "Library": "MS105N2" }, + { "Material": "Carbon Steel", "Thickness": 0.120, "Gas": "AIR", "Library": "MS120AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.120, "Gas": "N2", "Library": "MS120N2" }, + { "Material": "Carbon Steel", "Thickness": 0.120, "Gas": "N2", "Library": "MS120N2FE" }, + { "Material": "Carbon Steel", "Thickness": 0.135, "Gas": "AIR", "Library": "MS135AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.135, "Gas": "N2", "Library": "MS135N2" }, + { "Material": "Carbon Steel", "Thickness": 0.135, "Gas": "N2", "Library": "MS135N2FE" }, + { "Material": "Carbon Steel", "Thickness": 0.135, "Gas": "N2", "Library": "MS135N2Panel" }, + { "Material": "Carbon Steel", "Thickness": 0.188, "Gas": "AIR", "Library": "MS188AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.188, "Gas": "N2", "Library": "MS188N2" }, + { "Material": "Carbon Steel", "Thickness": 0.188, "Gas": "N2", "Library": "MS188N2FLOORPLATE" }, + { "Material": "Carbon Steel", "Thickness": 0.188, "Gas": "O2", "Library": "MS188O2" }, + { "Material": "Carbon Steel", "Thickness": 0.250, "Gas": "AIR", "Library": "MS250AIR" }, + { "Material": "Carbon Steel", "Thickness": 0.250, "Gas": "N2", "Library": "MS250N2" }, + { "Material": "Carbon Steel", "Thickness": 0.250, "Gas": "N2", "Library": "MS250N2FLOORPLATE" }, + { "Material": "Carbon Steel", "Thickness": 0.250, "Gas": "O2", "Library": "MS250O2" }, + { "Material": "Carbon Steel", "Thickness": 0.313, "Gas": "O2", "Library": "MS313O2" }, + { "Material": "Carbon Steel", "Thickness": 0.375, "Gas": "O2", "Library": "MS375O2" }, + { "Material": "Carbon Steel", "Thickness": 0.500, "Gas": "N2", "Library": "MS500N2" }, + { "Material": "Carbon Steel", "Thickness": 0.500, "Gas": "O2", "Library": "MS500O2" }, + { "Material": "Carbon Steel", "Thickness": 0.625, "Gas": "O2", "Library": "MS625O2" }, + { "Material": "Carbon Steel", "Thickness": 0.750, "Gas": "O2", "Library": "MS750O2" }, + { "Material": "Carbon Steel", "Thickness": 1.000, "Gas": "O2", "Library": "MS1000O2" }, + + { "Material": "Stainless Steel", "Thickness": 0.036, "Gas": "AIR", "Library": "SS036AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.036, "Gas": "N2", "Library": "SS036N2" }, + { "Material": "Stainless Steel", "Thickness": 0.048, "Gas": "AIR", "Library": "SS048AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.048, "Gas": "N2", "Library": "SS048N2" }, + { "Material": "Stainless Steel", "Thickness": 0.060, "Gas": "AIR", "Library": "SS060AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.060, "Gas": "N2", "Library": "SS060N2" }, + { "Material": "Stainless Steel", "Thickness": 0.075, "Gas": "AIR", "Library": "SS075AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.075, "Gas": "N2", "Library": "SS075N2" }, + { "Material": "Stainless Steel", "Thickness": 0.075, "Gas": "N2", "Library": "SS075N2FE" }, + { "Material": "Stainless Steel", "Thickness": 0.105, "Gas": "AIR", "Library": "SS105AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.105, "Gas": "N2", "Library": "SS105N2" }, + { "Material": "Stainless Steel", "Thickness": 0.105, "Gas": "N2", "Library": "SS105N2FE" }, + { "Material": "Stainless Steel", "Thickness": 0.120, "Gas": "AIR", "Library": "SS120AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.120, "Gas": "N2", "Library": "SS120N2" }, + { "Material": "Stainless Steel", "Thickness": 0.120, "Gas": "N2", "Library": "SS120N2FE" }, + { "Material": "Stainless Steel", "Thickness": 0.135, "Gas": "AIR", "Library": "SS135AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.135, "Gas": "N2", "Library": "SS135N2" }, + { "Material": "Stainless Steel", "Thickness": 0.135, "Gas": "N2", "Library": "SS135N2FE" }, + { "Material": "Stainless Steel", "Thickness": 0.188, "Gas": "AIR", "Library": "SS188AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.188, "Gas": "N2", "Library": "SS188N2" }, + { "Material": "Stainless Steel", "Thickness": 0.250, "Gas": "AIR", "Library": "SS250AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.250, "Gas": "N2", "Library": "SS250N2" }, + { "Material": "Stainless Steel", "Thickness": 0.313, "Gas": "N2", "Library": "SS313N2" }, + { "Material": "Stainless Steel", "Thickness": 0.375, "Gas": "AIR", "Library": "SS375AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.375, "Gas": "N2", "Library": "SS375N2" }, + { "Material": "Stainless Steel", "Thickness": 0.500, "Gas": "AIR", "Library": "SS500AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.500, "Gas": "N2", "Library": "SS500N2" }, + { "Material": "Stainless Steel", "Thickness": 0.625, "Gas": "N2", "Library": "SS625N2" }, + { "Material": "Stainless Steel", "Thickness": 0.750, "Gas": "AIR", "Library": "SS750AIR" }, + { "Material": "Stainless Steel", "Thickness": 0.750, "Gas": "N2", "Library": "SS750N2" }, + { "Material": "Stainless Steel", "Thickness": 1.000, "Gas": "AIR", "Library": "SS1000AIR" }, + { "Material": "Stainless Steel", "Thickness": 1.000, "Gas": "N2", "Library": "SS1000N2" }, + + { "Material": "Phenolic", "Thickness": 0.0, "Gas": "", "Library": "Phenolic" }, + { "Material": "Gasket", "Thickness": 0.250, "Gas": "N2", "Library": "GASKET250N2" } + ], + "EtchLibraries": [ + { "Gas": "AIR", "Library": "EtchAIR" }, + { "Gas": "N2", "Library": "EtchN2" }, + { "Gas": "N2", "Library": "EtchN2_fast" }, + { "Gas": "N2", "Library": "Etchn2_no_mark_pvc" }, + { "Gas": "O2", "Library": "EtchO2" }, + { "Gas": "O2", "Library": "ETCHO2FINE" } + ] +}