using ACadSharp; using ACadSharp.Entities; using ACadSharp.Tables; using CSMath; using Rozpisky.Dxf; using Rozpisky.Rendering; using Xunit; using AcColor = ACadSharp.Color; namespace Rozpisky.Tests; /// /// Entity, které dřív propadly switchem bez default větve, a tedy zmizely tiše: /// vložené bloky (INSERT), elipsy, body, vyplněné čtyřúhelníky. Uživatel si přidává vlastní /// loga, takže „nevykreslí se a nikdo se to nedozví" je nejhorší možné chování. /// public class EntityTesty { /// Přehraje dokument sestavený v paměti přes dočasný soubor (DxfTemplate čte ze souboru). private static (RecordingRenderer G, IReadOnlyDictionary Nezpracovane) Prehraj(CadDocument doc) { string cesta = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "rozpisky-entity-" + Guid.NewGuid().ToString("N") + ".dxf"); try { ACadSharp.IO.DxfWriter.Write(cesta, doc, binary: true); var tpl = new DxfTemplate(cesta); var g = new RecordingRenderer(); tpl.Replay(g); return (g, tpl.NezpracovaneEntity); } finally { try { System.IO.File.Delete(cesta); } catch (System.IO.IOException) { } } } /// Dokument s jedním blokem (čtvercová čára 0,0–10,10) a jeho vložením. private static CadDocument SBlokem(Action uprav, AcColor? barvaCary = null) { var doc = new CadDocument(); var blok = new BlockRecord("ctverec"); blok.Entities.Add(new Line(new XYZ(0, 0, 0), new XYZ(10, 0, 0)) { Color = barvaCary ?? AcColor.ByLayer, }); doc.BlockRecords.Add(blok); var ins = new Insert(blok); uprav(ins); doc.Entities.Add(ins); return doc; } [Fact] public void VsechnaDodavanaDataSeVykresliBezeZbytku() { // Šablona i všech 9 log musí projít beze zbytku – jinak se v nich něco nekreslí. var sablona = new DxfTemplate(TestData.Sablona); sablona.Replay(new RecordingRenderer(), values: null, includeNoPrint: true); Assert.Empty(sablona.NezpracovaneEntity); foreach (var logo in TestData.VsechnaLoga) { var tpl = new DxfTemplate(TestData.Logo(logo)); tpl.Replay(new RecordingRenderer()); Assert.True(tpl.NezpracovaneEntity.Count == 0, $"{logo}: nezpracované entity {string.Join(", ", tpl.NezpracovaneEntity.Select(p => $"{p.Key}×{p.Value}"))}"); } } [Fact] public void VlozenyBlokSeRozvineNaSpravnemMiste() { var (g, nezpracovane) = Prehraj(SBlokem(ins => ins.InsertPoint = new XYZ(100, 50, 0))); Assert.Empty(nezpracovane); Assert.Equal(1, g.LineCount); Assert.Equal((100, 50), g.Lines[0].Od); Assert.Equal((110, 50), g.Lines[0].Do); } [Fact] public void MeritkoANatoceniBlokuSeProjevi() { var (g, _) = Prehraj(SBlokem(ins => { ins.InsertPoint = new XYZ(0, 0, 0); ins.XScale = 2; ins.YScale = 2; ins.Rotation = Math.PI / 2; // 90° → úsečka z osy X na osu Y })); Assert.Equal(1, g.LineCount); var (od, doB) = g.Lines[0]; Assert.Equal(0, od.X, 6); Assert.Equal(0, od.Y, 6); Assert.Equal(0, doB.X, 6); Assert.Equal(20, doB.Y, 6); } [Fact] public void BarvaByBlockSeVezmeZVkladajiciEntity() { // Tohle je smysl ByBlock: stejný blok vložený dvakrát může mít pokaždé jinou barvu. var (g, _) = Prehraj(SBlokem( ins => { ins.InsertPoint = new XYZ(0, 0, 0); ins.Color = new AcColor(5); }, barvaCary: AcColor.ByBlock)); // Stavů jsou dva: jeden za samotný INSERT, druhý za úsečku uvnitř bloku – zajímá nás ten druhý. var stav = g.PosledniStav; Assert.Equal(BarvaDruh.Index, stav.Barva.Druh); Assert.Equal(5, stav.Barva.Index); } [Fact] public void ElipsaSeVykresliJakoLomenaCara() { var doc = new CadDocument(); doc.Entities.Add(new Ellipse { Center = new XYZ(0, 0, 0), MajorAxisEndPoint = new XYZ(10, 0, 0), RadiusRatio = 0.5, StartParameter = 0, EndParameter = 2 * Math.PI, }); var (g, nezpracovane) = Prehraj(doc); Assert.Empty(nezpracovane); var body = Assert.Single(g.Polylines); Assert.True(body.Count >= 8); // Body musí ležet na elipse s poloosami 10 a 5. foreach (var (x, y) in body) Assert.Equal(1.0, x * x / 100 + y * y / 25, 3); } [Fact] public void SolidSeVyplniVeSpravnemPoradiRohu() { // V DXF jsou 3. a 4. roh proti obvodu prohozené – při špatném pořadí vyjde přesýpací hodiny. var doc = new CadDocument(); doc.Entities.Add(new Solid { FirstCorner = new XYZ(0, 0, 0), SecondCorner = new XYZ(10, 0, 0), ThirdCorner = new XYZ(0, 10, 0), FourthCorner = new XYZ(10, 10, 0), }); var (g, nezpracovane) = Prehraj(doc); Assert.Empty(nezpracovane); var smycky = Assert.Single(g.Fills); var body = Assert.Single(smycky); Assert.Equal(new[] { (0.0, 0.0), (10.0, 0.0), (10.0, 10.0), (0.0, 10.0) }, body.Take(4).Select(p => (Math.Round(p.X, 6), Math.Round(p.Y, 6)))); } [Fact] public void NeznamaEntitaSeSpocitaMistoTichehoZahozeni() { var doc = new CadDocument(); doc.Entities.Add(new Ray { StartPoint = new XYZ(0, 0, 0), Direction = new XYZ(1, 0, 0) }); var (g, nezpracovane) = Prehraj(doc); Assert.Empty(g.Polylines); Assert.Equal(0, g.LineCount); Assert.Equal(1, nezpracovane.Values.Sum()); } [Fact] public void PocitadloSeMeziPruchodyNehromadi() { var doc = new CadDocument(); doc.Entities.Add(new Ray { StartPoint = new XYZ(0, 0, 0), Direction = new XYZ(1, 0, 0) }); string cesta = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "rozpisky-entity-" + Guid.NewGuid().ToString("N") + ".dxf"); try { ACadSharp.IO.DxfWriter.Write(cesta, doc, binary: true); var tpl = new DxfTemplate(cesta); tpl.Replay(new RecordingRenderer()); tpl.Replay(new RecordingRenderer()); Assert.Equal(1, tpl.NezpracovaneEntity.Values.Sum()); } finally { try { System.IO.File.Delete(cesta); } catch (System.IO.IOException) { } } } }