Files
Rozpisky/Rozpisky.Tests/HatchTesty.cs
T
marekandClaude Opus 5 a6377ab583 Baseline: současný stav projektu Rozpisky
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>
2026-09-07 09:45:49 +02:00

97 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)));
}
}