První commit — WPF aplikace pro generování výkresových rohových razítek (.NET 10, SkiaSharp, ACadSharp, ClosedXML) včetně xUnit testů, DXF šablony, log a dokumentace. Build výstupy (bin/, obj/, .vs/) jsou ignorovány. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
97 lines
4.0 KiB
C#
97 lines
4.0 KiB
C#
using Rozpisky.Dxf;
|
||
using Xunit;
|
||
|
||
namespace Rozpisky.Tests;
|
||
|
||
/// <summary>
|
||
/// Šrafy (HATCH) s hranovými hranicemi (úsečky, oblouky, elipsy) – dřív se tiše přeskočily,
|
||
/// takže tečky a oblé výplně v logách chyběly. Hodnoty jsou předpočítané ze skutečných DXF.
|
||
/// </summary>
|
||
public class HatchTesty
|
||
{
|
||
private static RecordingRenderer Prehraj(string logo)
|
||
{
|
||
var rec = new RecordingRenderer();
|
||
new DxfTemplate(TestData.Logo(logo)).Replay(rec);
|
||
return rec;
|
||
}
|
||
|
||
private static (double W, double H, double Cx, double Cy) Bbox(IReadOnlyList<(double X, double Y)> loop)
|
||
{
|
||
double ax = double.MaxValue, ay = double.MaxValue, bx = double.MinValue, by = double.MinValue;
|
||
foreach (var (x, y) in loop)
|
||
{
|
||
ax = Math.Min(ax, x); ay = Math.Min(ay, y);
|
||
bx = Math.Max(bx, x); by = Math.Max(by, y);
|
||
}
|
||
return (bx - ax, by - ay, (ax + bx) / 2, (ay + by) / 2);
|
||
}
|
||
|
||
[Fact]
|
||
public void Tesia_TeckaZKruhoveHrany_SeVyplni()
|
||
{
|
||
var rec = Prehraj("tesia.dxf");
|
||
// 2 SOLID hatche: obrys žárovky (polyline s bulge) + tečka (plná kruhová hrana r≈0,78).
|
||
var smycky = rec.Fills.SelectMany(f => f).ToList();
|
||
Assert.Equal(2, smycky.Count);
|
||
// Tečka = menší smyčka; průměr ≈ 1,56 mm (plný kruh z jediné obloukové hrany).
|
||
var tecka = smycky.OrderBy(l => Bbox(l).W).First();
|
||
var (w, h, _, _) = Bbox(tecka);
|
||
Assert.InRange(w, 1.50, 1.62);
|
||
Assert.InRange(h, 1.50, 1.62);
|
||
}
|
||
|
||
[Fact]
|
||
public void SudopBrno_MichaneUseckoveAObloukoveHrany_DajiUzavreneSmycky()
|
||
{
|
||
var rec = Prehraj("sudopBrno.dxf");
|
||
// 6 SOLID šraf, všechny jen s hranovými cestami (úsečky + oblouky) → dřív 0 výplní.
|
||
// Referenční bboxy spočtené nezávisle hustým vzorkováním raw dat hran (512 dílků/oblouk).
|
||
Assert.Equal(6, rec.Fills.Count);
|
||
var smycky = rec.Fills.SelectMany(f => f).ToList();
|
||
Assert.Equal(7, smycky.Count); // jeden hatch má 2 cesty, ostatní po jedné
|
||
Assert.All(smycky, l => Assert.True(l.Count >= 3));
|
||
|
||
// Nezávisle na pořadí (draw order přes SortEntitiesTable může hatche přeuspořádat) ověříme,
|
||
// že existují smyčky s referenčními bboxy – včetně plné kružnice r=3,825 (7,649²) z jediné
|
||
// obloukové hrany a řetězů úsečka+oblouk vč. ccw=false (zrcadlené úhly). Chybné znaménko/
|
||
// otočení hrany nebo ztracená kružnice by referenci znatelně změnily.
|
||
MaSmyckuBbox(smycky, 7.649, 7.649);
|
||
MaSmyckuBbox(smycky, 5.571, 0.626);
|
||
MaSmyckuBbox(smycky, 2.092, 0.066);
|
||
MaSmyckuBbox(smycky, 7.807, 1.085);
|
||
MaSmyckuBbox(smycky, 11.290, 1.733);
|
||
}
|
||
|
||
private static void MaSmyckuBbox(IReadOnlyList<IReadOnlyList<(double X, double Y)>> smycky, double refW, double refH)
|
||
=> Assert.Contains(smycky, l =>
|
||
{
|
||
var (w, h, _, _) = Bbox(l);
|
||
return w >= refW - 0.1 && w <= refW + 0.02 && h >= refH - 0.1 && h <= refH + 0.02;
|
||
});
|
||
|
||
[Fact]
|
||
public void Signalprojekt_KruhovaAEliptickaHrana_SeVyplni()
|
||
{
|
||
var rec = Prehraj("signalprojekt.dxf");
|
||
Assert.Equal(2, rec.Fills.Count);
|
||
var smycky = rec.Fills.SelectMany(f => f).ToList();
|
||
// Eliptická cesta: poloosy 1,16 a 0,759·1,16 → bbox ≈ 1,76 × 2,32 (hlavní osa svisle).
|
||
Assert.Contains(smycky, l =>
|
||
{
|
||
var (w, h, _, _) = Bbox(l);
|
||
double lo = Math.Min(w, h), hi = Math.Max(w, h);
|
||
return Math.Abs(hi - 2.32) < 0.05 && Math.Abs(lo - 1.76) < 0.05;
|
||
});
|
||
}
|
||
|
||
[Fact]
|
||
public void PolylinioveHranice_BezRegrese()
|
||
{
|
||
// exprojekt: 3 SOLID šrafy čistě s polyline hranicemi – musí zůstat beze změny.
|
||
var rec = Prehraj("exprojekt.dxf");
|
||
Assert.Equal(3, rec.Fills.Count);
|
||
Assert.All(rec.Fills, f => Assert.All(f, l => Assert.True(l.Count >= 3)));
|
||
}
|
||
}
|