fix(extract): Chunk-Ausgabe lauf-stabil, Eckenprüfung in beide Richtungen

emit.py normalisiert jede ausgegebene Fläche und sortiert die Listen nach der
Ausgabestruktur selbst. unary_union() in apply_street() gab das kartenweite
Straßenpolygon mit anderem Ringstartpunkt und an anderer Listenstelle zurück und
änderte damit 88 Chunkdateien, in denen sich geometrisch nichts bewegt hatte
(symmetrische Differenz 0,00 m²). Belagsarten und Mittellinien behalten ihre
Reihenfolge: overview.py malt die Beläge in Listenreihenfolge übereinander, und
vergeLampPoints() hängt an Reihenfolge und Laufrichtung der Mittellinien —
Sortieren verschöbe dort 1.848 von 3.921 Laternen auf die andere Straßenseite.

check_corners() misst gegen den Straßenrand statt gegen die Straßenfläche. Alle
vier Ecken liegen in der Fahrbahn, ihr Flächenabstand ist 0,000 m; die alte
Prüfung schlug deshalb nur an, wenn eine Straße sich zurückzieht. Eine nach
innen verbreiterte Straße hätte apply_park() still auf das veraltete Viereck
zurückgeschnitten.

Die Parkwege werden am Parkviereck abgeschnitten — die runden Kappen von
LineString.buffer() lagen mit 95,96 m² darüber hinaus, rund 41 m² davon sichtbar
als Betonzungen auf den umgebenden Belägen. load_elements() prüft den OSM-Abzug
so streng wie die Parkdatei, mit Dateiname statt nacktem KeyError.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
knsoandClaude Opus 5 committed 2026-09-16 13:43:01 +02:00
1 parent a3504df43d
commit 3c74202b5e
10 files changed
+333 -102

No files matched your search

+6 -1
View File
@@ -14,7 +14,12 @@ const BRIDGE_THICKNESS = 0.6;
const BRIDGE_OFFSET = SURFACE_OFFSET;
export const SURFACE_KINDS = ["sand", "park", "urban", "field", "court", "pool", "parking"];
/** Pastellton je Gebäude, reproduzierbar aus seiner Lage. */
/** Pastellton je Gebäude, reproduzierbar aus seiner Lage.
*
* Der Ton hängt am ersten Punkt des Außenrings, nicht an der Listenposition. Welcher Punkt das
* ist, legt seit Fix-Runde 3 die Ausgabe fest: emit.py normalisiert jede Fläche vor dem
* Schreiben (kleinster Punkt zuerst), sonst vergäbe GEOS den Startpunkt je nach Rechenweg neu
* und ein Extraktionslauf färbte die halbe Stadt ohne erkennbaren Grund um. */
function buildingTint(poly) {
const [x, z] = poly[0][0];
const h = Math.abs(Math.sin(x * 12.9898 + z * 78.233) * 43758.5453) % 1;
+16
View File
@@ -120,6 +120,22 @@ async function loadSet(loader, slug, fallback, { tint, maxAnisotropy } = {}) {
// Fläche), units den senkrechten Blick von oben (Steigung ~ 0) — der Spieler sieht im Spiel
// beides, je nach Kamerawinkel (Vogelperspektive in fly mode wie im Befund, aber auch normale
// Bodenperspektive).
//
// Die Beträge sind der Listenindex: jede neue Schicht schiebt alles über ihr eine Stufe weiter
// von der Kamera weg — genauer, weiter davor. Mit den fünf Park-Schichten (sand kam dazu, dann
// field, court, pool, parking, paths) ist die oberste Stufe von −4 auf −9 gewachsen, die
// Straßen bekommen also mehr als das Doppelte des früheren Versatzes. Für den senkrechten Blick
// ist das gleichgültig: units zählt in der kleinsten auflösbaren Tiefendifferenz, neun davon
// sind auch bei 300 m weit unter einem Millimeter. Der streifende Blick ist die Stelle, an der
// es auffallen kann, denn dort wird factor mit der Tiefensteigung multipliziert, und die geht
// bei fast waagerechtem Blick über eine Bodenfläche gegen unendlich: eine Straße wird dann um
// ein Vielfaches ihres nominellen Versatzes nach vorn gezogen und kann vor Geometrie geraten,
// die gar nicht an der Rangfolge teilnimmt (Gebäude, Brücken, Wasser — alle mit Versatz 0) und
// in Wahrheit vor ihr liegt. Wer hier eine Schicht ergänzt, verschiebt damit nicht nur die neue,
// sondern alle darüber und muss den streifenden Blick nachsehen. Bei −9 zeigte die Browser-
// prüfung im Park (Augenhöhe auf dem 13th-St-Weg, Blick über Rasen und Felder) nichts davon;
// wächst die Liste weiter, ist die Stufenhöhe zu entkoppeln, statt den Index weiterzuzählen.
//
// Flamingo Park: Felder, Plätze, Pool und Parkplatz liegen über dem Rasen, die Wege über allen Flächen
// und unter den Straßen, die sie an der Parkkante berühren.
export const POLYGON_OFFSET_ORDER = ["ground", "urban", "park", "sand", "field", "court", "pool", "parking", "paths", "roads"];