fix(qwen38flashnext): number plates in commit order and drop etch marks

BuildResult set PlateIndex to the stock index, so every sheet cut from
the same stock shared one index; OpenNest.Api maps plates by it.

Part geometry filtered only rapids, so scribe/etch moves counted as
material - the bug OpenNest fixed in 1b5e1b1. Use SpecialLayers.IsMaterial.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
aj
2026-09-25 07:45:13 -04:00
co-authored by Claude Opus 5.5
parent 1579fa6810
commit 54e8a0461b
3 changed files with 33 additions and 2 deletions
@@ -405,7 +405,7 @@ internal sealed class JobSolver
);
}
plates.Add(
new NestJobPlateResult(sheet.StockIndex, _job.Plates[sheet.StockIndex], placements)
new NestJobPlateResult(plates.Count, _job.Plates[sheet.StockIndex], placements)
);
}
@@ -78,7 +78,7 @@ internal sealed class PartModel
DrawingJobMapper.ToProgram(part.Geometry)
)
)
if (!ReferenceEquals(entity.Layer, SpecialLayers.Rapid))
if (SpecialLayers.IsMaterial(entity.Layer))
entities.Add(entity);
if (entities.Count == 0)
return null;
@@ -107,6 +107,37 @@ public class Qwen38FlashNextNestingEngineTests
Assert.Equal(1, huge.Unplaced);
}
[Fact]
public void EtchMarksAreLeftOutOfNestingGeometry()
{
// A bend tick starts on material and ends 1.0 into a side notch, outside the part but
// inside its bounding box (the PEP case that crashed nesting before 1b5e1b1). As
// material it is open geometry leaving the part; as a mark it must be ignored.
var etched = Polyline((0, 0), (10, 0), (10, 4), (8, 4), (8, 6), (10, 6), (10, 10), (0, 10));
etched.Codes.Add(new RapidMove(7.5, 5));
etched.Codes.Add(new LinearMove(9, 5) { Layer = LayerType.Scribe });
var job = Job(new[] { Part("part", etched, 2, RotationPolicy.Fixed(0)) }, new[] { Stock("sheet", 10.4, 20.6, spacing: 0.2) });
var result = new Qwen38FlashNextNestingEngine().Solve(job);
AssertValid(job, result);
Assert.Equal(NestJobStatus.Complete, result.Status);
Assert.Equal(2, Assert.Single(result.Plates).Placements.Count);
}
[Fact]
public void PlateIndicesRunInCommitOrder()
{
// Every sheet comes from the same stock (index 0), so the stock index must not leak
// into PlateIndex: the host and OpenNest.Api treat it as the sheet's position.
var job = Job(new[] { Part("square", Rectangle(10, 10), 30) }, new[] { Stock("sheet", 25, 45, spacing: 0.25) });
var result = new Qwen38FlashNextNestingEngine().Solve(job);
Assert.True(result.Plates.Count > 1);
Assert.Equal(Enumerable.Range(0, result.Plates.Count), result.Plates.Select(p => p.PlateIndex));
}
// ---- helpers -------------------------------------------------------------------------
private static void AssertValid(NestJob job, NestJobResult result)