Files
OpenNest/OpenNest.Tests/IO/TitleBlockDetectorTests.cs
T

246 lines
8.6 KiB
C#

using System.Collections.Generic;
using CSMath;
using OpenNest.Geometry;
using OpenNest.IO;
using Xunit;
namespace OpenNest.Tests.IO
{
public class TitleBlockDetectorTests
{
private static Line MakeLine(double x1, double y1, double x2, double y2) =>
new Line(x1, y1, x2, y2);
[Fact]
public void DetectByLayerName_FlagsTitleLayer()
{
var line = MakeLine(0, 0, 10, 0);
line.Layer = new Layer("TITLE");
var entities = new List<Entity> { line };
var result = TitleBlockDetector.Detect(entities, null);
Assert.Contains(line.Id, result);
}
[Fact]
public void DetectByLayerName_CaseInsensitive()
{
var line = MakeLine(0, 0, 10, 0);
line.Layer = new Layer("border");
var entities = new List<Entity> { line };
var result = TitleBlockDetector.Detect(entities, null);
Assert.Contains(line.Id, result);
}
[Fact]
public void DetectByLayerName_IgnoresNonMatchingLayers()
{
var line = MakeLine(0, 0, 10, 0);
line.Layer = new Layer("0");
var entities = new List<Entity> { line };
var result = TitleBlockDetector.Detect(entities, null);
Assert.DoesNotContain(line.Id, result);
}
[Theory]
[InlineData("TITLE")]
[InlineData("TITLEBLOCK")]
[InlineData("TITLE_BLOCK")]
[InlineData("BORDER")]
[InlineData("FRAME")]
[InlineData("TB")]
[InlineData("INFO")]
[InlineData("SHEET")]
[InlineData("ANNOTATION")]
public void DetectByLayerName_AllKnownNames(string layerName)
{
var line = MakeLine(0, 0, 10, 0);
line.Layer = new Layer(layerName);
var entities = new List<Entity> { line };
var result = TitleBlockDetector.Detect(entities, null);
Assert.Contains(line.Id, result);
}
[Fact]
public void DetectBorder_FlagsLinesOnBoundingBoxEdges()
{
var entities = new List<Entity>
{
new Line(0, 0, 86, 0) { Layer = new Layer("0") },
new Line(86, 0, 86, 134) { Layer = new Layer("0") },
new Line(86, 134, 0, 134) { Layer = new Layer("0") },
new Line(0, 134, 0, 0) { Layer = new Layer("0") },
new Line(30, 40, 50, 90) { Layer = new Layer("0") },
new Line(50, 90, 70, 40) { Layer = new Layer("0") },
new Line(70, 40, 30, 40) { Layer = new Layer("0") },
};
var result = TitleBlockDetector.Detect(entities, null);
Assert.Contains(entities[0].Id, result);
Assert.Contains(entities[1].Id, result);
Assert.Contains(entities[2].Id, result);
Assert.Contains(entities[3].Id, result);
Assert.DoesNotContain(entities[4].Id, result);
Assert.DoesNotContain(entities[5].Id, result);
Assert.DoesNotContain(entities[6].Id, result);
}
[Fact]
public void DetectBorder_FlagsZoneMarkerTicks()
{
var entities = new List<Entity>
{
new Line(0, 0, 100, 0) { Layer = new Layer("0") },
new Line(100, 0, 100, 80) { Layer = new Layer("0") },
new Line(100, 80, 0, 80) { Layer = new Layer("0") },
new Line(0, 80, 0, 0) { Layer = new Layer("0") },
new Line(25, 80, 25, 77) { Layer = new Layer("0") },
new Line(50, 80, 50, 77) { Layer = new Layer("0") },
new Line(75, 80, 75, 77) { Layer = new Layer("0") },
new Line(40, 30, 60, 30) { Layer = new Layer("0") },
};
var result = TitleBlockDetector.Detect(entities, null);
Assert.Contains(entities[4].Id, result);
Assert.Contains(entities[5].Id, result);
Assert.Contains(entities[6].Id, result);
Assert.DoesNotContain(entities[7].Id, result);
}
[Fact]
public void DetectBorder_IgnoresWhenNoBorderPresent()
{
var entities = new List<Entity>
{
new Line(30, 40, 50, 90) { Layer = new Layer("0") },
new Line(50, 90, 70, 40) { Layer = new Layer("0") },
new Line(70, 40, 30, 40) { Layer = new Layer("0") },
};
var result = TitleBlockDetector.Detect(entities, null);
Assert.Empty(result);
}
[Fact]
public void DetectBorder_ToleratesSlightRotation()
{
var angleRad = OpenNest.Math.Angle.ToRadians(0.5);
var endY = 86 * System.Math.Sin(angleRad);
var entities = new List<Entity>
{
new Line(0, 0, 86, endY) { Layer = new Layer("0") },
new Line(86, endY, 86, 134) { Layer = new Layer("0") },
new Line(86, 134, 0, 134) { Layer = new Layer("0") },
new Line(0, 134, 0, 0) { Layer = new Layer("0") },
new Line(30, 40, 50, 90) { Layer = new Layer("0") },
};
var result = TitleBlockDetector.Detect(entities, null);
Assert.Contains(entities[0].Id, result);
}
[Fact]
public void DetectTitleBlock_FlagsEntitiesInTextDenseCorner()
{
var partLine1 = new Line(5, 70, 25, 120) { Layer = new Layer("0") };
var partLine2 = new Line(25, 120, 45, 70) { Layer = new Layer("0") };
var partLine3 = new Line(45, 70, 5, 70) { Layer = new Layer("0") };
var tbLines = new List<Entity>();
for (var x = 50; x <= 85; x += 5)
tbLines.Add(new Line(x, 0, x, 30) { Layer = new Layer("0") });
for (var y = 0; y <= 30; y += 5)
tbLines.Add(new Line(50, y, 85, y) { Layer = new Layer("0") });
var entities = new List<Entity> { partLine1, partLine2, partLine3 };
entities.AddRange(tbLines);
var doc = BuildDocWithTexts(
(60, 5, "TITLE: Test Part"),
(60, 10, "DWG NO: 12345"),
(60, 15, "SCALE: 1:1"),
(60, 20, "REV: A"),
(60, 25, "MATERIAL: STEEL"));
var result = TitleBlockDetector.Detect(entities, doc);
foreach (var tb in tbLines)
Assert.Contains(tb.Id, result);
Assert.DoesNotContain(partLine1.Id, result);
Assert.DoesNotContain(partLine2.Id, result);
Assert.DoesNotContain(partLine3.Id, result);
}
[Fact]
public void DetectTitleBlock_NoFalsePositivesWithoutText()
{
var entities = new List<Entity>
{
new Line(30, 40, 50, 90) { Layer = new Layer("0") },
new Line(50, 90, 70, 40) { Layer = new Layer("0") },
new Line(70, 40, 30, 40) { Layer = new Layer("0") },
};
var result = TitleBlockDetector.Detect(entities, null);
Assert.Empty(result);
}
[Fact]
public void DetectTitleBlock_BottomEdgeStrip()
{
var partLine = new Line(20, 40, 80, 40) { Layer = new Layer("0") };
var tbLines = new List<Entity>();
for (var x = 0; x <= 100; x += 10)
tbLines.Add(new Line(x, 0, x, 20) { Layer = new Layer("0") });
for (var y = 0; y <= 20; y += 5)
tbLines.Add(new Line(0, y, 100, y) { Layer = new Layer("0") });
var entities = new List<Entity> { partLine };
entities.AddRange(tbLines);
var doc = BuildDocWithTexts(
(10, 5, "TITLE"),
(30, 5, "DWG NO"),
(50, 5, "SCALE"),
(70, 5, "REV"),
(90, 5, "DATE"));
var result = TitleBlockDetector.Detect(entities, doc);
foreach (var tb in tbLines)
Assert.Contains(tb.Id, result);
Assert.DoesNotContain(partLine.Id, result);
}
private static ACadSharp.CadDocument BuildDocWithTexts(
params (double x, double y, string value)[] texts)
{
var doc = new ACadSharp.CadDocument();
foreach (var (x, y, value) in texts)
{
var mtext = new ACadSharp.Entities.MText
{
InsertPoint = new XYZ(x, y, 0),
Value = value,
Height = 2.0
};
doc.Entities.Add(mtext);
}
return doc;
}
}
}