feat(io): add title block region detection with corner/edge scoring (phase 3)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using CSMath;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.IO;
|
||||
using Xunit;
|
||||
@@ -148,5 +149,97 @@ namespace OpenNest.Tests.IO
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user