diff --git a/OpenNest.Core/Bending/Bend.cs b/OpenNest.Core/Bending/Bend.cs index 3f8e694..5ed454b 100644 --- a/OpenNest.Core/Bending/Bend.cs +++ b/OpenNest.Core/Bending/Bend.cs @@ -26,6 +26,10 @@ namespace OpenNest.Bending [System.Text.Json.Serialization.JsonIgnore] public Entity SourceEntity { get; set; } + // Import-only identity of the original CAD annotation (not nest metadata). + [System.Text.Json.Serialization.JsonIgnore] + public ulong? SourceNoteHandle { get; set; } + public double Length => StartPoint.DistanceTo(EndPoint); public double AngleRadians => Angle.HasValue diff --git a/OpenNest.IO/Bending/SolidWorksBendDetector.cs b/OpenNest.IO/Bending/SolidWorksBendDetector.cs index 15b5d54..251c019 100644 --- a/OpenNest.IO/Bending/SolidWorksBendDetector.cs +++ b/OpenNest.IO/Bending/SolidWorksBendDetector.cs @@ -56,6 +56,7 @@ namespace OpenNest.IO.Bending var noteText = StripMTextFormatting(note.Value); bend.Direction = GetBendDirection(noteText); bend.NoteText = noteText; + bend.SourceNoteHandle = note.Handle; ParseBendNote(noteText, bend); } @@ -94,6 +95,7 @@ namespace OpenNest.IO.Bending bend.Angle = other.Angle; bend.Radius = other.Radius; bend.NoteText = other.NoteText; + bend.SourceNoteHandle = other.SourceNoteHandle; break; } } diff --git a/OpenNest.Tests/Bending/CadBendNoteTests.cs b/OpenNest.Tests/Bending/CadBendNoteTests.cs new file mode 100644 index 0000000..c892365 --- /dev/null +++ b/OpenNest.Tests/Bending/CadBendNoteTests.cs @@ -0,0 +1,47 @@ +using ACadSharp; +using ACadSharp.Entities; +using ACadSharp.Tables; +using CSMath; +using OpenNest.Bending; +using OpenNest.Controls; +using OpenNest.IO.Bending; + +namespace OpenNest.Tests.Bending; + +public class CadBendNoteTests +{ + [Fact] + public void DetectedNote_HidesOnlyItsSourceText_AndReturnsWhenBendRemoved() + { + var doc = new CadDocument(); + doc.Entities.Add(new Line(new XYZ(0, 0, 0), new XYZ(10, 0, 0)) + { + Layer = new Layer("BEND"), + LineType = new LineType("CENTER") + }); + var note = new MText { Value = "UP 90° R0.125", InsertPoint = new XYZ(5, 0.1, 0), Height = 0.2 }; + doc.Entities.Add(note); + var unrelated = new MText { Value = note.Value, InsertPoint = new XYZ(50, 50, 0), Height = 0.2 }; + doc.Entities.Add(unrelated); + + var bends = new SolidWorksBendDetector().DetectBends(doc); + var bend = Assert.Single(bends); + Assert.Equal(note.Handle, bend.SourceNoteHandle); + var text = new CadText { SourceHandle = note.Handle, Value = note.Value }; + Assert.True(text.IsReplacedByBendNote(bends)); + Assert.False(new CadText { SourceHandle = unrelated.Handle, Value = note.Value }.IsReplacedByBendNote(bends)); + + bends.Clear(); + Assert.False(text.IsReplacedByBendNote(bends)); + } + + [Fact] + public void MissingSourceOrReplacement_DoesNotHideText() + { + var text = new CadText { SourceHandle = 42, Value = "UP 90° R0.125" }; + Assert.False(text.IsReplacedByBendNote(null)); + Assert.False(text.IsReplacedByBendNote(new[] { new Bend { NoteText = text.Value } })); + Assert.False(text.IsReplacedByBendNote(new[] { new Bend { SourceNoteHandle = 42 } })); + Assert.False(new CadText().IsReplacedByBendNote(new[] { new Bend { NoteText = text.Value } })); + } +} diff --git a/OpenNest.Tests/Bending/SolidWorksBendDetectorTests.cs b/OpenNest.Tests/Bending/SolidWorksBendDetectorTests.cs index 40e95b4..379cdde 100644 --- a/OpenNest.Tests/Bending/SolidWorksBendDetectorTests.cs +++ b/OpenNest.Tests/Bending/SolidWorksBendDetectorTests.cs @@ -91,6 +91,9 @@ public class SolidWorksBendDetectorTests Assert.All(bends, b => { Assert.NotNull(b.NoteText); + Assert.NotNull(b.SourceNoteHandle); + Assert.Contains(doc.Entities, e => e.Handle == b.SourceNoteHandle + && e is ACadSharp.Entities.MText); Assert.Equal(BendDirection.Up, b.Direction); Assert.Equal(90.0, b.Angle); Assert.Equal(0.125, b.Radius); diff --git a/OpenNest/Controls/CadText.cs b/OpenNest/Controls/CadText.cs index d2d5174..8ae4d81 100644 --- a/OpenNest/Controls/CadText.cs +++ b/OpenNest/Controls/CadText.cs @@ -1,10 +1,19 @@ using System.Drawing; +using System.Collections.Generic; +using System.Linq; +using OpenNest.Bending; using OpenNest.Geometry; namespace OpenNest.Controls { public class CadText { + public ulong? SourceHandle { get; set; } + + public bool IsReplacedByBendNote(IEnumerable bends) => + SourceHandle.HasValue && bends != null && bends.Any(b => + b.SourceNoteHandle == SourceHandle && !string.IsNullOrEmpty(b.NoteText)); + public Vector Position { get; set; } public string Value { get; set; } public double Height { get; set; } diff --git a/OpenNest/Controls/EntityView.cs b/OpenNest/Controls/EntityView.cs index 5171714..b73bcb5 100644 --- a/OpenNest/Controls/EntityView.cs +++ b/OpenNest/Controls/EntityView.cs @@ -346,7 +346,7 @@ namespace OpenNest.Controls foreach (var text in Texts) { - if (string.IsNullOrEmpty(text.Value)) + if (string.IsNullOrEmpty(text.Value) || text.IsReplacedByBendNote(Bends)) continue; var estimatedWidth = text.Height * text.Value.Length * 0.6; @@ -531,6 +531,9 @@ namespace OpenNest.Controls foreach (var text in Texts) { + // The bend overlay already renders this source annotation. + if (text.IsReplacedByBendNote(Bends)) continue; + var pos = PointWorldToGraph(text.Position); var fontSize = LengthWorldToGui(text.Height); if (fontSize < 2f) continue; diff --git a/OpenNest/Forms/CadConverterForm.cs b/OpenNest/Forms/CadConverterForm.cs index 392bb63..9a8e9cb 100644 --- a/OpenNest/Forms/CadConverterForm.cs +++ b/OpenNest/Forms/CadConverterForm.cs @@ -929,6 +929,7 @@ namespace OpenNest.Forms var (mh, mv) = MapAttachmentPoint(mtext.AttachmentPoint); texts.Add(new CadText { + SourceHandle = mtext.Handle, Position = new Vector(mtext.InsertPoint.X, mtext.InsertPoint.Y), Value = ReplaceControlCodes(StripMTextFormatting(mtext.Value)), Height = mtext.Height, @@ -958,6 +959,7 @@ namespace OpenNest.Forms }; texts.Add(new CadText { + SourceHandle = text.Handle, Position = new Vector(pt.X, pt.Y), Value = ReplaceControlCodes(text.Value), Height = text.Height, diff --git a/README.md b/README.md index ebefd90..baa5f62 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Or open `OpenNest.sln` in Visual Studio and run the `OpenNest` project. ### CAD Converter -The CAD Converter turns DXF/DWG files into nest-ready drawings. Toggle layers, colors, and linetypes to exclude construction geometry; review detected bend lines; and preview the generated cut program with contour ordering before accepting the drawing into the nest. +The CAD Converter turns DXF/DWG files into nest-ready drawings. Detected bend notes replace their original CAD annotations in the preview, avoiding duplicate labels without hiding unrelated text. Toggle layers, colors, and linetypes to exclude construction geometry; review detected bend lines; and preview the generated cut program with contour ordering before accepting the drawing into the nest.

CAD Converter — layer, color, and linetype filtering