Files
OpenNest/OpenNest.Tests/CuttingPlanning/DrawingPinReviewTests.cs
T
ajandClaude Opus 5.5 4d55e11318 style: use one spelling across the codebase
The repo mixed variants such as center/centre and color/colour, so a
name could be spelled either way and searches missed half the hits.
Standardize on the US spelling, matching .NET's own APIs (Color, Center).

Wire values owned by other systems keep their spelling: the material
ledger's "Cancelled" hold status and GitHub's "cancelled" job status.

No behavior change beyond the spelling of a few status messages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 16:11:30 -04:00

131 lines
5.8 KiB
C#

using OpenNest.CNC;
using OpenNest.CNC.CuttingPlanning;
using OpenNest.CNC.CuttingStrategy;
using OpenNest.Diagnostics;
using OpenNest.Engine;
using OpenNest.Engine.CuttingPlanning;
using OpenNest.Engine.Sequencing;
using OpenNest.Geometry;
namespace OpenNest.Tests.CuttingPlanning;
/// <summary>
/// The pre-post review reports a part whose active pins its program does not apply, plus fixed
/// (locked or pinned) lead violations.
/// </summary>
public class DrawingPinReviewTests
{
[Fact]
public void PrePost_PinsAppliedByPlanCutting_AreNotReported()
{
var (nest, plate, part) = PinnedNest();
var proposal = CuttingPlanBatch.Capture([plate], PinnedContourTests.NestSettings(), false).Plan();
Assert.Equal(CuttingCommitStatus.Applied, proposal.Apply().Status);
var review = PostVerificationAnalyzer.Analyze(nest);
Assert.DoesNotContain(review.Findings, f => f.Kind is PostVerificationKind.FixedLead or PostVerificationKind.Incomplete);
Assert.True(part.HasManualLeadIns);
}
[Fact]
public void PrePost_PinsNotApplied_IsAWarning()
{
var (nest, _, _) = PinnedNest(); // The program is the drawing's own: no pinned lead-in.
var finding = Assert.Single(PostVerificationAnalyzer.Analyze(nest).Findings, f => f.Kind == PostVerificationKind.FixedLead);
Assert.Equal(1, finding.PartNumber);
Assert.Equal("Drawing pins not applied: drawing pin 1 is not cut as pinned; plan cutting to apply it.", finding.Message);
}
[Fact]
public void PrePost_PinsOff_IsNotReported()
{
var (nest, _, part) = PinnedNest();
part.DrawingPinsOff = true;
Assert.DoesNotContain(PostVerificationAnalyzer.Analyze(nest).Findings, f => f.Kind == PostVerificationKind.FixedLead);
}
[Fact]
public void PrePost_LockedLeadInsOverridingPins_IsAWarning()
{
var (nest, _, part) = PinnedNest();
var prepared = PreparedContours.Capture(part.BaseDrawing.Program, ExplicitContourTests.Parameters());
Assert.True(part.RestoreLeadInProgram(prepared.Emit([prepared.ClosestEntry(0, new Vector(-1, 5))]), true));
var finding = Assert.Single(PostVerificationAnalyzer.Analyze(nest).Findings, f => f.Kind == PostVerificationKind.FixedLead);
Assert.StartsWith("Drawing pins not applied: the part's locked lead-ins override them.", finding.Message);
}
[Fact]
public void PrePost_UnresolvedPin_IsAWarning()
{
var nest = new Nest();
var plate = nest.CreatePlate();
plate.Parts.Add(new Part(PinnedContourTests.SquareWithPin(new Vector(5, 5), PinnedContourTests.Corner()),
new Vector(5, 5)));
var finding = Assert.Single(PostVerificationAnalyzer.Analyze(nest).Findings, f => f.Kind == PostVerificationKind.FixedLead);
Assert.Equal("Drawing pins not applied: drawing pin 1 no longer matches the geometry.", finding.Message);
}
[Fact]
public void PrePost_PinnedLeadIntoNeighbor_IsReportedAgainAfterAcceptance()
{
var nest = new Nest();
var plate = nest.CreatePlate();
var drawing = new Drawing("pinned", ExplicitContourTests.Square(false));
drawing.CutPins.Add(new ContourCutPin(new Vector(10, 5), new LineLeadIn { Length = 1.0, ApproachAngle = 90 },
new NoLeadOut()));
plate.Parts.Add(new Part(drawing, Vector.Zero));
plate.Parts.Add(new Part(new Drawing("neighbor", LeadPathValidationTests.Rectangle(0, 0, 2, 2)), new Vector(10.3, 4)));
var proposal = CuttingPlanBatch.Capture([plate], PinnedContourTests.NestSettings(), false).Plan();
Assert.Equal(CuttingCommitStatus.Applied, proposal.Apply(acceptWarnings: true).Status);
var pinned = plate.Parts.Single(p => p.BaseDrawing == drawing);
var neighbor = plate.Parts.Single(p => p.BaseDrawing != drawing);
var finding = Assert.Single(PostVerificationAnalyzer.Analyze(nest).Findings, f => f.Kind == PostVerificationKind.FixedLead);
Assert.Equal((plate.Parts.IndexOf(pinned) + 1, plate.Parts.IndexOf(neighbor) + 1),
(finding.PartNumber!.Value, finding.OtherPartNumber!.Value));
Assert.Equal($"Drawing pin 1 lead on cutting contour 1 contacts or enters the material of part "
+ $"{plate.Parts.IndexOf(neighbor) + 1}. Planning kept it as given; review it before posting.", finding.Message);
}
[Fact]
public void PrePost_LockedLeadTouchingAClamp_IsReported()
{
var nest = new Nest();
var plate = nest.CreatePlate();
plate.Size = new Size(100, 100);
var part = new Part(new Drawing("square", ExplicitContourTests.Square(false)), new Vector(5, 5));
var program = new Program();
program.MoveTo(-0.3, 5);
program.Codes.Add(new LinearMove(0, 5) { Layer = LayerType.Leadin });
program.LineTo(0, 10); program.LineTo(10, 10); program.LineTo(10, 0); program.LineTo(0, 0); program.LineTo(0, 5);
Assert.True(part.RestoreLeadInProgram(program, true));
plate.Parts.Add(part);
plate.ClampZones.Add(new ClampZone("left", new Box(4.6, 9.9, 0.3, 0.2)));
var findings = PostVerificationAnalyzer.Analyze(nest).Findings;
var finding = Assert.Single(findings, f => f.Kind == PostVerificationKind.FixedLead);
Assert.Equal("left", finding.ClampId);
Assert.Equal("Locked lead on cutting contour 1 touches active clamp 'left'. Planning kept it as given; "
+ "review it before posting.", finding.Message);
}
private static (Nest Nest, Plate Plate, Part Part) PinnedNest()
{
var nest = new Nest();
var plate = nest.CreatePlate();
var part = new Part(PinnedContourTests.SquareWithPin(Vector.Zero, PinnedContourTests.Corner()), new Vector(5, 5));
plate.Parts.Add(part);
return (nest, plate, part);
}
}