Files
OpenNest/OpenNest.Posts.Cincinnati/CincinnatiPostConfig.cs
AJ Isaacs 3d4204db7b fix: Cincinnati post processor arc feedrate, G89 spacing, pallet exchange, and preamble
- Add radius-based arc feedrate calculation (Variables/Percentages modes)
  with configurable radius ranges (#123/#124/#125 or inline expressions)
- Fix arc distance in SpeedClassifier using actual arc length instead of
  chord length (full circles previously computed as zero)
- Fix G89 P spacing: P now adjacent to filename per CL-707 manual syntax
- Add lead-out feedrate support (#129) and arc lead-in feedrate (#127)
- Fix pallet exchange: StartAndEnd emits M50 in preamble + last sheet only
- Add G121 Smart Rapids emission when UseSmartRapids is enabled
- Add G90 absolute mode to main program preamble alongside G20/G21

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 09:33:50 -04:00

358 lines
12 KiB
C#

using System.Collections.Generic;
namespace OpenNest.Posts.Cincinnati
{
/// <summary>
/// Specifies how coordinate positioning is handled between parts.
/// </summary>
public enum CoordinateMode
{
/// <summary>Set absolute position.</summary>
G92,
/// <summary>Use relative/incremental positioning.</summary>
G91,
/// <summary>Use machine coordinate system.</summary>
G53
}
/// <summary>
/// Specifies how G89 (hole drilling/tapping parameters) are provided.
/// </summary>
public enum G89Mode
{
/// <summary>Use external library file for G89 parameters.</summary>
LibraryFile,
/// <summary>Explicitly define G89 parameters in the program.</summary>
Explicit
}
/// <summary>
/// Specifies where kerf compensation is applied.
/// </summary>
public enum KerfMode
{
/// <summary>Controller side (using cutter compensation codes).</summary>
ControllerSide,
/// <summary>Pre-applied to part geometry during post-processing.</summary>
PreApplied
}
/// <summary>
/// Specifies which side of the cut line kerf compensation is applied to.
/// </summary>
public enum KerfSide
{
/// <summary>Kerf applied to the left side of the cut.</summary>
Left,
/// <summary>Kerf applied to the right side of the cut.</summary>
Right
}
/// <summary>
/// Specifies how M47 (optional stop) commands are used.
/// </summary>
public enum M47Mode
{
/// <summary>Always include M47.</summary>
Always,
/// <summary>Include M47 with block delete functionality.</summary>
BlockDelete,
/// <summary>Automatically determine M47 placement.</summary>
Auto,
/// <summary>Do not use M47.</summary>
None
}
/// <summary>
/// Specifies when pallet exchange occurs.
/// </summary>
public enum PalletMode
{
/// <summary>No pallet exchange.</summary>
None,
/// <summary>Pallet exchange at end of sheet.</summary>
EndOfSheet,
/// <summary>Pallet exchange at start and end of sheet.</summary>
StartAndEnd
}
/// <summary>
/// Configuration for Cincinnati post processor.
/// Defines machine-specific parameters, output format, and cutting strategies.
/// </summary>
public sealed class CincinnatiPostConfig
{
/// <summary>
/// Gets or sets the configuration name/identifier.
/// Default: "CL940"
/// </summary>
public string ConfigurationName { get; set; } = "CL940";
/// <summary>
/// Gets or sets the units for posted output.
/// Default: Units.Inches
/// </summary>
public Units PostedUnits { get; set; } = Units.Inches;
/// <summary>
/// Gets or sets the decimal accuracy for numeric output.
/// Default: 4
/// </summary>
public int PostedAccuracy { get; set; } = 4;
/// <summary>
/// Gets or sets how coordinate positioning is handled between parts.
/// Default: CoordinateMode.G92
/// </summary>
public CoordinateMode CoordModeBetweenParts { get; set; } = CoordinateMode.G92;
/// <summary>
/// Gets or sets whether to use subprograms for sheet operations.
/// Default: true
/// </summary>
public bool UseSheetSubprograms { get; set; } = true;
/// <summary>
/// Gets or sets the starting subprogram number for sheet operations.
/// Default: 101
/// </summary>
public int SheetSubprogramStart { get; set; } = 101;
/// <summary>
/// Gets or sets whether to use M98 sub-programs for part geometry.
/// When enabled, each unique part geometry is written as a reusable sub-program
/// called via M98, reducing output size for nests with repeated parts.
/// Default: false
/// </summary>
public bool UsePartSubprograms { get; set; } = false;
/// <summary>
/// Gets or sets the starting sub-program number for part geometry sub-programs.
/// Default: 200
/// </summary>
public int PartSubprogramStart { get; set; } = 200;
/// <summary>
/// Gets or sets the subprogram number for variable declarations.
/// Default: 100
/// </summary>
public int VariableDeclarationSubprogram { get; set; } = 100;
/// <summary>
/// Gets or sets how G89 parameters are provided.
/// Default: G89Mode.LibraryFile
/// </summary>
public G89Mode ProcessParameterMode { get; set; } = G89Mode.LibraryFile;
/// <summary>
/// Gets or sets the default assist gas when Nest.AssistGas is empty.
/// Default: "O2"
/// </summary>
public string DefaultAssistGas { get; set; } = "O2";
/// <summary>
/// Gets or sets the gas used for etch operations.
/// Independent of the cutting assist gas — etch typically requires a specific gas.
/// Default: "N2"
/// </summary>
public string DefaultEtchGas { get; set; } = "N2";
/// <summary>
/// Gets or sets the material-to-library mapping for cut operations.
/// Each entry maps (material, thickness, gas) to a G89 library file.
/// </summary>
public List<MaterialLibraryEntry> MaterialLibraries { get; set; } = new();
/// <summary>
/// Gets or sets the gas-to-library mapping for etch operations.
/// Each entry maps a gas type to a G89 etch library file.
/// </summary>
public List<EtchLibraryEntry> EtchLibraries { get; set; } = new();
/// <summary>
/// Gets or sets whether to use exact stop mode (G61).
/// Default: false
/// </summary>
public bool UseExactStopMode { get; set; } = false;
/// <summary>
/// Gets or sets where kerf compensation is applied.
/// Default: KerfMode.ControllerSide
/// </summary>
public KerfMode KerfCompensation { get; set; } = KerfMode.ControllerSide;
/// <summary>
/// Gets or sets the default side for kerf compensation.
/// Default: KerfSide.Left
/// </summary>
public KerfSide DefaultKerfSide { get; set; } = KerfSide.Left;
/// <summary>
/// Gets or sets how M47 is used in interior cuts.
/// Default: M47Mode.Always
/// </summary>
public M47Mode InteriorM47 { get; set; } = M47Mode.Always;
/// <summary>
/// Gets or sets how M47 is used in exterior cuts.
/// Default: M47Mode.Always
/// </summary>
public M47Mode ExteriorM47 { get; set; } = M47Mode.Always;
/// <summary>
/// Gets or sets the safety head raise distance (in machine units).
/// Default: 2000
/// </summary>
public int? SafetyHeadraiseDistance { get; set; } = 2000;
/// <summary>
/// Gets or sets the distance threshold for M47 override.
/// Default: null
/// </summary>
public double? M47OverrideDistanceThreshold { get; set; } = null;
/// <summary>
/// Gets or sets whether to use anti-dive functionality.
/// Default: true
/// </summary>
public bool UseAntiDive { get; set; } = true;
/// <summary>
/// Gets or sets whether to use smart rapids optimization.
/// Default: false
/// </summary>
public bool UseSmartRapids { get; set; } = false;
/// <summary>
/// Gets or sets when pallet exchange occurs.
/// Default: PalletMode.EndOfSheet
/// </summary>
public PalletMode PalletExchange { get; set; } = PalletMode.EndOfSheet;
/// <summary>
/// Gets or sets whether to use line numbers in output.
/// Default: true
/// </summary>
public bool UseLineNumbers { get; set; } = true;
/// <summary>
/// Gets or sets the starting line number for features.
/// Default: 1
/// </summary>
public int FeatureLineNumberStart { get; set; } = 1;
/// <summary>
/// Gets or sets whether to use speed/gas commands.
/// Default: false
/// </summary>
public bool UseSpeedGas { get; set; } = false;
/// <summary>
/// Gets or sets the feedrate percentage for lead-in moves.
/// Default: 0.5 (50%)
/// </summary>
public double LeadInFeedratePercent { get; set; } = 0.5;
/// <summary>
/// Gets or sets the feedrate percentage for lead-in arc-to-line moves.
/// Default: 0.5 (50%)
/// </summary>
public double LeadInArcLine2FeedratePercent { get; set; } = 0.5;
/// <summary>
/// Gets or sets the feedrate percentage for lead-out moves.
/// Default: 0.5 (50%)
/// </summary>
public double LeadOutFeedratePercent { get; set; } = 0.5;
/// <summary>
/// Gets or sets the feedrate multiplier for circular cuts.
/// Default: 0.8 (80%)
/// </summary>
public double CircleFeedrateMultiplier { get; set; } = 0.8;
/// <summary>
/// Gets or sets the arc feedrate calculation mode.
/// Default: ArcFeedrateMode.None
/// </summary>
public ArcFeedrateMode ArcFeedrate { get; set; } = ArcFeedrateMode.None;
/// <summary>
/// Gets or sets the radius-based arc feedrate ranges.
/// Ranges are matched from smallest MaxRadius to largest.
/// </summary>
public List<ArcFeedrateRange> ArcFeedrateRanges { get; set; } = new()
{
new() { MaxRadius = 0.125, FeedratePercent = 0.25, VariableNumber = 123 },
new() { MaxRadius = 0.750, FeedratePercent = 0.50, VariableNumber = 124 },
new() { MaxRadius = 4.500, FeedratePercent = 0.80, VariableNumber = 125 }
};
/// <summary>
/// Gets or sets the variable number for sheet width.
/// Default: 110
/// </summary>
public int SheetWidthVariable { get; set; } = 110;
/// <summary>
/// Gets or sets the variable number for sheet length.
/// Default: 111
/// </summary>
public int SheetLengthVariable { get; set; } = 111;
}
public class MaterialLibraryEntry
{
public string Material { get; set; } = "";
public double Thickness { get; set; }
public string Gas { get; set; } = "";
public string Library { get; set; } = "";
}
public class EtchLibraryEntry
{
public string Gas { get; set; } = "";
public string Library { get; set; } = "";
}
/// <summary>
/// Specifies how arc feedrates are calculated based on radius.
/// </summary>
public enum ArcFeedrateMode
{
/// <summary>No radius-based arc feedrate adjustment (only full circles use multiplier).</summary>
None,
/// <summary>Inline percentage expressions: F [#148*pct] based on radius range.</summary>
Percentages,
/// <summary>Radius-range-based variables: F #varNum based on radius range.</summary>
Variables
}
/// <summary>
/// Defines a radius range and its associated feedrate for arc moves.
/// </summary>
public class ArcFeedrateRange
{
/// <summary>Maximum radius for this range (inclusive).</summary>
public double MaxRadius { get; set; }
/// <summary>Feedrate as a fraction of process feedrate (e.g. 0.25 = 25%).</summary>
public double FeedratePercent { get; set; }
/// <summary>Variable number for Variables mode (e.g. 123).</summary>
public int VariableNumber { get; set; }
}
}