From afdd386456c725780d4601a1cc6f3a80339dd9e5 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sat, 28 Mar 2026 09:49:07 -0400 Subject: [PATCH] feat: add entity index labels toggle to EntityView and CadConverterForm Labels are drawn at each entity's midpoint with a filled background circle for readability. Toggle via "Labels" checkbox in the detail bar. Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest/Controls/EntityView.cs | 55 +++++++++++++++++++++ OpenNest/Forms/CadConverterForm.Designer.cs | 11 +++++ OpenNest/Forms/CadConverterForm.cs | 6 +++ 3 files changed, 72 insertions(+) diff --git a/OpenNest/Controls/EntityView.cs b/OpenNest/Controls/EntityView.cs index d27231d..1500649 100644 --- a/OpenNest/Controls/EntityView.cs +++ b/OpenNest/Controls/EntityView.cs @@ -28,9 +28,13 @@ namespace OpenNest.Controls public List SimplifierToleranceLeft { get; set; } public List SimplifierToleranceRight { get; set; } public List OriginalEntities { get; set; } + public bool ShowEntityLabels { get; set; } private readonly Pen gridPen = new Pen(Color.FromArgb(70, 70, 70)); private readonly Dictionary penCache = new Dictionary(); + private readonly Font labelFont = new Font("Segoe UI", 7f); + private readonly SolidBrush labelBrush = new SolidBrush(Color.FromArgb(220, 255, 255, 200)); + private readonly SolidBrush labelBackBrush = new SolidBrush(Color.FromArgb(33, 40, 48)); public event EventHandler LinePicked; public event EventHandler PickCancelled; @@ -112,6 +116,9 @@ namespace OpenNest.Controls DrawEntity(e.Graphics, entity, pen); } + if (ShowEntityLabels) + DrawEntityLabels(e.Graphics); + if (SimplifierPreview != null) { // Draw tolerance zone (offset lines each side of original geometry) @@ -301,12 +308,60 @@ namespace OpenNest.Controls return bestLine; } + private void DrawEntityLabels(Graphics g) + { + for (var i = 0; i < Entities.Count; i++) + { + var entity = Entities[i]; + if (!entity.Layer.IsVisible || !entity.IsVisible) + continue; + + var mid = GetEntityMidPoint(entity); + if (!mid.HasValue) continue; + + var pt = PointWorldToGraph(mid.Value); + var text = i.ToString(); + var size = g.MeasureString(text, labelFont); + var cx = pt.X - size.Width / 2f; + var cy = pt.Y - size.Height / 2f; + var radius = System.Math.Max(size.Width, size.Height) / 2f + 2f; + g.FillEllipse(labelBackBrush, pt.X - radius, pt.Y - radius, radius * 2f, radius * 2f); + g.DrawString(text, labelFont, labelBrush, cx, cy); + } + } + + private static Vector? GetEntityMidPoint(Entity entity) + { + switch (entity) + { + case Line line: + return line.MidPoint; + + case Arc arc: + var midAngle = arc.IsReversed + ? arc.StartAngle - arc.SweepAngle() / 2.0 + : arc.StartAngle + arc.SweepAngle() / 2.0; + return new Vector( + arc.Center.X + arc.Radius * System.Math.Cos(midAngle), + arc.Center.Y + arc.Radius * System.Math.Sin(midAngle)); + + case Circle circle: + return circle.Center; + + default: + return null; + } + } + protected override void Dispose(bool disposing) { if (disposing) { ClearPenCache(); gridPen.Dispose(); + labelFont.Dispose(); + labelBrush.Dispose(); + labelBackBrush.Dispose(); } base.Dispose(disposing); } diff --git a/OpenNest/Forms/CadConverterForm.Designer.cs b/OpenNest/Forms/CadConverterForm.Designer.cs index 293c442..036baa7 100644 --- a/OpenNest/Forms/CadConverterForm.Designer.cs +++ b/OpenNest/Forms/CadConverterForm.Designer.cs @@ -31,6 +31,7 @@ namespace OpenNest.Forms btnSimplify = new System.Windows.Forms.Button(); btnExportDxf = new System.Windows.Forms.Button(); chkShowOriginal = new System.Windows.Forms.CheckBox(); + chkLabels = new System.Windows.Forms.CheckBox(); lblDetect = new System.Windows.Forms.Label(); cboBendDetector = new System.Windows.Forms.ComboBox(); bottomPanel1 = new OpenNest.Controls.BottomPanel(); @@ -133,6 +134,7 @@ namespace OpenNest.Forms detailBar.Controls.Add(btnSimplify); detailBar.Controls.Add(btnExportDxf); detailBar.Controls.Add(chkShowOriginal); + detailBar.Controls.Add(chkLabels); detailBar.Controls.Add(lblDetect); detailBar.Controls.Add(cboBendDetector); detailBar.Dock = System.Windows.Forms.DockStyle.Bottom; @@ -246,6 +248,14 @@ namespace OpenNest.Forms chkShowOriginal.Margin = new System.Windows.Forms.Padding(6, 3, 0, 0); chkShowOriginal.CheckedChanged += new System.EventHandler(this.OnShowOriginalChanged); // + // chkLabels + // + chkLabels.AutoSize = true; + chkLabels.Font = new System.Drawing.Font("Segoe UI", 9F); + chkLabels.Text = "Labels"; + chkLabels.Margin = new System.Windows.Forms.Padding(6, 3, 0, 0); + chkLabels.CheckedChanged += new System.EventHandler(this.OnLabelsChanged); + // // lblDetect // lblDetect.AutoSize = true; @@ -347,6 +357,7 @@ namespace OpenNest.Forms private System.Windows.Forms.Button btnSimplify; private System.Windows.Forms.Button btnExportDxf; private System.Windows.Forms.CheckBox chkShowOriginal; + private System.Windows.Forms.CheckBox chkLabels; private System.Windows.Forms.ComboBox cboBendDetector; private System.Windows.Forms.Label lblQty; private System.Windows.Forms.Label lblCust; diff --git a/OpenNest/Forms/CadConverterForm.cs b/OpenNest/Forms/CadConverterForm.cs index 77ea09f..112212b 100644 --- a/OpenNest/Forms/CadConverterForm.cs +++ b/OpenNest/Forms/CadConverterForm.cs @@ -481,6 +481,12 @@ namespace OpenNest.Forms entityView1.Invalidate(); } + private void OnLabelsChanged(object sender, EventArgs e) + { + entityView1.ShowEntityLabels = chkLabels.Checked; + entityView1.Invalidate(); + } + private void OnExportDxfClick(object sender, EventArgs e) { var item = CurrentItem;