From b3e9e5e28b7a7fca70d7bfe8602506f943625f37 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sun, 5 Apr 2026 00:34:34 -0400 Subject: [PATCH] feat: add plate optimizer UI controls to AutoNestForm Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest/Forms/AutoNestForm.Designer.cs | 84 ++++++++++++++++++++++++- OpenNest/Forms/AutoNestForm.cs | 70 ++++++++++++++++++++- 2 files changed, 152 insertions(+), 2 deletions(-) diff --git a/OpenNest/Forms/AutoNestForm.Designer.cs b/OpenNest/Forms/AutoNestForm.Designer.cs index 14b87c5..a5941f5 100644 --- a/OpenNest/Forms/AutoNestForm.Designer.cs +++ b/OpenNest/Forms/AutoNestForm.Designer.cs @@ -33,7 +33,14 @@ this.acceptButton = new System.Windows.Forms.Button(); this.createNewPlatesAsNeededBox = new System.Windows.Forms.CheckBox(); this.cancelButton = new System.Windows.Forms.Button(); + this.optimizePlateSizeBox = new System.Windows.Forms.CheckBox(); + this.plateOptionsPanel = new System.Windows.Forms.Panel(); + this.plateOptionsGrid = new System.Windows.Forms.DataGridView(); + this.salvageRateLabel = new System.Windows.Forms.Label(); + this.salvageRateBox = new System.Windows.Forms.TextBox(); + this.salvageRatePercentLabel = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.plateOptionsGrid)).BeginInit(); this.bottomPanel1.SuspendLayout(); this.SuspendLayout(); // @@ -53,6 +60,7 @@ // // bottomPanel1 // + this.bottomPanel1.Controls.Add(this.optimizePlateSizeBox); this.bottomPanel1.Controls.Add(this.acceptButton); this.bottomPanel1.Controls.Add(this.createNewPlatesAsNeededBox); this.bottomPanel1.Controls.Add(this.cancelButton); @@ -96,11 +104,78 @@ this.cancelButton.TabIndex = 7; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; - // + // + // optimizePlateSizeBox + // + this.optimizePlateSizeBox.AutoSize = true; + this.optimizePlateSizeBox.Location = new System.Drawing.Point(220, 15); + this.optimizePlateSizeBox.Name = "optimizePlateSizeBox"; + this.optimizePlateSizeBox.Size = new System.Drawing.Size(148, 20); + this.optimizePlateSizeBox.TabIndex = 10; + this.optimizePlateSizeBox.Text = "Optimize plate size"; + this.optimizePlateSizeBox.UseVisualStyleBackColor = true; + this.optimizePlateSizeBox.CheckedChanged += new System.EventHandler(this.optimizePlateSizeBox_CheckedChanged); + // + // plateOptionsPanel + // + this.plateOptionsPanel.Controls.Add(this.plateOptionsGrid); + this.plateOptionsPanel.Controls.Add(this.salvageRateLabel); + this.plateOptionsPanel.Controls.Add(this.salvageRateBox); + this.plateOptionsPanel.Controls.Add(this.salvageRatePercentLabel); + this.plateOptionsPanel.Dock = System.Windows.Forms.DockStyle.Bottom; + this.plateOptionsPanel.Location = new System.Drawing.Point(0, 135); + this.plateOptionsPanel.Name = "plateOptionsPanel"; + this.plateOptionsPanel.Size = new System.Drawing.Size(545, 200); + this.plateOptionsPanel.TabIndex = 11; + this.plateOptionsPanel.Visible = false; + // + // plateOptionsGrid + // + this.plateOptionsGrid.AllowUserToOrderColumns = true; + this.plateOptionsGrid.AllowUserToResizeRows = false; + this.plateOptionsGrid.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.plateOptionsGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.plateOptionsGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.plateOptionsGrid.Location = new System.Drawing.Point(0, 0); + this.plateOptionsGrid.Name = "plateOptionsGrid"; + this.plateOptionsGrid.RowHeadersVisible = false; + this.plateOptionsGrid.Size = new System.Drawing.Size(545, 170); + this.plateOptionsGrid.TabIndex = 0; + // + // salvageRateLabel + // + this.salvageRateLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.salvageRateLabel.AutoSize = true; + this.salvageRateLabel.Location = new System.Drawing.Point(8, 176); + this.salvageRateLabel.Name = "salvageRateLabel"; + this.salvageRateLabel.Size = new System.Drawing.Size(96, 16); + this.salvageRateLabel.TabIndex = 1; + this.salvageRateLabel.Text = "Salvage Rate:"; + // + // salvageRateBox + // + this.salvageRateBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.salvageRateBox.Location = new System.Drawing.Point(106, 173); + this.salvageRateBox.Name = "salvageRateBox"; + this.salvageRateBox.Size = new System.Drawing.Size(50, 22); + this.salvageRateBox.TabIndex = 2; + this.salvageRateBox.Text = "50"; + // + // salvageRatePercentLabel + // + this.salvageRatePercentLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.salvageRatePercentLabel.AutoSize = true; + this.salvageRatePercentLabel.Location = new System.Drawing.Point(158, 176); + this.salvageRatePercentLabel.Name = "salvageRatePercentLabel"; + this.salvageRatePercentLabel.Size = new System.Drawing.Size(21, 16); + this.salvageRatePercentLabel.TabIndex = 3; + this.salvageRatePercentLabel.Text = "%"; + // // AutoNestForm // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.ClientSize = new System.Drawing.Size(545, 385); + this.Controls.Add(this.plateOptionsPanel); this.Controls.Add(this.bottomPanel1); this.Controls.Add(this.dataGridView1); this.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); @@ -110,6 +185,7 @@ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "AutoNest"; ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.plateOptionsGrid)).EndInit(); this.bottomPanel1.ResumeLayout(false); this.bottomPanel1.PerformLayout(); this.ResumeLayout(false); @@ -123,5 +199,11 @@ private System.Windows.Forms.Button cancelButton; private System.Windows.Forms.CheckBox createNewPlatesAsNeededBox; private Controls.BottomPanel bottomPanel1; + private System.Windows.Forms.CheckBox optimizePlateSizeBox; + private System.Windows.Forms.Panel plateOptionsPanel; + private System.Windows.Forms.DataGridView plateOptionsGrid; + private System.Windows.Forms.Label salvageRateLabel; + private System.Windows.Forms.TextBox salvageRateBox; + private System.Windows.Forms.Label salvageRatePercentLabel; } } \ No newline at end of file diff --git a/OpenNest/Forms/AutoNestForm.cs b/OpenNest/Forms/AutoNestForm.cs index 4018d54..38b2220 100644 --- a/OpenNest/Forms/AutoNestForm.cs +++ b/OpenNest/Forms/AutoNestForm.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; @@ -12,6 +13,7 @@ namespace OpenNest.Forms LoadDrawings(nest); dataGridView1.DataError += dataGridView1_DataError; + LoadDefaultPlateOptions(); } public bool AllowPlateCreation @@ -20,6 +22,72 @@ namespace OpenNest.Forms set { createNewPlatesAsNeededBox.Checked = value; } } + public bool OptimizePlateSize + { + get { return optimizePlateSizeBox.Checked; } + set { optimizePlateSizeBox.Checked = value; } + } + + public double SalvageRate + { + get + { + if (double.TryParse(salvageRateBox.Text, out var val)) + return System.Math.Clamp(val / 100.0, 0, 1); + return 0.5; + } + set { salvageRateBox.Text = (value * 100).ToString("F0"); } + } + + public List GetPlateOptions() + { + var result = new List(); + var gridItems = plateOptionsGrid.DataSource as List; + if (gridItems == null) return result; + + foreach (var item in gridItems) + { + if (item.Width <= 0 || item.Length <= 0) continue; + result.Add(new PlateOption + { + Width = item.Width, + Length = item.Length, + Cost = item.Cost, + }); + } + + return result; + } + + private void LoadDefaultPlateOptions() + { + var items = new List + { + new() { Width = 48, Length = 96, Cost = 0 }, + new() { Width = 48, Length = 120, Cost = 0 }, + new() { Width = 48, Length = 144, Cost = 0 }, + new() { Width = 60, Length = 96, Cost = 0 }, + new() { Width = 60, Length = 120, Cost = 0 }, + new() { Width = 60, Length = 144, Cost = 0 }, + new() { Width = 72, Length = 96, Cost = 0 }, + new() { Width = 72, Length = 120, Cost = 0 }, + new() { Width = 72, Length = 144, Cost = 0 }, + }; + plateOptionsGrid.DataSource = items; + } + + private void optimizePlateSizeBox_CheckedChanged(object sender, EventArgs e) + { + plateOptionsPanel.Visible = optimizePlateSizeBox.Checked; + } + + internal class PlateOptionItem + { + public double Width { get; set; } + public double Length { get; set; } + public double Cost { get; set; } + } + private void LoadDrawings(Nest nest) { var items = new List();