diff --git a/OpenNest.Core/Converters/ConvertProgram.cs b/OpenNest.Core/Converters/ConvertProgram.cs index f7dff54..c1a8cc7 100644 --- a/OpenNest.Core/Converters/ConvertProgram.cs +++ b/OpenNest.Core/Converters/ConvertProgram.cs @@ -59,9 +59,11 @@ namespace OpenNest.Converters if (mode == Mode.Incremental) pt += curpos; + var layer = ConvertLayer(linearMove.Layer); var line = new Line(curpos, pt) { - Layer = ConvertLayer(linearMove.Layer) + Layer = layer, + Color = layer.Color }; geometry.Add(line); curpos = pt; @@ -76,7 +78,8 @@ namespace OpenNest.Converters var line = new Line(curpos, pt) { - Layer = SpecialLayers.Rapid + Layer = SpecialLayers.Rapid, + Color = SpecialLayers.Rapid.Color }; geometry.Add(line); curpos = pt; @@ -103,9 +106,9 @@ namespace OpenNest.Converters var layer = ConvertLayer(arcMove.Layer); if (startAngle.IsEqualTo(endAngle)) - geometry.Add(new Circle(center, radius) { Layer = layer }); + geometry.Add(new Circle(center, radius) { Layer = layer, Color = layer.Color }); else - geometry.Add(new Arc(center, radius, startAngle, endAngle, arcMove.Rotation == RotationType.CW) { Layer = layer }); + geometry.Add(new Arc(center, radius, startAngle, endAngle, arcMove.Rotation == RotationType.CW) { Layer = layer, Color = layer.Color }); curpos = endpt; } diff --git a/OpenNest.Core/SpecialLayers.cs b/OpenNest.Core/SpecialLayers.cs index 9931fae..46d6578 100644 --- a/OpenNest.Core/SpecialLayers.cs +++ b/OpenNest.Core/SpecialLayers.cs @@ -1,21 +1,22 @@ -using OpenNest.Geometry; +using System.Drawing; +using OpenNest.Geometry; namespace OpenNest { public static class SpecialLayers { - public static readonly Layer Default = new Layer("0"); + public static readonly Layer Default = new Layer("0") { Color = Color.White }; - public static readonly Layer Cut = new Layer("CUT"); + public static readonly Layer Cut = new Layer("CUT") { Color = Color.White }; - public static readonly Layer Rapid = new Layer("RAPID"); + public static readonly Layer Rapid = new Layer("RAPID") { Color = Color.Gray }; - public static readonly Layer Display = new Layer("DISPLAY"); + public static readonly Layer Display = new Layer("DISPLAY") { Color = Color.Cyan }; - public static readonly Layer Leadin = new Layer("LEADIN"); + public static readonly Layer Leadin = new Layer("LEADIN") { Color = Color.Yellow }; - public static readonly Layer Leadout = new Layer("LEADOUT"); + public static readonly Layer Leadout = new Layer("LEADOUT") { Color = Color.Yellow }; - public static readonly Layer Scribe = new Layer("SCRIBE"); + public static readonly Layer Scribe = new Layer("SCRIBE") { Color = Color.Magenta }; } } diff --git a/OpenNest.IO/Bending/SolidWorksBendDetector.cs b/OpenNest.IO/Bending/SolidWorksBendDetector.cs index 0ad9a8f..c441c35 100644 --- a/OpenNest.IO/Bending/SolidWorksBendDetector.cs +++ b/OpenNest.IO/Bending/SolidWorksBendDetector.cs @@ -17,9 +17,13 @@ namespace OpenNest.IO.Bending public double MaxBendRadius { get; set; } = 4.0; private static readonly Regex BendNoteRegex = new Regex( - @"\b(?UP|DOWN|DN)\s+(?\d+(\.\d+)?)°?\s*R\s*(?\d+(\.\d+)?)\b", + @"(?UP|DOWN|DN)\s+(?\d+(\.\d+)?)[^A-Z\d]*R\s*(?\d+(\.\d+)?)", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex MTextFormatRegex = new Regex( + @"\\[fHCTQWASpOoLlKk][^;]*;|\\P|[{}]|%%[dDpPcC]", + RegexOptions.Compiled); + public List DetectBends(CadDocument document) { var bendLines = FindBendLines(document); @@ -45,9 +49,10 @@ namespace OpenNest.IO.Bending var note = FindClosestBendNote(line, bendNotes); if (note != null) { - bend.Direction = GetBendDirection(note.Value); - bend.NoteText = note.Value; - ParseBendNote(note.Value, bend); + var noteText = StripMTextFormatting(note.Value); + bend.Direction = GetBendDirection(noteText); + bend.NoteText = noteText; + ParseBendNote(noteText, bend); } if (!bend.Radius.HasValue || bend.Radius.Value <= MaxBendRadius) @@ -106,6 +111,24 @@ namespace OpenNest.IO.Bending } } + private static string StripMTextFormatting(string text) + { + if (string.IsNullOrEmpty(text)) + return text; + + // Replace known DXF special characters + var result = text + .Replace("%%d", "°").Replace("%%D", "°") + .Replace("%%p", "±").Replace("%%P", "±") + .Replace("%%c", "⌀").Replace("%%C", "⌀"); + + // Strip MText formatting codes and braces + result = MTextFormatRegex.Replace(result, " "); + + // Collapse multiple spaces + return Regex.Replace(result.Trim(), @"\s+", " "); + } + private MText FindClosestBendNote(ACadSharp.Entities.Line bendLine, List notes) { if (notes.Count == 0) return null; diff --git a/OpenNest/Controls/EntityView.cs b/OpenNest/Controls/EntityView.cs index 5627c90..a2476d8 100644 --- a/OpenNest/Controls/EntityView.cs +++ b/OpenNest/Controls/EntityView.cs @@ -1,4 +1,5 @@ -using OpenNest.Geometry; +using OpenNest.Bending; +using OpenNest.Geometry; using OpenNest.Math; using System.Collections.Generic; using System.Drawing; @@ -10,6 +11,8 @@ namespace OpenNest.Controls public class EntityView : DrawControl { public List Entities; + public List Bends = new List(); + public int SelectedBendIndex = -1; private readonly Pen gridPen = new Pen(Color.FromArgb(70, 70, 70)); private readonly Dictionary penCache = new Dictionary(); @@ -49,6 +52,8 @@ namespace OpenNest.Controls DrawEntity(e.Graphics, entity, pen); } + DrawBendLines(e.Graphics); + #if DRAW_OFFSET var offsetShape = new Shape(); @@ -106,6 +111,9 @@ namespace OpenNest.Controls private Pen GetEntityPen(Color color) { + if (color.IsEmpty || color.A == 0) + color = Color.White; + // Clamp dark colors to ensure visibility on dark background var brightness = (color.R * 299 + color.G * 587 + color.B * 114) / 1000; if (brightness < 80) @@ -130,6 +138,29 @@ namespace OpenNest.Controls penCache.Clear(); } + private void DrawBendLines(Graphics g) + { + if (Bends == null || Bends.Count == 0) + return; + + using var bendPen = new Pen(Color.Yellow, 1.5f) + { + DashStyle = DashStyle.Dash + }; + using var selectedPen = new Pen(Color.Cyan, 2.5f) + { + DashStyle = DashStyle.Dash + }; + + for (var i = 0; i < Bends.Count; i++) + { + var bend = Bends[i]; + var pt1 = PointWorldToGraph(bend.StartPoint); + var pt2 = PointWorldToGraph(bend.EndPoint); + g.DrawLine(i == SelectedBendIndex ? selectedPen : bendPen, pt1, pt2); + } + } + protected override void Dispose(bool disposing) { if (disposing) diff --git a/OpenNest/Forms/CadConverterForm.cs b/OpenNest/Forms/CadConverterForm.cs index 2841c55..58d7f0e 100644 --- a/OpenNest/Forms/CadConverterForm.cs +++ b/OpenNest/Forms/CadConverterForm.cs @@ -134,6 +134,7 @@ namespace OpenNest.Forms entityView1.ClearPenCache(); entityView1.Entities.Clear(); entityView1.Entities.AddRange(item.Entities); + entityView1.Bends = item.Bends ?? new List(); item.Entities.ForEach(e => e.IsVisible = true); if (item.Entities.Any(e => e.Layer != null)) @@ -174,7 +175,7 @@ namespace OpenNest.Forms private void OnBendLineSelected(object sender, int index) { - // TODO: Highlight bend line in EntityView + entityView1.SelectedBendIndex = index; entityView1.Invalidate(); } @@ -184,6 +185,8 @@ namespace OpenNest.Forms if (item == null || index < 0 || index >= item.Bends.Count) return; item.Bends.RemoveAt(index); + entityView1.Bends = item.Bends; + entityView1.SelectedBendIndex = -1; filterPanel.LoadItem(item.Entities, item.Bends); entityView1.Invalidate(); }