mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-06 19:15:44 -05:00
fix(report): keep IDs on neighboring part groups one spacing apart
Each dotted group outline was padded 1 pt beyond its parts. At overview scale a 0.25 in part spacing is only ~1.3 pt, so the outlines of two adjacent clusters (e.g. the six small bars and the two holed plates on N26-27Y plate 1) overlapped, and the later group - with its ID - was silently dropped. Pad outlines by under half the part spacing instead, so neighboring clusters both get their outline and ID. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a994bae76f
commit
fbe82d198a
4 files changed
+32
-3
No files matched your search
@@ -63,6 +63,9 @@ internal static class NestReportDiagram
|
||||
var groups = new List<DiagramGroup>();
|
||||
// A small screen-space gap also accommodates tightly packed parts with unset spacing.
|
||||
var gap = System.Math.Max(4, plate.PartSpacing * fit.Scale * 2);
|
||||
// Outlines stay under half the part spacing from their members, so the outlines of two
|
||||
// neighboring clusters (different IDs one spacing apart) never meet or overlap.
|
||||
var margin = plate.PartSpacing > 0 ? System.Math.Min(1, plate.PartSpacing * fit.Scale * 0.45) : 1;
|
||||
var remaining = failed.ToHashSet();
|
||||
foreach (var seed in failed)
|
||||
{
|
||||
@@ -90,7 +93,7 @@ internal static class NestReportDiagram
|
||||
var boundary = boxes[seed];
|
||||
foreach (var member in members.Skip(1))
|
||||
boundary.Union(boxes[member]);
|
||||
boundary.Inflate(1, 1);
|
||||
boundary.Inflate(margin, margin);
|
||||
var memberSet = members.ToHashSet();
|
||||
// A rectangular group must not imply that unrelated or ungrouped parts belong to it.
|
||||
if (!view.Contains(boundary)
|
||||
|
||||
@@ -256,6 +256,30 @@ public sealed class NestPdfLayoutTests : IDisposable
|
||||
Assert.False(plan.Groups[0].Boundary.IntersectsWith(plan.Groups[1].Boundary));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Plan_NeighboringClustersOfDifferentPartsOneSpacingApartAreBothGrouped()
|
||||
{
|
||||
// A second washer drawing (another ID) packed one part spacing to the right of the first
|
||||
// cluster: their outlines must not meet, or the second group and its ID were dropped.
|
||||
var nest = NestReportTestData.CreateDenseNest();
|
||||
var plate = nest.Plates[0];
|
||||
var other = new Drawing("Other washer", NestReportTestData.HoledSquare(1, 0.25));
|
||||
nest.Drawings.Add(other);
|
||||
var right = plate.Parts.Max(part => part.BoundingBox.Right);
|
||||
for (var row = 0; row < 4; row++)
|
||||
plate.Parts.Add(new Part(other, new Vector(right + plate.PartSpacing, 30 + row * 1.5)));
|
||||
var snapshot = NestReportBuilder.Capture(nest, NestReportTestData.GeneratedAt);
|
||||
|
||||
var plan = NestReportDiagram.Plan(snapshot.Plates[0], 720, 320);
|
||||
|
||||
Assert.Equal(2, plan.Groups.Count);
|
||||
Assert.Equal(["2", "3"], plan.Groups.Select(group => group.Label.Id).Order());
|
||||
Assert.False(plan.Groups[0].Boundary.IntersectsWith(plan.Groups[1].Boundary));
|
||||
foreach (var group in plan.Groups)
|
||||
Assert.All(group.Parts, index => Assert.True(group.Boundary.Contains(
|
||||
plan.Fit.Rect(snapshot.Plates[0].Parts[index].Geometry.Bounds))));
|
||||
}
|
||||
|
||||
[SkippableFact]
|
||||
public void Write_LabelOnHoledPartAvoidsTheHole()
|
||||
{
|
||||
|
||||
@@ -126,7 +126,7 @@ public static class NestReportTestData
|
||||
return drawing;
|
||||
}
|
||||
|
||||
private static Program HoledSquare(double size, double radius)
|
||||
internal static Program HoledSquare(double size, double radius)
|
||||
{
|
||||
var program = RectangleProgram(size, size);
|
||||
var center = size / 2;
|
||||
|
||||
@@ -93,7 +93,9 @@ and a part too small to label never prevents export. Every part remains in the
|
||||
quantity tables even when its diagram label cannot fit.
|
||||
|
||||
Nearby small parts with the same report ID may share a dotted rectangular outline
|
||||
and one ID beside it. Separate clusters get separate outlines. A group is omitted
|
||||
and one ID beside it. Separate clusters get separate outlines; an outline stays
|
||||
within half the part spacing of its parts, so clusters of different parts packed
|
||||
one spacing apart each keep their own outline and ID. A group is omitted
|
||||
if its rectangle includes any other part or cutoff, or if there is no clear space
|
||||
for its label. Clearance is tested against real contours, not bounding boxes, so a
|
||||
cluster nested in a larger part's cutout or notch is still grouped and labeled. Dotted group outlines are distinct from dashed scrap cutoffs.
|
||||
|
||||
Reference in new issue
Block a user