mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-21 07:51:36 -04:00
feat(desktop): draw cut-off lines as a prominent orange-red dash
Cut-off scrap lines were a solid 1.5px near-black stroke that read like another sheet/part outline. They now render as a 2px orange-red dash so operators can spot scrap cuts at a glance, and the manual cut-off preview is recolored to match the applied line. Selected cut-offs keep their solid blue highlight. Add bitmap regression tests (CutOffDisplayTests) that verify the dashed orange style, the dashed gaps, and the unchanged selection highlight.
This commit is contained in:
1 parent
74f32f0516
commit
1d745d20ba
3 files changed
+107
-2
No files matched your search
@@ -0,0 +1,98 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using OpenNest.Controls;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.WinForms.Tests;
|
||||
|
||||
public class CutOffDisplayTests
|
||||
{
|
||||
private static readonly Color OldLineGray = Color.FromArgb(64, 64, 64);
|
||||
private static readonly Color CutoffLine = Color.OrangeRed;
|
||||
private static readonly Color SelectedBlue = Color.FromArgb(0, 120, 255);
|
||||
|
||||
// A 100x100 quadrant-4 sheet puts a vertical cut-off at x=50 on the
|
||||
// graph column x=50, rows 0..100 (PointWorldToGraph flips Y).
|
||||
private static (PlateView View, CutOff Cutoff) BuildPlateWithCutOff()
|
||||
{
|
||||
var view = new PlateView(ColorSchemeRegistry.Get("Workshop"))
|
||||
{
|
||||
Size = new System.Drawing.Size(100, 100),
|
||||
};
|
||||
view.Matrix = new Matrix();
|
||||
view.Plate.Size = new OpenNest.Geometry.Size(100, 100);
|
||||
view.Plate.Quadrant = 4;
|
||||
var cutoff = new CutOff(new Vector(50, 0), CutOffAxis.Vertical);
|
||||
view.Plate.CutOffs.Add(cutoff);
|
||||
view.Plate.RegenerateCutOffs(new CutOffSettings());
|
||||
return (view, cutoff);
|
||||
}
|
||||
|
||||
private static (int Orange, int White, int OldGray, int Blue) CountLinePixels(Bitmap image)
|
||||
{
|
||||
var orange = 0;
|
||||
var white = 0;
|
||||
var oldGray = 0;
|
||||
var blue = 0;
|
||||
|
||||
for (var y = 3; y <= 96; y++)
|
||||
{
|
||||
for (var x = 48; x <= 52; x++)
|
||||
{
|
||||
var c = image.GetPixel(x, y);
|
||||
|
||||
if (c.R >= 200 && c.G <= 120 && c.B <= 80)
|
||||
orange++;
|
||||
else if (c.R >= 240 && c.G >= 240 && c.B >= 240)
|
||||
white++;
|
||||
else if (
|
||||
System.Math.Abs(c.R - OldLineGray.R) <= 32
|
||||
&& System.Math.Abs(c.G - OldLineGray.G) <= 32
|
||||
&& System.Math.Abs(c.B - OldLineGray.B) <= 32
|
||||
)
|
||||
oldGray++;
|
||||
else if (c.B >= 200 && c.R <= 60)
|
||||
blue++;
|
||||
}
|
||||
}
|
||||
|
||||
return (orange, white, oldGray, blue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CutOffLineIsDashedOrangeNotSolidBlack() => StaTestThread.Run(() =>
|
||||
{
|
||||
var (view, _) = BuildPlateWithCutOff();
|
||||
using (view)
|
||||
using (var image = new Bitmap(100, 100))
|
||||
using (var g = Graphics.FromImage(image))
|
||||
{
|
||||
g.Clear(Color.White);
|
||||
view.Renderer.DrawCutOffs(g);
|
||||
|
||||
var (orange, white, oldGray, _) = CountLinePixels(image);
|
||||
Assert.True(orange >= 10, $"Expected the orange cut-off dash, found {orange} pixels.");
|
||||
Assert.True(white >= 10, $"Expected dashed gaps along the cut-off line, found {white} white pixels.");
|
||||
Assert.Equal(0, oldGray);
|
||||
}
|
||||
}, TimeSpan.FromMinutes(1), "Cut-off display test timed out.");
|
||||
|
||||
[Fact]
|
||||
public void SelectedCutOffKeepsSolidBlueHighlight() => StaTestThread.Run(() =>
|
||||
{
|
||||
var (view, cutoff) = BuildPlateWithCutOff();
|
||||
using (view)
|
||||
{
|
||||
view.Selection.SelectedCutOffs.Add(cutoff);
|
||||
using var image = new Bitmap(100, 100);
|
||||
using var g = Graphics.FromImage(image);
|
||||
g.Clear(Color.White);
|
||||
view.Renderer.DrawCutOffs(g);
|
||||
|
||||
var (orange, _, oldGray, blue) = CountLinePixels(image);
|
||||
Assert.True(blue >= 20, $"Expected the solid blue selection line, found {blue} pixels.");
|
||||
Assert.Equal(0, orange);
|
||||
Assert.Equal(0, oldGray);
|
||||
}
|
||||
}, TimeSpan.FromMinutes(1), "Selected cut-off display test timed out.");
|
||||
}
|
||||
@@ -100,7 +100,10 @@ namespace OpenNest.Actions
|
||||
if (program.Codes.Count == 0)
|
||||
return;
|
||||
|
||||
using var pen = new Pen(Color.FromArgb(128, 64, 64, 64), 1.5f / plateView.ViewScale)
|
||||
// Match the applied cut-off line's look (orange-red dash) so the
|
||||
// preview is exactly what the click produces; the alpha keeps it
|
||||
// reading as a preview.
|
||||
using var pen = new Pen(Color.FromArgb(128, 255, 69, 0), 1.5f / plateView.ViewScale)
|
||||
{
|
||||
DashStyle = DashStyle.Dash,
|
||||
};
|
||||
|
||||
@@ -242,13 +242,17 @@ namespace OpenNest.Controls
|
||||
}
|
||||
}
|
||||
|
||||
// Scrap cut-off lines must stand out from the dark part outlines and the
|
||||
// sheet: a saturated orange-red dash, not another solid near-black line.
|
||||
private static readonly Color CutOffLineColor = Color.OrangeRed;
|
||||
|
||||
public void DrawCutOffs(Graphics g)
|
||||
{
|
||||
var plate = view.DisplayPlate;
|
||||
if (plate?.CutOffs == null || plate.CutOffs.Count == 0)
|
||||
return;
|
||||
|
||||
using var pen = new Pen(Color.FromArgb(64, 64, 64), 1.5f);
|
||||
using var pen = new Pen(CutOffLineColor, 2.0f) { DashStyle = DashStyle.Dash };
|
||||
using var selectedPen = new Pen(Color.FromArgb(0, 120, 255), 3.5f);
|
||||
|
||||
foreach (var cutoff in plate.CutOffs)
|
||||
|
||||
Reference in new issue
Block a user