/** * Zeichnet die extrahierte Geometrie als SVG-Draufsicht - Kontrolle, ob die * Transformation aus dem PDF stimmt. * * Aufruf: node tools/debug-svg.mjs [nur-farbe-hex] */ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const OUT = path.join(__dirname, 'out'); const data = JSON.parse(fs.readFileSync(path.join(OUT, 'plan-raw.json'), 'utf8')); const only = process.argv[2]?.toLowerCase(); const PAD = 1.5; const PXM = 34; // Pixel pro Meter let x0 = Infinity, z0 = Infinity, x1 = -Infinity, z1 = -Infinity; for (const s of data.shapes) for (const [x, z] of s.pts) { x0 = Math.min(x0, x); x1 = Math.max(x1, x); z0 = Math.min(z0, z); z1 = Math.max(z1, z); } x0 -= PAD; z0 -= PAD; x1 += PAD; z1 += PAD; const W = Math.round((x1 - x0) * PXM), H = Math.round((z1 - z0) * PXM); const X = (x) => ((x - x0) * PXM).toFixed(1); const Z = (z) => ((z - z0) * PXM).toFixed(1); const out = []; out.push(``); out.push(``); const fills = data.shapes.filter((s) => s.op === 'f' && s.area > 0.05); fills.sort((a, b) => b.area - a.area); for (const s of fills) { if (only && s.hex.toLowerCase() !== only) continue; const d = s.pts.map((p, i) => `${i ? 'L' : 'M'}${X(p[0])},${Z(p[1])}`).join('') + 'Z'; out.push(``); } if (!only) { for (const s of data.shapes) { if (s.op !== 's' || s.pts.length < 2) continue; const d = s.pts.map((p, i) => `${i ? 'L' : 'M'}${X(p[0])},${Z(p[1])}`).join(''); out.push(``); } for (const sp of data.spots) { out.push(``); out.push(`${sp.y.toFixed(2)}`); } } // Massstab und Achsen out.push(` `); out.push(`+X (ENE)`); out.push(`+Z (SSE)`); out.push(`Gartenplan → Site-Frame · ${(x1 - x0).toFixed(1)} × ${(z1 - z0).toFixed(1)} m · 1 Raster = 1 m`); out.push(''); const file = path.join(OUT, only ? `debug-${only.replace('#', '')}.svg` : 'debug-plan.svg'); fs.writeFileSync(file, out.join('\n')); console.log('geschrieben:', file, `${W}x${H}px`);