diff --git a/OpenNest.Posts.Cincinnati/CincinnatiPreambleWriter.cs b/OpenNest.Posts.Cincinnati/CincinnatiPreambleWriter.cs new file mode 100644 index 0000000..8cbf0c0 --- /dev/null +++ b/OpenNest.Posts.Cincinnati/CincinnatiPreambleWriter.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; +using OpenNest; + +namespace OpenNest.Posts.Cincinnati; + +/// +/// Emits the main program header and variable declaration subprogram +/// for a Cincinnati laser post-processor output file. +/// +public sealed class CincinnatiPreambleWriter +{ + private readonly CincinnatiPostConfig _config; + + public CincinnatiPreambleWriter(CincinnatiPostConfig config) + { + _config = config; + } + + /// + /// Writes the main program header block. + /// + public void WriteMainProgram(TextWriter w, string nestName, string materialDescription, int sheetCount) + { + w.WriteLine(CoordinateFormatter.Comment($"NEST {nestName}")); + w.WriteLine(CoordinateFormatter.Comment($"CONFIGURATION - {_config.ConfigurationName}")); + w.WriteLine(CoordinateFormatter.Comment(DateTime.Now.ToString("MM-dd-yyyy hh:mm:ss tt"))); + + if (!string.IsNullOrEmpty(materialDescription)) + w.WriteLine(CoordinateFormatter.Comment($"Material = {materialDescription}")); + + if (_config.UseExactStopMode) + w.WriteLine("G61"); + + w.WriteLine(CoordinateFormatter.Comment("MAIN PROGRAM")); + + w.WriteLine(_config.PostedUnits == Units.Millimeters ? "G21" : "G20"); + + w.WriteLine("M42"); + + if (_config.ProcessParameterMode == G89Mode.LibraryFile && !string.IsNullOrEmpty(_config.DefaultLibraryFile)) + w.WriteLine($"G89 P {_config.DefaultLibraryFile}"); + + w.WriteLine($"M98 P{_config.VariableDeclarationSubprogram} (Variable Declaration)"); + + w.WriteLine("GOTO1 (GOTO SHEET NUMBER)"); + + for (var i = 1; i <= sheetCount; i++) + { + var subNum = _config.SheetSubprogramStart + (i - 1); + w.WriteLine($"N{i}M98 P{subNum} (SHEET {i})"); + } + + w.WriteLine("M42"); + w.WriteLine("M30 (END OF MAIN)"); + } + + /// + /// Writes the variable declaration subprogram block. + /// + public void WriteVariableDeclaration(TextWriter w, ProgramVariableManager vars) + { + w.WriteLine("(*****************************************************)"); + w.WriteLine($":{_config.VariableDeclarationSubprogram}"); + w.WriteLine("(Variable Declaration Start)"); + + foreach (var line in vars.EmitDeclarations()) + w.WriteLine(line); + + w.WriteLine("M99 (Variable Declaration End)"); + } +} diff --git a/OpenNest.Tests/Cincinnati/CincinnatiPreambleWriterTests.cs b/OpenNest.Tests/Cincinnati/CincinnatiPreambleWriterTests.cs new file mode 100644 index 0000000..7481913 --- /dev/null +++ b/OpenNest.Tests/Cincinnati/CincinnatiPreambleWriterTests.cs @@ -0,0 +1,97 @@ +using System.IO; +using System.Text; +using OpenNest.Posts.Cincinnati; + +namespace OpenNest.Tests.Cincinnati; + +public class CincinnatiPreambleWriterTests +{ + [Fact] + public void WriteMainProgram_EmitsHeader() + { + var config = new CincinnatiPostConfig + { + ConfigurationName = "CL940", + PostedUnits = Units.Inches, + DefaultLibraryFile = "MS135N2PANEL.lib" + }; + var sb = new StringBuilder(); + using var sw = new StringWriter(sb); + var writer = new CincinnatiPreambleWriter(config); + + writer.WriteMainProgram(sw, "TestNest", "Mild Steel, 10GA", 2); + + var output = sb.ToString(); + Assert.Contains("( NEST TestNest )", output); + Assert.Contains("( CONFIGURATION - CL940 )", output); + Assert.Contains("G20", output); + Assert.Contains("M42", output); + Assert.Contains("G89 P MS135N2PANEL.lib", output); + Assert.Contains("M98 P100 (Variable Declaration)", output); + Assert.Contains("GOTO1 (GOTO SHEET NUMBER)", output); + Assert.Contains("N1M98 P101 (SHEET 1)", output); + Assert.Contains("N2M98 P102 (SHEET 2)", output); + Assert.Contains("M30 (END OF MAIN)", output); + } + + [Fact] + public void WriteMainProgram_EmitsG21ForMetric() + { + var config = new CincinnatiPostConfig { PostedUnits = Units.Millimeters }; + var sb = new StringBuilder(); + using var sw = new StringWriter(sb); + var writer = new CincinnatiPreambleWriter(config); + + writer.WriteMainProgram(sw, "Test", "", 1); + + Assert.Contains("G21", sb.ToString()); + } + + [Fact] + public void WriteMainProgram_EmitsG61_WhenExactStop() + { + var config = new CincinnatiPostConfig { UseExactStopMode = true }; + var sb = new StringBuilder(); + using var sw = new StringWriter(sb); + var writer = new CincinnatiPreambleWriter(config); + + writer.WriteMainProgram(sw, "Test", "", 1); + + Assert.Contains("G61", sb.ToString()); + } + + [Fact] + public void WriteMainProgram_OmitsG61_WhenNotExactStop() + { + var config = new CincinnatiPostConfig { UseExactStopMode = false }; + var sb = new StringBuilder(); + using var sw = new StringWriter(sb); + var writer = new CincinnatiPreambleWriter(config); + + writer.WriteMainProgram(sw, "Test", "", 1); + + Assert.DoesNotContain("G61", sb.ToString()); + } + + [Fact] + public void WriteVariableDeclaration_EmitsSubprogram() + { + var config = new CincinnatiPostConfig(); + var vars = new ProgramVariableManager(); + vars.GetOrCreate("LeadInFeedrate", 126, "[#148*0.5]"); + vars.GetOrCreate("CircleFeedrate", 128, ".8"); + + var sb = new StringBuilder(); + using var sw = new StringWriter(sb); + var writer = new CincinnatiPreambleWriter(config); + + writer.WriteVariableDeclaration(sw, vars); + + var output = sb.ToString(); + Assert.Contains(":100", output); + Assert.Contains("(Variable Declaration Start)", output); + Assert.Contains("#126=", output); + Assert.Contains("#128=", output); + Assert.Contains("M99 (Variable Declaration End)", output); + } +}