Files
OpenNest/OpenNest.WinForms.Tests/Controls/CutOffSegmentLabelTests.cs
T
ajandClaude Opus 5.5 0ba5539fab fix(display): keep cut-off lines from striking through segment ids
Cut-off lines are painted after the parts, so the dashed line ran straight
through each segment's id, which sits on the cut. Cut-off segment ids are now
held back from the parts pass and drawn after the lines, over a disc of the
plate's fill color.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 09:46:43 -04:00

100 lines
4.2 KiB
C#

using System.Drawing;
using System.Drawing.Drawing2D;
using OpenNest.Controls;
using OpenNest.Geometry;
namespace OpenNest.WinForms.Tests.Controls;
/// <summary>
/// Each segment of a cut-off is its own part of the one cut-off drawing. Its sequence label must
/// sit on its own cut: labelled from the whole drawing, every segment stacked its number on one
/// point, and the view's culling decided which one showed as the user zoomed.
/// </summary>
public class CutOffSegmentLabelTests
{
[Fact]
public void EachSegmentIsLabelledAtTheMiddleOfItsOwnCut() => StaTestThread.Run(() =>
{
using var view = new PlateView(ColorSchemeRegistry.Get("Workshop"));
view.Matrix = new Matrix();
view.Plate.Size = new OpenNest.Geometry.Size(100, 100);
view.Plate.Quadrant = 1;
view.Plate.Parts.Add(new Part(new Drawing("Block", Square(20)), new Vector(40, 40)));
view.Plate.CutOffs.Add(new CutOff(new Vector(50, 0), CutOffAxis.Vertical));
view.Plate.RegenerateCutOffs(new CutOffSettings());
var segments = view.Plate.Parts.Where(p => p.BaseDrawing.IsCutOff).ToList();
Assert.Equal(2, segments.Count);
var labels = new List<float>();
foreach (var segment in segments)
{
var layout = LayoutPart.Create(segment, view);
var extent = CutOffSegments.Extent(segment, vertical: true)!.Value;
Assert.Equal(50, layout.LabelScreenPoint.X, 3);
Assert.Equal((extent.Start + extent.End) / 2, layout.LabelScreenPoint.Y, 3);
labels.Add(layout.LabelScreenPoint.Y);
layout.ReleaseDisplayResources();
}
Assert.NotEqual(labels[0], labels[1]);
}, TimeSpan.FromMinutes(1), "Cut-off segment label test timed out.");
[Fact]
public void CutLineDoesNotStrikeThroughASegmentsId() => StaTestThread.Run(() =>
{
// A quadrant-4 sheet under a Y-flipping matrix lands parts and cut-off lines on the same
// pixels: the cut-off at x=50 runs down graph column 50, rows 0..100, painted from the
// view's origin as OnPaint does so the culling sees the whole sheet.
using var view = new PlateView(ColorSchemeRegistry.Get("Workshop")) { Size = new System.Drawing.Size(240, 240) };
view.Matrix = new Matrix(1, 0, 0, -1, 0, 0);
view.Plate.Size = new OpenNest.Geometry.Size(100, 100);
view.Plate.Quadrant = 4;
view.Plate.Parts.Add(new Part(new Drawing("Block", Square(20)), new Vector(40, -60)));
view.Plate.CutOffs.Add(new CutOff(new Vector(50, 0), CutOffAxis.Vertical));
view.Plate.RegenerateCutOffs(new CutOffSettings());
var viewBounds = view.GetViewBounds();
var (dx, dy) = ((int)-viewBounds.X, (int)-viewBounds.Y);
using var image = new Bitmap(view.Width, view.Height);
using var g = Graphics.FromImage(image);
g.Clear(Color.White);
g.TranslateTransform(dx, dy);
view.Renderer.DrawParts(g);
view.Renderer.DrawCutOffs(g);
var labels = view.LayoutParts.Where(p => p.BasePart.BaseDrawing.IsCutOff)
.Select(p => Point.Round(p.LabelScreenPoint) + new System.Drawing.Size(dx, dy)).ToList();
Assert.Equal(2, labels.Count);
Assert.True(CountOrange(image, dx + 48, dx + 52, dy, dy + 99) >= 10, "Expected the cut-off line outside its ids.");
foreach (var label in labels)
Assert.Equal(0, CountOrange(image, label.X - 2, label.X + 2, label.Y - 4, label.Y + 4));
}, TimeSpan.FromMinutes(1), "Cut-off segment id background test timed out.");
private static int CountOrange(Bitmap image, int left, int right, int top, int bottom)
{
var count = 0;
for (var y = top; y <= bottom; y++)
{
for (var x = left; x <= right; x++)
{
var c = image.GetPixel(x, y);
if (c.R >= 200 && c.G <= 120 && c.B <= 80)
count++;
}
}
return count;
}
private static OpenNest.CNC.Program Square(double size)
{
var program = new OpenNest.CNC.Program();
program.MoveTo(0, 0);
program.LineTo(size, 0);
program.LineTo(size, size);
program.LineTo(0, size);
program.LineTo(0, 0);
return program;
}
}