Files
OpenNest/OpenNest.WinForms.Tests/Forms/NestReviewFormTests.cs
T
ajandClaude Opus 5.5 cd2bea054b feat(desktop): show Auto Nest as a sheet strip with a Keep/Discard review
Auto Nest no longer draws parts on the plate view before they are kept:
its result is a set of sheets, possibly of several sizes, not parts on the
current plate. Ghost parts stay with interactive Fill and remnant tools.

- NestJobStage.PlanImproved carries an engine's best whole-job plan so far;
  Irregular reports one whenever a variant or the tail re-plan beats it.
- NestPipeline adds PlanSheets: the plan on detached drawings built from
  the job geometry (with the caller's names and colors), so previews never
  touch caller drawings or quantities.
- SheetStripControl draws every sheet side by side at one scale, repeats
  once with their count, captioned with size, parts and utilization.
- The progress window shows "Best plan so far"; a review window shows the
  final sheets, totals, cost summary and unplaced parts before commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 23:56:38 -04:00

71 lines
2.8 KiB
C#

using OpenNest.Engine;
using OpenNest.Engine.Jobs;
using OpenNest.Forms;
using OpenNest.Geometry;
namespace OpenNest.WinForms.Tests.Forms;
public class NestReviewFormTests
{
[Fact]
public void ShowsTheSheetsAndNamesUnplacedPartsWithoutTouchingQuantities() => StaTestThread.Run(() =>
{
var item = new NestItem { Drawing = new Drawing("bracket", Rectangle()), Quantity = 3 };
var stock = new NestPlateStock("sheet", new Size(48, 96), quantity: null, partSpacing: 0.25);
var engine = new StubEngine(job => new NestJobResult(
NestJobStatus.Incomplete,
NestJobStopReason.NoPlacementFound,
new[]
{
new NestJobPlateResult(0, job.Plates[0], new[]
{
new NestJobPlacement(job.Parts[0].Id, 0, 1, 1, 0),
new NestJobPlacement(job.Parts[0].Id, 1, 20, 1, 0),
}),
},
new[] { new PartFulfillment(job.Parts[0].Id, 3, 2, 1) },
new[] { new StockUsage(job.Plates[0].Id, 1, null) }));
var result = NestPipeline.Run(engine, "Stub", new NestPipelineRequest("Stub", new[] { item }, new[] { stock }));
using var form = new NestReviewForm(result, ColorScheme.Default);
Assert.Equal(1, form.Strip.SheetCount);
Assert.Equal(2, form.Strip.PartCount);
// Two 10 x 20 parts on a 48 x 96 sheet.
Assert.Equal(400.0 / (48 * 96), form.Strip.Utilization, 6);
Assert.Contains("bracket: 1 not placed", form.Summary);
Assert.Equal(0, item.Drawing.Quantity.Nested);
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
[Fact]
public void RepeatedSheetsCountEveryPhysicalCopy() => StaTestThread.Run(() =>
{
var drawing = new Drawing("bracket", Rectangle());
var stock = new NestPlateStock("sheet", new Size(48, 96), quantity: null, partSpacing: 0.25);
var part = new Part(drawing, new Vector(1, 1));
using var strip = new OpenNest.Controls.SheetStripControl();
strip.SetSheets(new[] { new ProposedPlate(0, stock, new[] { part }) { Quantity = 3 } });
Assert.Equal(3, strip.SheetCount);
Assert.Equal(3, strip.PartCount);
}, TimeSpan.FromMinutes(1), "The STA test did not complete.");
private sealed class StubEngine(Func<NestJob, NestJobResult> solve) : INestingEngine
{
public NestJobResult Solve(NestJob job, IProgress<NestJobProgress> progress = null,
CancellationToken token = default) => solve(job);
}
private static CNC.Program Rectangle()
{
var program = new CNC.Program();
program.MoveTo(0, 0);
program.LineTo(10, 0);
program.LineTo(10, 20);
program.LineTo(0, 20);
program.LineTo(0, 0);
return program;
}
}