Files
Rozpisky/Rozpisky/Rendering/BoundsRenderer.cs
T
marekandClaude Opus 5 001afc2d81 Šrafy: rozvinout vzor na čáry místo plné výplně
Každá šrafa se kreslila jako plná výplň, bez ohledu na vzor. Logo md_sfdi.dxf
má 3× ANSI31 (šikmé čáry) – vycházel z něj plný blok. Nový SrafaVzor rozvine
definiční čáry vzoru na úsečky: rodina rovnoběžek podle vektoru Offset,
ořezaná hranicemi šrafy sudo-lichou paritou (takže díry ve vnořených smyčkách
vyjdou správně) a čárkováním z DashLengths. Proti zamrznutí náhledu při vadném
měřítku ve zdroji je strop 20 000 úseček na šrafu.

Rozhraní: Fill(loops) dostává druhý parametr Vypln. Rastrové renderery kreslí
rozvinuté čáry (Skia vzory neumí), DXF export je ignoruje a zapíše zpátky HATCH
s původním jménem vzoru, měřítkem a úhlem – v CADu tak zůstane editovatelný.
Když se vzor rozvinout nepodaří, plocha zůstane prázdná; zaplácnout ji načerno
je horší než ji nevyplnit.

Ověřeno i vizuálně: z 9 dodávaných log se změnilo jen md_sfdi, ostatních 8 je
po renderu do PNG pixel po pixelu shodných s předchozím stavem.

105 testů zelených.

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

72 lines
3.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.
namespace Rozpisky.Rendering;
/// <summary>
/// Nic nekreslí jen sčítá min/max souřadnic (ROZPISKY.md §3). Stejnou kresbou se zjistí
/// rozsah pro vystředění na A4 / „zoom to fit".
/// </summary>
public sealed class BoundsRenderer : IProfileRenderer
{
public double MinX { get; private set; } = double.MaxValue;
public double MinY { get; private set; } = double.MaxValue;
public double MaxX { get; private set; } = double.MinValue;
public double MaxY { get; private set; } = double.MinValue;
public bool IsEmpty => MinX > MaxX;
public double Width => IsEmpty ? 0 : MaxX - MinX;
public double Height => IsEmpty ? 0 : MaxY - MinY;
private void Add(double x, double y)
{
if (x < MinX) MinX = x;
if (y < MinY) MinY = y;
if (x > MaxX) MaxX = x;
if (y > MaxY) MaxY = y;
}
public void Stav(in KresliciStav s) { }
public void Line(double x1, double y1, double x2, double y2) { Add(x1, y1); Add(x2, y2); }
public void Polyline(IReadOnlyList<(double X, double Y)> pts, bool closed = false)
{
foreach (var (x, y) in pts) Add(x, y);
}
public void Circle(double cx, double cy, double r) { Add(cx - r, cy - r); Add(cx + r, cy + r); }
public void Stroke(Contour c) => AddContour(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)
{
// Hrubý odhad rozsahu (na vystředění stačí kotva + přibližná výška/šířka), víceřádkově.
var segs = (text ?? "").Replace("\\P", "\n").Replace('\r', '\n').Split('\n');
int longest = 0;
foreach (var s in segs) if (s.Length > longest) longest = s.Length;
double wf = widthFactor > 0 ? widthFactor : 1;
double w = longest * heightMm * 0.6 * wf
+ heightMm * Math.Abs(Math.Tan(style.ObliqueDeg * Math.PI / 180)); // přesah sklonu
double blockH = segs.Length * heightMm * 1.4;
// Kotva dle zarovnání: box roste od kotvy směrem daným H/V (dřív jen doprava nahoru).
double dx = h switch { HAlign.Center => -w / 2, HAlign.Right => -w, _ => 0 };
double dy = v switch { VAlign.Top => -blockH, VAlign.Middle => -blockH / 2, _ => 0 };
Add(x + dx, y + dy);
Add(x + dx + w, y + dy + blockH);
}
public void Fill(IReadOnlyList<Contour> loops, Vypln vypln = default)
{
foreach (var loop in loops) AddContour(loop);
}
/// <summary>Započítá obrys oblouky navzorkuje na body (na bbox stačí hrubší tolerance).</summary>
private void AddContour(Contour c)
{
var pts = new List<(double X, double Y)>();
foreach (var e in c.Edges) e.AppendPoints(pts, maxSagitta: 0.1);
foreach (var (x, y) in pts) Add(x, y);
if (c.Edges.Count > 0) { Add(c.Edges[^1].EX, c.Edges[^1].EY); } // poslední koncový bod
}
}