Ablauf wie beim Hood Yard mit den gefundenen Fallstricken (Dreiecke je Knoten, Bodenplatte +6 cm, globale Materiallisten, Asset-Test je Ort, launch.json nur im Hauptordner, gl.finish-Messung, Vorwärmen prüfen) und Werkzeugen: Modell vermessen, Kartendaten eines Weltfensters, Vergleichsbild Satellit/Spiel, Screenshot-Dekodierung, erprobte Browser-Ausschnitte. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
51 lines
2.9 KiB
JavaScript
51 lines
2.9 KiB
JavaScript
// Holt die Kartendaten eines Weltausschnitts für die Platzierung, in Welt-x/-y (Meter, Norden = +y):
|
|
//
|
|
// node .claude/skills/placing-editor-models/scripts/site-data.mjs <x0> <x1> <y0> <y1> <ausgabe.json>
|
|
//
|
|
// Enthält Land, Flächen (park/sand/urban), Straßen, Gebäude, Palmen und die Laternen, wie PropLayer sie
|
|
// setzt (vergeLampPoints(lampPoints(...)) je Chunk — Laternen stehen bis 16 m neben ihrer Mittellinie,
|
|
// deshalb werden auch die Nachbarchunks des Ausschnitts gelesen). render-site.py zeichnet daraus das
|
|
// Vergleichsbild; die Grenzen für Straßenrand, Felder usw. lassen sich direkt aus dem JSON ablesen.
|
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
import { CHUNKS_PER_SIDE, CHUNK_SIZE, SLICE, chunkName } from "../../../../src/world/coords.js";
|
|
import { lampPoints, vergeLampPoints } from "../../../../src/world/props.js";
|
|
|
|
const [x0, x1, y0, y1] = process.argv.slice(2, 6).map(Number);
|
|
const out = process.argv[6];
|
|
if ([x0, x1, y0, y1].some(Number.isNaN) || !out) {
|
|
console.error("Aufruf: node site-data.mjs <x0> <x1> <y0> <y1> <ausgabe.json>");
|
|
process.exit(1);
|
|
}
|
|
|
|
const iOf = (X) => Math.floor((X - SLICE.x0) / CHUNK_SIZE);
|
|
const jOf = (Y) => Math.floor((SLICE.y1 - Y) / CHUNK_SIZE);
|
|
const clamp = (k) => Math.min(CHUNKS_PER_SIDE - 1, Math.max(0, k));
|
|
const chunkUrl = (i, j) => new URL(`../../../../public/data/vice-a/chunk_${i}_${j}.json`, import.meta.url);
|
|
|
|
const chunks = [];
|
|
const palms = [];
|
|
const lamps = [];
|
|
for (let i = clamp(iOf(x0) - 1); i <= clamp(iOf(x1) + 1); i++) {
|
|
for (let j = clamp(jOf(y1) - 1); j <= clamp(jOf(y0) + 1); j++) {
|
|
const c = JSON.parse(readFileSync(chunkUrl(i, j), "utf8"));
|
|
const [ox, oz] = c.origin;
|
|
const world = (u, v) => [Number((ox + u).toFixed(2)), Number((-(oz + v)).toFixed(2))];
|
|
const rings = (poly) => poly.map((ring) => ring.map(([u, v]) => world(u, v)));
|
|
chunks.push({
|
|
key: `${i}_${j}`, name: chunkName(i, j),
|
|
land: c.land.map(rings),
|
|
surfaces: (c.surfaces ?? []).map((s) => ({ kind: s.kind, rings: rings(s.poly) })),
|
|
roads: c.roads.map((r) => ({ bridge: r.bridge, rings: rings(r.poly) })),
|
|
buildings: c.buildings.map((b) => ({ height: b.height, rings: rings(b.poly) })),
|
|
});
|
|
for (const [u, v] of c.palms ?? []) palms.push(world(u, v));
|
|
for (const p of vergeLampPoints(lampPoints(c.centerlines ?? []), c.roads ?? [])) lamps.push(world(p.x, p.z));
|
|
}
|
|
}
|
|
|
|
const inside = ([X, Y]) => X >= x0 && X <= x1 && Y >= y0 && Y <= y1;
|
|
writeFileSync(out, JSON.stringify({ box: { x0, x1, y0, y1 }, chunks, palms, lamps }));
|
|
console.log(`${chunks.length} Chunks (${chunks.map((c) => c.name).join(", ")}), ` +
|
|
`${palms.filter(inside).length} Palmen und ${lamps.filter(inside).length} Laternen im Ausschnitt → ${out}`);
|
|
for (const lamp of lamps.filter(inside)) console.log(` Laterne bei (${lamp[0]} | ${lamp[1]})`);
|