using System.IO;
using ACadSharp.Entities;
using ACadSharp.IO;
using Rozpisky.Dxf;
using Rozpisky.Rendering;
using Xunit;
namespace Rozpisky.Tests;
///
/// Šrafa v exportovaném DXF. Vzor musí jít ven i s definičními čarami – DXF je nese uvnitř
/// entity HATCH, a bez nich si ho cílový CAD dosadí ze svých .pat, ve svých
/// jednotkách a měřítku. Pak vypadá v každém výkresu jinak a většinou tak hustě, že to ani
/// nevypadá jako šrafa. A protože se logo do rámečku zmenšuje, musí se s ním zmenšit i vzor.
///
public class SrafaExportTesty : IDisposable
{
private readonly string _soubor = Path.Combine(Path.GetTempPath(), "rozpisky-srafa-" + Guid.NewGuid().ToString("N") + ".dxf");
public void Dispose()
{
try { File.Delete(_soubor); } catch (IOException) { }
GC.SuppressFinalize(this);
}
/// Přehraje logo do DXF (volitelně přes zmenšení do rámečku) a načte výsledek zpět.
private List Kolecko(double meritko)
{
var dxf = new DxfProfileRenderer();
IProfileRenderer cil = meritko == 1 ? dxf : new TransformRenderer(dxf, meritko, 0, 0);
new DxfTemplate(TestData.Logo("md_sfdi.dxf")).Replay(cil);
DxfWriter.Write(_soubor, dxf.Document, binary: true);
return DxfReader.Read(_soubor).Entities.OfType().ToList();
}
/// Rozteč rovnoběžek vzoru = kolmá složka posunu mezi sousedními čarami.
private static double Roztec(HatchPattern.Line cara)
{
double nx = -Math.Sin(cara.Angle), ny = Math.Cos(cara.Angle);
return Math.Abs(cara.Offset.X * nx + cara.Offset.Y * ny);
}
private static double RoztecZdroje()
{
var zdroj = DxfReader.Read(TestData.Logo("md_sfdi.dxf"))
.Entities.OfType().First(h => !h.IsSolid);
return Roztec(zdroj.Pattern!.Lines[0]);
}
[Fact]
public void ExportovanaSrafaNeseDefiniciVzoru()
{
var srafy = Kolecko(meritko: 1).Where(h => !h.IsSolid).ToList();
Assert.NotEmpty(srafy);
foreach (var h in srafy)
{
Assert.Equal("ANSI31", h.Pattern?.Name);
Assert.NotNull(h.Pattern);
Assert.NotEmpty(h.Pattern!.Lines); // tohle chybělo: vzor šel ven jen jménem
}
}
[Fact]
public void RoztecVzoruOdpovidaZdroji()
{
var srafa = Kolecko(meritko: 1).First(h => !h.IsSolid);
Assert.Equal(RoztecZdroje(), Roztec(srafa.Pattern!.Lines[0]), 9);
}
[Fact]
public void ZmensenimLogaSeZmensiIVzor()
{
// Logo se do rámečku rozpisky vejde jen zmenšené. Kdyby si vzor nechal původní rozteč,
// vyšla by v CADu buď plná plocha, nebo pár čar přes celé logo.
const double meritko = 0.1;
var srafa = Kolecko(meritko).First(h => !h.IsSolid);
Assert.Equal(RoztecZdroje() * meritko, Roztec(srafa.Pattern!.Lines[0]), 9);
}
[Fact]
public void MeritkoAUhelZustavajiNeutralni()
{
// ACadSharp při zápisu násobí rozteč vzoru hodnotou PatternScale, ale při čtení zpátky
// nedělí – s nenulovým měřítkem by se vzor s každým kolečkem roztáhl. Efektivní hodnoty
// proto nese samotná definice a měřítko s úhlem zůstávají neutrální.
var srafa = Kolecko(meritko: 1).First(h => !h.IsSolid);
Assert.Equal(1, srafa.PatternScale, 9);
Assert.Equal(0, srafa.PatternAngle, 9);
}
[Fact]
public void PlnaVyplnZustavaSolidBezVzoru()
{
// md_sfdi má všechny šrafy vzorované, plné výplně jsou v ostatních logách.
var dxf = new DxfProfileRenderer();
new DxfTemplate(TestData.Logo("exprojekt.dxf")).Replay(dxf);
DxfWriter.Write(_soubor, dxf.Document, binary: true);
var solidni = DxfReader.Read(_soubor).Entities.OfType().ToList();
Assert.NotEmpty(solidni);
foreach (var h in solidni)
{
Assert.True(h.IsSolid);
Assert.Equal("SOLID", h.Pattern?.Name);
Assert.Empty(h.Pattern!.Lines);
}
}
}