Files
Rozpisky/Rozpisky.Tests/RecordingRenderer.cs
T
marekandClaude Opus 5 a900acc7bb Entity: rozvinout bloky, doplnit elipsy a hlásit, co program neumí
Switch v Replay neměl default větev: INSERT, ELLIPSE, POINT, SOLID, 3DFACE
a POLYLINE3D propadly bez akce a bez záznamu. V dodávaných souborech žádná
z nich není, ale uživatel si přidává vlastní loga – to nejhorší, co se mu může
stát, je logo, které se nevykreslí a nikdo mu to neřekne.

- INSERT se rozvine rekurzivně (vztažný bod, měřítko os, natočení), s ochranou
  proti bloku vkládajícímu sám sebe. Uvnitř bloku se hladina „0" a barva
  ByBlock berou od vkládající entity – proto jde stejný blok vložit dvakrát
  a pokaždé v jiné barvě.
- TransformRenderer umí celou afinní transformaci, ne jen měřítko a posun.
  Oblouk zůstane obloukem jen u podobnosti bez zrcadlení; jinak by z kružnice
  byla elipsa, kterou kreslicí rozhraní nezná, tak se rozloží na lomenou čáru.
- ELLIPSE, POINT, SOLID, 3DFACE, POLYLINE3D se kreslí. U SOLID pozor na
  prohozený 3. a 4. roh, jinak vyjdou přesýpací hodiny.
- Zbytek se počítá do DxfTemplate.NezpracovaneEntity a souhrn exportu (PDF
  i DXF) ho vypíše. Export se kvůli tomu nezastaví.
- Spline se dělí podle délky (dřív pevných 64 dílků – málo pro dlouhé křivky,
  zbytečně moc pro krátké).
- Verze výstupního DXF se zafixovala na AC1027 (jako zdrojová šablona). Dřív ji
  určoval default ACadSharp, který může upgrade balíčku tiše změnit.

Šablona i všech 9 log projdou s prázdným počítadlem (test). Render log do PNG
je pixel po pixelu shodný s předchozím stavem. 114 testů zelených.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 14:46:02 +02:00

79 lines
3.8 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.Rendering;
namespace Rozpisky.Tests;
/// <summary>
/// Testovací <see cref="IProfileRenderer"/>: nic nekreslí, jen zaznamenává volání primitiv,
/// aby testy mohly assertovat, co přesně parser (<c>DxfTemplate.Replay</c>) vyprodukoval.
/// Obrysy (<see cref="Contour"/>) se pro pohodlné assertování bboxů zaznamenávají jak analyticky
/// (<see cref="FillContours"/>, <see cref="StrokeContours"/>), tak jemně zploštěné na body
/// (<see cref="Fills"/>, <see cref="Polylines"/>) zpětně kompatibilní s dřívějšími testy.
/// </summary>
public sealed class RecordingRenderer : IProfileRenderer
{
public sealed record TextCall(double X, double Y, string Text, double HeightMm, HAlign H, VAlign V,
double RotationDeg, TextStyle Style, double WidthFactor, double MaxWidthMm);
/// <summary>Každé volání Fill = smyčky jednoho HATCH, zploštěné na body.</summary>
public List<IReadOnlyList<IReadOnlyList<(double X, double Y)>>> Fills { get; } = new();
/// <summary>Analytické obrysy jednotlivých volání Fill (se zachovanými oblouky).</summary>
public List<IReadOnlyList<Contour>> FillContours { get; } = new();
/// <summary>Analytické obrysy z volání Stroke (bulge polylinie, samostatné oblouky).</summary>
public List<Contour> StrokeContours { get; } = new();
public List<TextCall> Texts { get; } = new();
/// <summary>Zploštěné polylinie i obrysy ze Stroke (kvůli zpětné kompatibilitě testů).</summary>
public List<IReadOnlyList<(double X, double Y)>> Polylines { get; } = new();
public int LineCount { get; private set; }
public int CircleCount { get; private set; }
/// <summary>Stavy kresby v pořadí, jak přišly testy tak můžou tvrdit i o barvě a hladině.</summary>
public List<KresliciStav> Stavy { get; } = new();
/// <summary>Stav platný pro naposledy zaznamenanou entitu.</summary>
public KresliciStav PosledniStav => Stavy.Count > 0 ? Stavy[^1] : KresliciStav.Vychozi;
public void Stav(in KresliciStav s) => Stavy.Add(s);
/// <summary>Koncové body zaznamenaných úseček testy tvrdí i o poloze, nejen o počtu.</summary>
public List<((double X, double Y) Od, (double X, double Y) Do)> Lines { get; } = new();
public void Line(double x1, double y1, double x2, double y2)
{
LineCount++;
Lines.Add(((x1, y1), (x2, y2)));
}
public void Polyline(IReadOnlyList<(double X, double Y)> pts, bool closed = false) => Polylines.Add(pts);
public void Circle(double cx, double cy, double r) => CircleCount++;
public void Stroke(Contour c)
{
StrokeContours.Add(c);
Polylines.Add(Zplosti(c));
}
public void Text(double x, double y, string text, double heightMm,
HAlign h = HAlign.Left, VAlign v = VAlign.Baseline, double rotationDeg = 0,
TextStyle style = default, double widthFactor = 1, double maxWidthMm = 0)
=> Texts.Add(new TextCall(x, y, text, heightMm, h, v, rotationDeg, style, widthFactor, maxWidthMm));
/// <summary>Druh výplně u jednotlivých volání Fill (plná / vzor a jeho čáry).</summary>
public List<Vypln> Vyplne { get; } = new();
public void Fill(IReadOnlyList<Contour> loops, Vypln vypln = default)
{
FillContours.Add(loops);
Vyplne.Add(vypln);
Fills.Add(loops.Select(Zplosti).ToList());
}
/// <summary>Zploští obrys na body (jemně, sagitta ≤ 0,02 mm) pro bbox asserty v testech.</summary>
private static IReadOnlyList<(double X, double Y)> Zplosti(Contour c)
{
var pts = new List<(double X, double Y)>();
foreach (var e in c.Edges) e.AppendPoints(pts, maxSagitta: 0.02);
if (c.Edges.Count > 0) pts.Add((c.Edges[^1].EX, c.Edges[^1].EY));
return pts;
}
}