Geometrie massstaeblich aus dem Gartenplan-PDF (1:100) extrahiert: Belaege, Mauern, Pflanzenstandorte und 46 Hoehenkoten. Wohnhaus nach Gartenplan und den Fassadenplaenen von EHLE Architekten. - tools/: Pipeline PDF -> Szenenmodell (MuPDF, Node) - src/: three.js-Szene mit prozeduralen Texturen, Rundgang und Uebersicht - Docker/Traefik fuer garten.aicds.ch, Gitea-Workflow auf main Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
53 lines
1.7 KiB
JavaScript
53 lines
1.7 KiB
JavaScript
/**
|
|
* Listet alle Fuellfarben des Plans mit Flaeche, Anzahl Polygone und den
|
|
* naechstgelegenen Beschriftungen - Grundlage fuer die Farb-zu-Material-Zuordnung.
|
|
*
|
|
* Aufruf: node tools/inspect-colors.mjs [minFlaeche]
|
|
*/
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const data = JSON.parse(fs.readFileSync(path.join(__dirname, 'out', 'plan-raw.json'), 'utf8'));
|
|
const MIN = parseFloat(process.argv[2] ?? '0.15');
|
|
|
|
const centroid = (pts) => {
|
|
let x = 0, z = 0;
|
|
for (const p of pts) { x += p[0]; z += p[1]; }
|
|
return [x / pts.length, z / pts.length];
|
|
};
|
|
|
|
const groups = new Map();
|
|
for (const s of data.shapes) {
|
|
if (s.op !== 'f') continue;
|
|
const g = groups.get(s.hex) ?? { hex: s.hex, n: 0, area: 0, big: [], circles: 0 };
|
|
g.n++; g.area += s.area;
|
|
if (s.circle) g.circles++;
|
|
if (s.area >= MIN) g.big.push(s);
|
|
groups.set(s.hex, g);
|
|
}
|
|
|
|
const rows = [...groups.values()].sort((a, b) => b.area - a.area);
|
|
for (const g of rows) {
|
|
if (g.area < 0.2 && g.circles === 0) continue;
|
|
const near = new Set();
|
|
for (const s of g.big.slice(0, 6)) {
|
|
const [cx, cz] = centroid(s.pts);
|
|
const cands = data.labels
|
|
.map((l) => ({ l, d: Math.hypot(l.x - cx, l.z - cz) }))
|
|
.filter((c) => c.d < 3.5 && !/^-?\d\.\d{2}$/.test(c.l.text))
|
|
.sort((a, b) => a.d - b.d)
|
|
.slice(0, 3);
|
|
for (const c of cands) near.add(c.l.text);
|
|
}
|
|
console.log(
|
|
g.hex.padEnd(9),
|
|
('n=' + g.n).padEnd(7),
|
|
(g.area.toFixed(1) + ' m2').padStart(9),
|
|
('gross=' + g.big.length).padEnd(10),
|
|
('kreise=' + g.circles).padEnd(11),
|
|
[...near].slice(0, 7).join(' / '),
|
|
);
|
|
}
|