Planabgleich Etappe A bis C: Zugaenge, Rasenrandplatten, Torstufen
Deploy App / deploy (push) Successful in 28s

Systematischer Abgleich Plan gegen Szene, Bereich fuer Bereich.

Neu gebaut
- Lineare Bauteile (LINEAR): Treppe und Rampe am Ost- und Westzugang,
  Stahlrohrgelaender laengs des Gefaelles, Entwaesserungsrinnen mit
  buendigem Rost. Geometrie aus den Trittlinien des Plans abgegriffen
  (Ost: 8 Trittlinien z -4.18 bis -6.52, Koten -0.37/-1.57; West:
  Trittlinien alle 20 cm ab x -21.94, Koten -0.28/-1.08).
- Rasenrandplatten: das durchgehende Band von 6 cm Breite entlang der
  Rasenkante wird als hochkant stehende Randplatte mit Sichtkante
  aufgebaut, nicht mehr als Belag (neuer Typ randplatte, 1.2 m2).
- Zwei schwebende Travertinstufen am Gartentor, Koten -0.13 und -0.32.
- Winkelelemente entlang der Suedgrenze, Tegula-Streifen des Nachbarn.

Korrigiert
- Holzscheiterwand: der Plan zeigt zwei Felder 1.50 x 0.46 m, nicht eines.
  Farbe #ffaa00 war faelschlich als Tegula klassiert.
- Gartentor: Fluegel laeuft ueber z, nicht ueber x - das Tor stand um 90
  Grad verdreht. Jetzt Stabgitter mit Pfosten und senkrechten Staeben
  statt geschlossenem schwarzem Blatt.
- Winkelelemente Ost auf x 3.735 (Plan: Doppellinie 3.69/3.78), Fussweg
  auf x 2.86 bis 3.69 zwischen Verbundstein-Anpassung und Winkelelementen.
- Rinne beim Gartentor auf die Schraffur des Plans (z 2.295, x -23.34
  bis -21.74).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-10 17:56:58 +02:00
co-authored by Claude Opus 5
parent ba9ce4ed21
commit 32ceba7de0
9 changed files with 364 additions and 26 deletions
+105 -9
View File
@@ -25,7 +25,7 @@ export const SURFACE_BY_COLOR = {
'#bbbbbb': 'verbundstein', // Anpassung Verbundsteine Nachbar
'#ddba99': 'beet',
'#c0bab4': 'spielsand',
'#ffaa00': 'tegula', // Tegula-Pflastersteine grau (im Plan orange markiert)
'#ffaa00': 'holzscheiter', // orange markiert: die beiden Holzscheiterwaende im Sichtschutz
'#ddd299': 'travertinstell',
'#73e900': 'ligusterhecke',
'#cccccc': 'winkelelement',
@@ -137,6 +137,22 @@ export const WALLS = [
note: 'Schenkel der Travertinsitzmauer laengs des Rasens, gleicher Hoehensprung',
path: [[-18.44, 0.55], [-18.44, 3.94]], t: 0.40, top: -0.02, base: -0.55, seating: true,
},
{
// Der Plan beschriftet die Linien an der Ostgrenze mit "Winkelelemente":
// sie stuetzen den Garten gegen den tiefer liegenden Fussweg ab.
id: 'winkelelemente-ost', type: 'beton',
note: 'Winkelelemente aus Beton an der Ostgrenze, gegen den Fussweg',
path: [[3.735, -6.90], [3.735, 4.90]],
t: 0.14, top: null, base: null, retains: 'ost',
},
{
// Der Plan beschriftet die Linie bei z 4.96 mit "Winkelelemente": sie
// fasst das hoeher liegende Nachbargrundstueck hinter dem Sichtschutz.
id: 'winkelelemente-sued', type: 'beton',
note: 'Winkelelemente aus Beton entlang der Suedgrenze',
path: [[-21.20, 4.96], [1.99, 4.96]],
t: 0.14, top: null, base: null, retains: 'sued',
},
{
id: 'betonmauer-nachbar', type: 'beton',
note: 'Bestehende Betonmauer des Suednachbarn entlang der Grenze',
@@ -147,15 +163,23 @@ export const WALLS = [
note: 'Rueckspringender Schenkel der Nachbarmauer',
path: [[2.09, 6.07], [2.09, 9.05]], t: 0.20, top: 1.10, base: -0.60,
},
// Der Plan zeigt zwei orange markierte Felder von 1.50 x 0.46 m in der
// Sichtschutzlinie; die Beschriftung "Holzscheiterwand 150 cm x 200 cm"
// steht zwischen ihnen und gilt fuer beide.
{
id: 'holzscheiterwand', type: 'holzscheiter',
id: 'holzscheiterwand-west', type: 'holzscheiter',
note: 'Holzscheiterwand 150 cm breit, 200 cm hoch, hinter dem Flammengrill',
path: [[-5.75, 4.35], [-4.25, 4.35]], t: 0.45, top: 2.26, base: 0.20,
path: [[-6.08, 4.18], [-4.58, 4.18]], t: 0.46, top: 2.32, base: 0.22,
},
{
id: 'stufe-gartentor', type: 'travertin',
note: 'Blockstufen beim Gartentor an der Suedwestecke',
path: [[-21.05, 2.15], [-21.05, 3.75]], t: 0.80, top: -0.18, base: -0.80,
id: 'holzscheiterwand-ost', type: 'holzscheiter',
note: 'Zweite Holzscheiterwand 150 cm breit, 200 cm hoch',
path: [[-8.74, 4.18], [-7.24, 4.18]], t: 0.46, top: 2.28, base: 0.18,
},
{
id: 'stufe-nordwest', type: 'travertin',
note: 'Stufe an der Nordwestecke, vom Sitzplatz auf die Schotterwiese',
path: [[-20.90, -7.29], [-20.10, -7.29]], t: 0.42, top: -0.33, base: -0.95,
},
{
id: 'lamellenwand', type: 'lamellen',
@@ -179,7 +203,9 @@ export const PROPS = [
{ id: 'wasserhahn', type: 'wasserhahn', x: -13.90, z: -4.60, w: 0.12, d: 0.12, h: 0.85, rot: 0 },
{ id: 'schlaufschacht', type: 'schacht', x: -14.35, z: -3.95, w: 0.30, d: 0.30, h: 0.02, rot: 0,
note: 'Schlaufschacht D = 30 cm' },
{ id: 'gartentor', type: 'tor', x: -21.60, z: 3.30, w: 1.00, d: 0.06, h: 1.10, rot: 0 },
// Der Torfluegel liegt im Plan bei x -21.53 und laeuft ueber z 2.56 bis 3.56.
{ id: 'gartentor', type: 'tor', x: -21.53, z: 3.06, w: 1.00, d: 0.06, h: 1.20, rot: 90,
note: 'Gartentor 100 cm, Stabgitter aus Stahl' },
// Zwei schwebende Travertinplatten fuehren vom gedeckten Sitzplatz (-0.02)
// auf den Hauptsitzplatz (-0.33). Lage und Format stehen im Plan, die
// Ausbildung als auskragende Platte zeigt das Referenzbild des Planers.
@@ -187,6 +213,13 @@ export const PROPS = [
top: -0.17, note: 'Schwebende Travertinstufe, Tritthoehe -0.17' },
{ id: 'stufe-unten', type: 'stufe', x: -14.880, z: -1.480, w: 0.80, d: 3.20, h: 0.08, rot: 0,
top: -0.31, note: 'Schwebende Travertinstufe, Tritthoehe -0.31' },
// Beim Gartentor liegen ebenfalls zwei schwebende Travertinstufen: der Plan
// zeichnet ein Feld 0.80 x 1.60 m mit den Koten -0.13 (Podest am Tor) und
// -0.32 (Anschluss an den Hauptsitzplatz).
{ id: 'stufe-tor-oben', type: 'stufe', x: -21.05, z: 3.35, w: 0.80, d: 0.80, h: 0.08, rot: 0,
top: -0.13, note: 'Schwebende Travertinstufe am Gartentor, Tritthoehe -0.13' },
{ id: 'stufe-tor-unten', type: 'stufe', x: -21.05, z: 2.55, w: 0.80, d: 0.80, h: 0.08, rot: 0,
top: -0.32, note: 'Schwebende Travertinstufe am Gartentor, Tritthoehe -0.32' },
];
/**
@@ -201,8 +234,27 @@ export const EXTRA_SURFACES = [
},
{
type: 'tegula',
note: 'Feuerwehrzufahrt und Zugangsweg, Tegula-Pflastersteine grau',
polygon: [[-25.60, -9.00], [-22.10, -9.00], [-22.10, 6.40], [-25.60, 6.40]],
note: 'Feuerwehrzufahrt und Zugangsweg westlich der Grenze, Tegula-Pflastersteine grau',
polygon: [[-25.60, -13.50], [-22.10, -13.50], [-22.10, 6.40], [-25.60, 6.40]],
},
{
// Der Plan zeigt oestlich der Grenze einen gepflasterten Weg, erst dahinter
// beginnt die Wiese. Zwei Leuchten stehen daran.
type: 'tegula',
note: 'Fussweg an der Ostseite zwischen Verbundstein-Anpassung und Winkelelementen',
polygon: [[2.86, -7.00], [3.69, -7.00], [3.69, 4.90], [2.86, 4.90]],
},
{
// Schmaler gepflasterter Streifen jenseits der Suedgrenze, zwischen
// Grenze (z 4.49) und den Winkelelementen des Nachbarn (z 4.96).
type: 'tegula',
note: 'Tegula-Streifen des Suednachbarn entlang der Grenze',
polygon: [[-21.74, 4.49], [1.99, 4.49], [1.99, 4.96], [-21.74, 4.96]],
},
{
type: 'tegula',
note: 'Stellplatte und Sitzplatz des Nachbarn im Nordosten',
polygon: [[0.40, -11.20], [4.60, -11.20], [4.60, -7.30], [0.40, -7.30]],
},
{
// Die schwebenden Stufen im Plan: eine Zwischenebene zwischen dem
@@ -214,6 +266,50 @@ export const EXTRA_SURFACES = [
},
];
/**
* Lineare Bauteile, die der Plan benennt, aber nur als Linienbuendel zeichnet:
* Treppen mit Rampe, die zugehoerigen Gelaender und die Entwaesserungsrinnen.
*
* `path` ist die Achse in Laufrichtung, `fromY`/`toY` die Hoehe an Anfang und
* Ende. Die Hoehen stammen aus den Koten beidseits des jeweiligen Bauteils.
*/
export const LINEAR = [
{
// Der Plan zeichnet acht Trittlinien bei z -4.18 bis -6.52 ueber die
// Breite x 2.17 bis 3.78; die Koten daneben lauten -0.37 und -1.57.
id: 'treppe-ost', kind: 'treppe',
note: 'Treppe und Rampe hinunter zum Stellplatz des Nachbarn (-0.37 auf -1.57)',
path: [[2.975, -4.18], [2.975, -6.52]], width: 1.61, fromY: -0.37, toY: -1.57, steps: 7,
},
{
id: 'gelaender-ost', kind: 'gelaender',
note: 'Gelaender laengs der Osttreppe',
path: [[2.17, -4.18], [2.17, -6.52]], fromY: -0.37, toY: -1.57, height: 0.95,
},
{
// Trittlinien bei x -21.94 bis -22.54 im Abstand von 20 cm, Block bis
// x -23.34; Koten -0.28 oben und -1.08 auf der Feuerwehrzufahrt.
id: 'treppe-west', kind: 'treppe',
note: 'Treppe und Rampe von der Feuerwehrzufahrt zum Gartentor (-0.28 auf -1.08)',
path: [[-21.84, 1.37], [-22.64, 1.37]], width: 1.70, fromY: -0.28, toY: -1.08, steps: 4,
},
{
id: 'gelaender-west', kind: 'gelaender',
note: 'Gelaender an der Treppe zur Feuerwehrzufahrt',
path: [[-21.84, 0.52], [-22.64, 0.52]], fromY: -0.28, toY: -1.08, height: 0.95,
},
{
id: 'rinne-gartentor', kind: 'rinne',
note: 'Entwaesserungsrinne vor dem Gartentor',
path: [[-23.34, 2.295], [-21.74, 2.295]], width: 0.15,
},
{
id: 'edelstahlrinne', kind: 'rinne',
note: 'Edelstahlrinne laengs der Fassade am Hauptsitzplatz',
path: [[-13.98, -6.55], [-13.98, -2.95]], width: 0.13,
},
];
/**
* Hoehe des Sichtschutzes. Er besteht aus aufrechten Travertinstelen
* (50 x 6 cm im Grundriss) und Eibengruppen, die sich abwechseln und
+17 -2
View File
@@ -8,7 +8,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import {
SURFACE_BY_COLOR, PLANT_BY_COLOR, TREES, WALLS, PROPS, LEVELS, STELE_HEIGHTS,
SURFACE_BY_COLOR, PLANT_BY_COLOR, TREES, WALLS, PROPS, LEVELS, STELE_HEIGHTS, LINEAR,
BUILDING, NEIGHBOUR_BUILDINGS, TERRAIN_ZONES, EXTRA_SPOTS, EXTRA_SURFACES,
START_VIEWS, SITE_LOCATION,
} from './authoring.mjs';
@@ -85,7 +85,7 @@ function fitPlane(points) {
// ---------------------------------------------------------------------------
/** Bauteile, die als Mauer modelliert werden - nicht als begehbare Flaeche. */
const NOT_A_SURFACE = new Set(['travertinmauer', 'winkelelement', 'spielhaus', 'gartenhaus', 'roboter', 'ligusterhecke']);
const NOT_A_SURFACE = new Set(['travertinmauer', 'winkelelement', 'spielhaus', 'gartenhaus', 'roboter', 'ligusterhecke', 'holzscheiter']);
const bboxOf = (pts) => {
let x0 = Infinity, z0 = Infinity, x1 = -Infinity, z1 = -Infinity;
@@ -133,6 +133,19 @@ for (const s of raw.shapes) {
}
}
// Rasenrandplatten: derselbe Ton wie die Stelen, aber als durchgehendes
// Band von 6 cm Breite entlang der Rasenkante. Sie stehen hochkant und
// trennen den Rasen vom Kiesbett des Sichtschutzes.
const laenge = Math.max(b.w, b.d);
if (s.hex === '#ddd299' && laenge > 0.8 && s.area / laenge < 0.15) {
const poly = polygonArea(s.pts) < 0 ? [...s.pts].reverse() : s.pts;
surfaces.push({
type: 'randplatte', area: round(s.area, 2),
polygon: poly.map((p) => [round(p[0]), round(p[1])]),
});
continue;
}
// Der Plan verwendet denselben hellen Ton fuer Dekorkies und fuer die
// Keramikterrasse des Nachbarn; unterschieden wird ueber die Lage.
if (type === 'dekorkies' && cz < -6.6) type = 'keramik';
@@ -466,6 +479,7 @@ const site = {
lamps,
walls,
props: PROPS,
linear: LINEAR,
stelen,
building: BUILDING,
neighbourBuildings: NEIGHBOUR_BUILDINGS,
@@ -487,6 +501,7 @@ console.log(`Lose Travertinplatten 40x60: ${slabs.length}`);
console.log(`Pflanzen ${plants.length}, Baeume ${trees.length}, Leuchten ${lamps.length}, Mauern ${walls.length}, Objekte ${PROPS.length}`);
const bySide = {};
for (const s of stelen) bySide[s.side] = (bySide[s.side] ?? 0) + 1;
console.log(`Lineare Bauteile ${LINEAR.length}: ` + LINEAR.map((l) => l.kind).join(', '));
console.log(`Travertinstelen ${stelen.length}: ` + Object.entries(bySide).map(([k, v]) => `${k} ${v} Stk auf ${STELE_HEIGHTS.find((r) => r.id === k)?.height ?? '?'} m`).join(', '));
console.log(`Hoehenraster ${nx} x ${nz} (${CELL} m), Koten ${terrainSpots.length}`);
const hs = Array.from(smoothed);