diff --git a/OpenNest.Core/Part.cs b/OpenNest.Core/Part.cs index 73e466bc..adf76d3a 100644 --- a/OpenNest.Core/Part.cs +++ b/OpenNest.Core/Part.cs @@ -432,11 +432,13 @@ namespace OpenNest /// Copies the lead-in state that goes with a copied program. Without it a copy of a /// lead-in part reads its rotation from the rebuilt program (zero), and lead-in /// assignment does not know to strip the copied lead-ins before adding new ones. + /// A copy of a placement with drawing pins off keeps them off. /// private void CopyLeadInStateFrom(Part source) { HasManualLeadIns = source.HasManualLeadIns; LeadInsLocked = source.LeadInsLocked; + DrawingPinsOff = source.DrawingPinsOff; CuttingParameters = source.CuttingParameters; preLeadInRotation = source.preLeadInRotation; } diff --git a/OpenNest.Data/LibraryDrawingInsert.cs b/OpenNest.Data/LibraryDrawingInsert.cs index 46a97ec5..808c56ef 100644 --- a/OpenNest.Data/LibraryDrawingInsert.cs +++ b/OpenNest.Data/LibraryDrawingInsert.cs @@ -74,9 +74,9 @@ public sealed class LibraryDrawingInsert public int Quantity { get; } /// - /// For a new copy, true when the library drawing's cut pins may be used in this nest: - /// the library material, grade and thickness match the nest's. An added quantity - /// leaves the existing copy as it is. + /// For a new copy, true when the library drawing's cut pins come with it: the library + /// material, grade and thickness match the nest's. Otherwise the copy has no pins. An + /// added quantity leaves the existing copy as it is. /// public bool KeepPins { get; } @@ -142,6 +142,10 @@ public sealed class LibraryDrawingInsert drawing.Material = new Material(record.MaterialName, record.MaterialGrade, drawing.Material?.Density ?? 0); drawing.Quantity.Required = quantity; drawing.Library = link; + // Pins were authored for the library material and thickness; elsewhere the nest's + // cutting settings apply (D3). The link still records the revision the copy came from. + if (differences.Count > 0) + drawing.CutPins.Clear(); return new LibraryDrawingInsert(nest, LibraryInsertKind.AddDrawing, drawing, quantity, keepPins: differences.Count == 0, warnings, ""); } diff --git a/OpenNest.Tests/CuttingStrategy/PartLeadInTransformTests.cs b/OpenNest.Tests/CuttingStrategy/PartLeadInTransformTests.cs index aec5be34..2a9b5b4d 100644 --- a/OpenNest.Tests/CuttingStrategy/PartLeadInTransformTests.cs +++ b/OpenNest.Tests/CuttingStrategy/PartLeadInTransformTests.cs @@ -182,4 +182,24 @@ public class PartLeadInTransformTests Assert.Equal(before.Width, after.Length, 6); Assert.Equal(before.Length, after.Width, 6); } + + [Fact] + public void Copies_KeepDrawingPinsOff() + { + var drawing = MakeSquareWithHole(); + var clean = MakeCleanPart(drawing, QuarterTurn, new Vector(2, 3)); + clean.DrawingPinsOff = true; + var withLeadIns = MakeLeadInPart(drawing, QuarterTurn); + withLeadIns.DrawingPinsOff = true; + + Assert.True(((Part)clean.Clone()).DrawingPinsOff); + Assert.True(clean.CloneAtOffset(new Vector(1, 1)).DrawingPinsOff); + Assert.True(((Part)withLeadIns.Clone()).DrawingPinsOff); + Assert.True(withLeadIns.CloneAtOffset(new Vector(1, 1)).DrawingPinsOff); + Assert.False(((Part)MakeCleanPart(drawing, 0, Vector.Zero).Clone()).DrawingPinsOff); + + // Pins-off is a placement choice, not lead-in state: clearing lead-ins keeps it. + withLeadIns.RemoveLeadIns(); + Assert.True(withLeadIns.DrawingPinsOff); + } } diff --git a/OpenNest.Tests/Data/LibraryDrawingInsertTests.cs b/OpenNest.Tests/Data/LibraryDrawingInsertTests.cs index ec14d9ca..d3dac08c 100644 --- a/OpenNest.Tests/Data/LibraryDrawingInsertTests.cs +++ b/OpenNest.Tests/Data/LibraryDrawingInsertTests.cs @@ -1,5 +1,7 @@ using System.Security.Cryptography; +using OpenNest.CNC.CuttingStrategy; using OpenNest.Data; +using OpenNest.Geometry; using OpenNest.Shapes; namespace OpenNest.Tests.Data; @@ -37,6 +39,8 @@ public class LibraryDrawingInsertTests var drawing = new RectangleShape { Name = "old package name", Length = 4, Width = 2 }.GetDrawing(); drawing.Material = new Material("Package material", "Package grade", 0.284); drawing.Customer = "Package customer"; + drawing.CutPins.Add(new ContourCutPin(new Vector(4, 2), new LineLeadIn { Length = 0.25 }, new NoLeadOut(), + new NormalTab { Size = 0.03 })); return new LibraryPackage(PackageBytes, drawing, units, warnings); } @@ -57,6 +61,7 @@ public class LibraryDrawingInsertTests var drawing = Assert.Single(nest.Drawings); Assert.Same(package.Drawing, drawing); + Assert.Equal(new Vector(4, 2), Assert.Single(drawing.CutPins).Point); Assert.Equal(("SYN-101", "Synthetic customer", 5), (drawing.Name, drawing.Customer, drawing.Quantity.Required)); Assert.Equal(("Synthetic Steel", "Grade A", 0.284), (drawing.Material.Name, drawing.Material.Grade, drawing.Material.Density)); var link = drawing.Library!; @@ -98,8 +103,11 @@ public class LibraryDrawingInsertTests Assert.Contains(expected, warning); Assert.Contains("'SYN-101'", warning); Assert.Contains("cut pins are dropped", warning); + Assert.Empty(insert.Drawing!.CutPins); insert.Apply(); - Assert.Single(nest.Drawings); + var drawing = Assert.Single(nest.Drawings); + Assert.Empty(drawing.CutPins); + Assert.NotNull(drawing.Library); } [Fact]