# Gartenvisualisierung Egglihaldenstrasse 9a Begehbare 3D-Visualisierung des geplanten Gartens von Jasmin und Damian Kellenberger, Egglihaldenstrasse 9a, 9030 Abtwil SG. Live: **https://garten.aicds.ch** Die gesamte Geometrie ist **massstäblich aus dem Gartenplan** abgeleitet – nicht nachmodelliert. Ein Node-Werkzeug liest die Vektordaten direkt aus dem Plan-PDF, rechnet sie in Meter um und erzeugt daraus das Szenenmodell. --- ## Grundlagen | Quelle | Inhalt | |---|---| | `Info Dateien/Gartenplan 1 …pdf` | Garten Design AG, 14.08.2026, Massstab 1:100, A1 | | `Info Dateien/20210427 - Projektpläne Haus 9a.pdf` | EHLE Architekten AG, Grundrisse, Fassaden, Umgebung | | `Info Dateien/WhatsApp Image …jpeg` | Fotos des Ist-Zustands (Fassade, Beläge, Nachbarschaft) | Die DWG wird nicht benötigt – das PDF enthält dieselbe Vektorgeometrie. ### Koordinatensystem Alles rechnet im **Site-Frame**, in Metern: - **X** – Hausachse ENE, Peilung 61.1615° gegen Nord - **Z** – senkrecht dazu, SSE, Peilung 151.1615° - **Y** – Höhe über dem Fixpunkt `0.00` = **651.17 m ü. M.** (OK Fertigboden EG) Der Nordpfeil des Plans zeigt exakt zur Blattoberkante, das Zeichnungsraster liegt um −28.8385° gedreht dazu. Der Massstab ist über das Plattenraster verifiziert: die Keramikplatten messen sich auf 0.600 m genau. ### Höhen | Bezug | relativ | absolut | |---|---|---| | Feuerwehrzufahrt, Nordwestecke | −2.08 | 648.09 m | | Nachbargarten Zollet (Haus 9, OK FB EG) | −1.70 | 649.47 m | | Hauptsitzplatz Travertin | −0.30 … −0.02 | 650.87 … 651.15 m | | Fixpunkt Hauseingang | 0.00 | 651.17 m | | Ostseite beim Apfelbaum | +0.63 | 651.80 m | | OK Fertigboden Obergeschoss | +2.90 | 654.07 m | | OK Attika Haus 9a | +6.15 | 657.32 m | --- ## Datenpipeline ```bash npm run data # extract-plan + build-site ``` 1. **`tools/extract-plan.mjs`** – öffnet das Plan-PDF mit MuPDF (WASM) und protokolliert alle Zeichenoperationen mit. Ergebnis: rund 5400 Polygone, 234 Pflanzenkreise, 229 Beschriftungen und 46 Höhenkoten, transformiert in den Site-Frame. → `tools/out/plan-raw.json` 2. **`tools/authoring.mjs`** – handgepflegte Ergänzungen: Zuordnung der Planfarben zu Belagsarten, Mauerachsen und -höhen, Gebäudekubatur, Geländezonen, Standorte. Alles kommentiert und auf Plan oder Architekturpläne zurückgeführt. 3. **`tools/build-site.mjs`** – klassiert die Flächen, leitet Pflanzen und Leuchten ab, interpoliert das Geländeraster (0.25 m) aus den Höhenkoten je Zone und schreibt `public/data/site.json` (rund 110 kB). Zur Kontrolle: `node tools/debug-svg.mjs` zeichnet die extrahierte Geometrie als SVG-Draufsicht, `node tools/inspect-colors.mjs` listet die Planfarben mit den nächstgelegenen Beschriftungen. ### Warum Zonen statt eines einzigen Geländes Das Grundstück fällt über rund 3.5 m ab, die Sprünge liegen aber nicht im Gelände, sondern in den Stützbauten: Travertinmauer zum Nachbargrundstück, Winkelelemente aus Beton entlang der Feuerwehrzufahrt, Betonmauer im Süden. Deshalb wird je Zone getrennt interpoliert – über die Zonengrenze hinweg nie. Die Mauern erhalten ihr Kronen- und Fussprofil aus dem Gelände beider Seiten. --- ## Anwendung ```bash npm install npm run dev # http://localhost:5173 npm run build # dist/, rund 640 kB ``` Stack: Vite + TypeScript + three.js. **Keine externen Assets** – sämtliche Texturen (Travertin, Keramik, Tegula, Rasen, Kies, Beton, Holzschalung, Scheiterwand) werden zur Laufzeit prozedural auf ein Canvas gezeichnet. Die UVs sind weltbezogen, damit die Plattenraster über Flächengrenzen hinweg durchlaufen – so wie auf dem Plan. ### Bedienung | | | |---|---| | Rundgang | Klicken, dann `W` `A` `S` `D`, `Shift` zum Rennen, `Esc` gibt die Maus frei | | Handy | links Joystick, rechts wischen zum Umsehen | | Übersicht | ziehen zum Drehen, Mausrad zum Zoomen | | Tageszeit | Regler oben rechts, Sonnenstand astronomisch für Abtwil SG gerechnet | Der Rundgang folgt dem Gelände, steigt Stufen bis 45 cm und wird von Mauern, Gebäuden, Hecken und Objekten aufgehalten. Ab Dämmerung schalten die 17 Leuchten des Plans automatisch ein. ### Aufbau ``` src/ site.ts Datenmodell und Höhen-Sampler scene/textures.ts prozedurale Beläge und Materialien scene/geometry.ts Polygone auf das Gelände legen, Mauern extrudieren scene/terrain.ts Geländeraster und Umland scene/surfaces.ts Beläge scene/structures.ts Mauern, Stelen, Objekte, Leuchten scene/vegetation.ts Gehölze, Hecken, Gräser, Stauden scene/building.ts Wohnhaus 9a und Nachbargebäude scene/environment.ts Himmel, Sonnenstand, Licht controls/walker.ts Begehen mit Kollision und Geländeführung ui/hud.ts Bedienoberfläche ``` --- ## Deployment Push auf `main` löst den Gitea-Workflow aus; die App landet unter `/opt/aicds/apps/Gartenvisualisierung/` und wird per `docker compose` gebaut. Traefik-Router `garten`, Host `garten.aicds.ch`, Netzwerk `agent-net`. ```bash docker compose config # Prüfung vor dem Push docker compose up -d --build ``` Das Image enthält nur `dist/` hinter nginx – die Planunterlagen und Fotos aus `Info Dateien/` werden über `.dockerignore` ausgeschlossen und gelangen nie in den Webcontainer. --- ## Was bewusst interpretiert ist Der Plan ist ein Situationsplan; einiges steht nur als Beschriftung darin. Diese Annahmen stecken in `tools/authoring.mjs` und sind dort einzeln kommentiert: - **Mauerhöhen** aus den Höhenkoten beidseits abgeleitet; die gelbe Kote `25` bei der Sitzmauer als 25 cm Aufkantung gelesen, `35` bei den Heidelbeeren analog. - **Lamellenwand zum Sitzen** als senkrechte Holzlamellen im Planrhythmus (10 cm breit, 35 cm tief, rund 90 cm Achsabstand), passend zum Foto des Ist-Zustands. - **Wohnhaus** in Kubatur und Öffnungen nach Gartenplan und Fassadenplänen, Materialisierung nach den Fotos: vertikale Holzschalung graubraun, heller Betonsockel, Flachdach mit extensiver Begrünung. - **Nachbarhaus Zollet** als einfaches Kontextvolumen, 1.70 m tiefer liegend. - **Solitärgehölze** mit den Kronenradien des Plans; Wuchshöhen als Erfahrungswerte. - **Gartenhaus, Spielhaus, Flammengrill, Bänkli** in Lage und Grundfläche nach Plan, in der Ausformulierung frei.