Files
DOSSIER-STANDALONE/docs/research/swisstopo-sia.md
T
karim ca859c4aa4 Browser-BIM (cad): semantisches Modell, abgeleitete 2D/3D-Sichten, Zeichenwerkzeuge
Standalone-Browser-Port von DOSSIER. Enthaelt das semantische Modell mit
Plan-/3D-Ableitung, Zeichen- und Editierwerkzeuge, Rhino-artiges Befehlssystem,
dockbares Panel-System, Resource-Manager, DXF/.lin/.pat-Import, i18n (de/en)
sowie Projektdokumentation und Probe-Harness.
2026-06-30 20:52:27 +02:00

31 KiB
Raw Blame History

Swisstopo-Geodaten & SIA-Flächenstandards im Browser-BIM

Stand: 2026-06-29 · Recherche für das Standalone-Browser-BIM (React + TS + Three.js), Port von DOSSIER (Rhino-Plugin). Ziel: (A) Schweizer Geodaten (Höhenmodell, Orthofoto, 3D-Gebäude, Parzellen) direkt im Browser laden, (B) Standort-Kontext (Gelände + Parzelle + Nachbargebäude) für ein Projekt importieren, (C) SIA-416- Flächen/Volumen + Raumschemata berechnen wie in DOSSIER.

Bezug zur ROADMAP: Swisstopo/Terrain/OSM = Phase 4 (Kontext/Daten); SIA-416- Räume + Bilanz-CSV = Phase 2. Beide sind dort bereits als -Features gelistet.

Alle in diesem Dokument genannten geo.admin.ch-Endpunkte wurden am 2026-06-29 live gegen die echte API getestet (curl + CORS-Header-Check). Wo „verifiziert" steht, liegt eine echte Antwort vor.


Teil A — Swisstopo-APIs & Dienste aus dem Browser

A.0 Das Wichtigste vorweg: CORS & Lizenz

Zwei Fragen entscheiden, ob ein Dienst ohne Backend-Proxy aus einer reinen Browser-App nutzbar ist: CORS und Lizenz. Beide sind hier günstig.

CORS (live verifiziert): Alle relevanten Hosts senden access-control-allow-origin: *:

Host Dienst CORS Range-Requests
api3.geo.admin.ch REST (height, profile, identify, find, search) *
data.geo.admin.ch STAC-API + Daten-Assets (COG-GeoTIFF, XYZ.zip) * 206 Partial Content, accept-ranges/content-range vorhanden
wmts.geo.admin.ch WMTS-Kacheln *
3d.geo.admin.ch 3D-Tiles (tileset.json + glTF) *

Konsequenz: Höhenabfrage, Geocoding, Parzellen-Identify, Karten-/Orthofoto- Kacheln, COG-GeoTIFF-Höhenmodell per Range-Request und 3D-Tiles sind direkt aus dem Browser ohne eigenen Proxy abrufbar. Das ist ein großer Vorteil gegenüber vielen anderen nationalen Geodiensten.

Lizenz: swisstopo/geo.admin.ch ist Open Government Data: „The acquisition and use of data or services is free of charge, subject to the provisions on fair use." Kommerzielle Nutzung ist erlaubt, Einbindung in (auch kommerzielle) Web-Apps explizit gedeckt. Pflicht-Attribution: © swisstopo (bzw. „© Data: swisstopo"). „Fair use" = z.B. Web-App mit Ø 20'000 Nutzern/Tag ok; aggressives Bot-Scraping vermeiden. Haftung ausgeschlossen, ~98% Verfügbarkeit. Terms of use FSDI

⚠️ Korrektur zu DOSSIER & zur Doku: Die offizielle REST-Doku notiert beim Height-Service „This service is not freely accessible (fee required)". Das ist in der Praxis falsch / veraltet: Der Endpunkt antwortet anonym, ohne Key, mit 200 und CORS * (verifiziert, siehe A.1). DOSSIERs Aussage „alle APIs offen, ohne Auth, ohne Key" deckt sich mit der gemessenen Realität. Wir verlassen uns aber nicht blind darauf, sondern behandeln 402/429 defensiv (Retry/Backoff, Cache).

A.1 Höhenabfrage — Height-Service (Einzelpunkt)

Punkt-Höhe (DTM) aus swissALTI3D/DTM. Verifiziert:

GET https://api3.geo.admin.ch/rest/services/height?easting=2600000&northing=1200000&sr=2056
→ {"height":"555.5"}

Parameter:

  • easting, northing — LV95 (sr=2056) oder LV03 (sr=21781). Pflicht.
  • sr2056 (LV95) angeben, sonst Default 21781.
  • elevation_modelDTM2 (= swissALTI3D, 2 m), DTM25 (Default), COMB. (Im Tal lieferten DTM2/DTM25/COMB denselben Wert; im Steilgelände kann DTM2 genauer sein.)
  • callback — JSONP (brauchen wir wegen CORS nicht).

Nutzung im Tool: Projekt-Nullpunkt-Z bzw. „Gebäude auf Gelände setzen" — eine einzelne Höhe an der Projekt-Koordinate. Antwortzeit ~50150 ms. Quelle: GeoAdmin REST Height

A.2 Höhenprofil — Profile-Service (Schnittlinie)

Höhen entlang einer Polylinie — ideal für Geländeschnitt unter einem Gebäude-Schnitt. Verifiziert (echte Werte zurück):

GET https://api3.geo.admin.ch/rest/services/profile.json
    ?geom={"type":"LineString","coordinates":[[2600000,1200000],[2600200,1200000]]}
    &sr=2056&nb_points=3
→ [{"alts":{"COMB":555.5,"DTM2":555.5,"DTM25":555.5},"dist":0,"easting":2600000,"northing":1200000},
   {"alts":{...},"dist":100,...}, {"dist":200,...}]

Parameter: geom (GeoJSON-LineString, max 6'000 Punkte), sr, nb_points (Anzahl Stützpunkte, Default 200), elevation_models, offset (Glättung). Auch als profile.csv. → Für 2D-Geländeschnitte ohne Mesh-Download. Quelle: GeoAdmin REST Profile

A.3 swissALTI3D — Höhenmodell als COG-GeoTIFF (Mesh-Quelle)

Das ist der Schlüssel für das Gelände-Mesh im Browser. swissALTI3D ist das präzise DTM der Schweiz (ohne Vegetation/Bebauung), Auflösung 0.5 m / 2 m, alle 6 Jahre aktualisiert (swissALTI3D). Bezug über die STAC-API (verifiziert — Tile swissalti3d_2019_2599-1198):

GET https://data.geo.admin.ch/api/stac/v1/collections/ch.swisstopo.swissalti3d/items
    ?bbox=<lonMin,latMin,lonMax,latMax>&limit=...

Jedes 1×1-km-Tile liefert pro Auflösung zwei Asset-Typen:

Asset Typ Browser-tauglich?
..._0.5_2056_5728.tif / ..._2_2056_5728.tif Cloud-Optimized GeoTIFF, EPSG:2056 direkt via geotiff.js + Range
..._0.5_2056_5728.xyz.zip / ..._2_..._xyz.zip ASCII-XYZ (E N Z) in ZIP via fflate entpacken (so macht es DOSSIER)

Verifiziert: data.geo.admin.ch liefert auf das .tif ein 206 Partial Content mit content-range bei Range:-Header und CORS *. Das bedeutet: geotiff.js liest nur den benötigten Ausschnitt eines COG per HTTP-Range, ohne das ganze File zu laden — perfekt für eine Browser-App. Bbox in WGS84 für STAC, Tile-Daten dann in LV95-Metern (kein Reprojizieren der Z-Werte nötig). Quelle: STAC tech docs · COG-Tile live geprüft.

A.4 SWISSIMAGE / Karten — WMTS-Kacheln

Orthofoto (10 cm) und Landeskarten als Kacheln. RESTful-URL-Template:

https://wmts.geo.admin.ch/1.0.0/<Layer>/default/<Time>/<TileMatrixSet>/<z>/<TileCol>/<TileRow>.<ext>

Beispiel-Layer:

  • ch.swisstopo.swissimage — Orthofoto, .jpeg
  • ch.swisstopo.pixelkarte-farbe — Landeskarte farbig, .jpeg
  • ch.kantone.cadastralwebmap-farbeKatasterplan (AV), .png

TileMatrixSets: 2056 (LV95), 21781, 3857 (Web-Mercator), 4326. Zoom 028 (4000 m → 0.1 m); Zoom 27/28 nur für wenige Layer (swissimage, Kataster). Für 3D in Three.js am einfachsten 3857 (Standard-Slippy-Map-Schema, z/x/y), z.B.

https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.swissimage/default/current/3857/{z}/{x}/{y}.jpeg

Für planimetrisch exakte 2D-Arbeit besser 2056. CORS * (verifiziert). Quellen: WMTS docs · WMTS service · WMTS EPSG:2056 CodePen.

Es gibt zusätzlich klassisches WMS (https://wms.geo.admin.ch/, GetMap mit beliebiger BBox/Größe, ebenfalls EPSG:2056). Für ein einzelnes georeferenziertes Orthofoto-Rechteck unter dem Modell ist ein WMS-GetMap manchmal praktischer als WMTS-Kacheln zu stitchen. WMS docs

A.5 swissBUILDINGS3D — Nachbargebäude (3D)

Zwei Wege:

(a) 3D-Tiles (Streaming, Cesium-Format)glTF/tileset.json, für große Gebiete:

https://3d.geo.admin.ch/<Layer>/<Version>/<Time>/tileset.json

Layer u.a. ch.swisstopo.swissbuildings3d.3d, ch.swisstopo.swisstlm3d.3d, ch.swisstopo.swissnames3d.3d, ch.swisstopo.vegetation.3d. Version = v1, Time optional (ISO YYYYMMDD, weglassen = aktuellste). CORS * (verifiziert auf tileset.json). Direkt für CesiumJS gedacht; in reinem Three.js über @loaders.gl/3d-tiles oder den 3DTilesRendererJS (NASA-AMMOS/three.js-Community) ladbar. 3D-Tiles docs · Switzerland in 3D

(b) STAC-Tiles als CAD/Mesh-Datei (Download pro Tile) — so macht es DOSSIER: Collections ch.swisstopo.swissbuildings3d_3_0 (neu; in Städten z.T. >700 MB Tiles) und ch.swisstopo.swissbuildings3d_2 (1-km-Tiles, ~50 MB, stabil). Assets in .dxf/.dwg/.obj/.ifc (+ .zip), Varianten solid/separated. Für den Import als echte, editierbare Massen ins eigene Modell ist der OBJ/IFC-Tile-Weg besser als 3D-Tiles (die sind read-only Visualisierung). swissBUILDINGS3D: >3 Mio Gebäude, Lage-/Höhengenauigkeit 3050 cm.

Empfehlung: Für „Nachbarschaft als Kontext anzeigen" (Phase 4 Start) 3D-Tiles streamen (kein Download, kein Parsing). Wenn der Nutzer Nachbargebäude als Geometrie braucht (Verschattung, Abstand), STAC-OBJ-Tile laden und als Mesh importieren.

A.6 Parzelle / Kataster (AV) — Identify-Service

Verifiziert — Parzellen-Polygon aus einer Koordinate, in LV95:

GET https://api3.geo.admin.ch/rest/services/api/MapServer/identify
    ?geometry=2600423,1199521&geometryType=esriGeometryPoint
    &imageDisplay=100,100,96&mapExtent=2600323,1199421,2600523,1199621
    &tolerance=2&layers=all:ch.kantone.cadastralwebmap-farbe
    &returnGeometry=true&geometryFormat=geojson&sr=2056
→ {"results":[{"type":"Feature","bbox":[...],
     "geometry":{"type":"Polygon","coordinates":[[ [2600377.1,1199523.7], ... ]]},
     "attributes":{"number":"698","egris_egrid":"CH507635214670","ak":"BE", ...}}]}
  • Parzellen-Layer: ch.kantone.cadastralwebmap-farbe (liefert number, egris_egrid = EGRID, Kanton; mit returnGeometry=true&geometryFormat=geojson das Parzellen-Polygon in LV95-Metern → direkt als Grundstücksgrenze importierbar).
  • Gebäudeadressen: ch.swisstopo.amtliches-gebaeudeadressverzeichnis; Gebäude-/ Wohnungsregister ch.bfs.gebaeude_wohnungs_register (EGID).
  • Pflichtparameter: geometry, geometryType (esriGeometryPoint|...Polygon|...Envelope), mapExtent, imageDisplay, tolerance; sr=2056; max 50 Features/Request.

Quellen: Identify features · GeoAdmin REST Identify/Find · Live-Antwort oben.

A.7 Geocoding — SearchServer (Adresse → LV95)

Verifiziert (Adresse → Koordinate, deckt sich mit DOSSIERs geocode()):

GET https://api3.geo.admin.ch/rest/services/api/SearchServer
    ?searchText=Bundesplatz 3 Bern&type=locations&origins=address&sr=2056&limit=1
→ results[0].attrs: { label:"Bundesplatz 3 <b>3011 Bern</b>", lat:46.94677, lon:7.44419,
                      geom_st_box2d:"BOX(2600423.26 1199521.11, ...)", origin:"address", ... }
  • type=locations, origins aus {address, parcel, gg25, gazetteer, zipcode, district, kantone}, sr=2056. Im LV95-Modus liefert die Geo-Admin-Konvention y=East, x=North (DOSSIER liest genau so: e=attrs.y, n=attrs.x). Labels enthalten <b>-Tags (strippen).
  • type=featuresearch + features=<layer> durchsucht Attribute (z.B. Parzellennummer).

Quelle: Search · Live-Antwort oben.

A.8 Koordinatensystem LV95 / EPSG:2056 & Transformationen

Intern rechnet das BIM-Tool in Metern (ROADMAP-Konvention) und verschiebt den Projekt-Ursprung nahe (0,0,0); LV95-Koordinaten sind ~2.6 Mio / 1.2 Mio Meter groß und würden bei float32 (Three.js) zu Jitter führen → Origin-Shift Pflicht (siehe B.3). DOSSIER macht genau das (origin_shift/shift_lv95, typ. bbox-Center → 0/0/0).

Transformations-Optionen:

  1. proj4 (npm proj4@2.20.9) — universell, exakt. EPSG:2056-Definition:

    proj4.defs("EPSG:2056",
      "+proj=somerc +lat_0=46.9524055555556 +lon_0=7.43958333333333 +k_0=1 "+
      "+x_0=2600000 +y_0=1200000 +ellps=bessel "+
      "+towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs +type=crs");
    const [e,n] = proj4("EPSG:4326","EPSG:2056",[lon,lat]); // WGS84→LV95
    

    Genauigkeit mit dieser 3-Parameter-towgs84 ~1 m (für Kontext-Import völlig ausreichend). Types: @types/proj4. Quellen: epsg.io/2056 · proj4js.

  2. Näherungsformeln (CH1903→WGS84, swisstopo) — DOSSIERs Ansatz, ~1 m genau, 0 Dependencies (zwei kleine Funktionen lv95_to_wgs84/wgs84_to_lv95). 1:1 nach TS portierbar; gut, wenn man proj4 nicht ziehen will. Reicht, weil STAC-Queries ohnehin nur eine grobe WGS84-Bbox brauchen und alle Daten schon in LV95 kommen.

  3. swisstopo REFRAME Web-API — cm-genaue offizielle Umrechnung (LV95↔WGS84, LN02↔Bessel). Nur nötig, wenn Vermessungs-Genauigkeit verlangt wird. REST, online. REFRAME Web

Empfehlung: proj4 mit fester EPSG:2056-Def (eine Abhängigkeit, exakt genug, wartungsarm) — oder, wenn Dependency-Geiz, DOSSIERs Formeln portieren. REFRAME nur bei Bedarf nachrüsten.

A.9 Endpoint-Übersicht (Spickzettel)

Zweck Endpoint Frei/CORS Format
Punkt-Höhe api3…/rest/services/height JSON
Höhenprofil (Schnitt) api3…/rest/services/profile.json JSON/CSV
Gelände-Mesh (COG) STAC …/swissalti3d/items.tif (COG, 2056) Range GeoTIFF
Gelände (ASCII) STAC …/swissalti3d.xyz.zip XYZ in ZIP
Orthofoto/Karte wmts…/1.0.0/<layer>/…/{z}/{x}/{y}.jpeg Kacheln
3D-Nachbargebäude (stream) 3d…/ch.swisstopo.swissbuildings3d.3d/v1/tileset.json 3D-Tiles/glTF
3D-Gebäude (Datei) STAC …/swissbuildings3d_2.obj/.ifc OBJ/IFC
Parzelle/Kataster api3…/MapServer/identify layers=all:ch.kantone.cadastralwebmap-farbe GeoJSON
Geocoding api3…/SearchServer?type=locations JSON

Teil B — Standort-Kontext importieren (Terrain + Parzelle + Nachbargebäude)

So bekommt ein Projekt seinen realen Kontext „auf Knopfdruck". Der Ablauf folgt DOSSIER (rhino/swisstopo.py), übersetzt auf Browser-Libs.

B.1 Pipeline (End-to-End)

Adresse/Parzelle  ──SearchServer──▶  Zentrum (E,N) in LV95
        │
        ├─ radius r  ──▶  bbox_LV95 (E±r, N±r)  ──proj4/Formeln──▶  bbox_WGS84
        │
        ├─[Parzelle]  identify(cadastralwebmap, point) ─▶ Polygon (LV95) ─▶ Grundstücksgrenze (Ebene 01 Vermessung)
        │
        ├─[Gelände]   STAC(swissalti3d, bbox_WGS84) ─▶ COG .tif(2056)
        │               └─ geotiff.js readRasters(window) ─▶ Höhen-Grid (E,N,Z, m)
        │               └─ Three.js BufferGeometry (Grid→Mesh) [optional: TIN, Höhenlinien, Volumen]
        │
        ├─[Orthofoto] WMTS swissimage ─▶ Textur auf Gelände-Mesh ODER georef. Plane
        │
        └─[Nachbarn]  3D-Tiles streamen (Anzeige)  ODER  STAC swissbuildings3d_2 .obj ─▶ Mesh-Import
                      (Weltweit/ausserhalb CH: OSM-Overpass als Fallback, siehe B.5)
   ──▶ alle Geometrien um origin_shift (bbox-Center→0/0/0) verschoben, Z aus ALTI3D

B.2 Gelände-Mesh aus swissALTI3D (Kern, Phase 4)

Empfohlener Browser-Weg (COG + geotiff.js):

  1. STAC-Query mit bbox_WGS84 → Liste der überlappenden Tiles; pro Tile das gewünschte COG-Asset (_2_2056_ für 2 m, _0.5_2056_ für 0.5 m).
  2. geotiff.js: const tiff = await fromUrl(href) → COG; image.readRasters({window}) liest nur den Ausschnitt (Range-Requests, da CORS+Range bestätigt). Ergebnis ist ein reguläres Z-Raster mit bekanntem Origin/PixelScale (LV95-Meter) aus den GeoKeys/image.getOrigin()/image.getResolution().
  3. Raster → THREE.BufferGeometry: ein Vertex pro Rasterpunkt (EshiftE, NshiftN, ZshiftZ), Faces als zwei Dreiecke pro Zelle (DOSSIER: mesh_from_grid, gleiche Logik), computeVertexNormals(). Bei 0.5 m wird das Mesh groß → bei Bedarf raumräumlich sub-samplen (DOSSIER macht ganzzahliges Sub-Sampling auf dem globalen LV95-Raster, damit Nachbar-Tiles nahtlos zusammenpassen).
  4. Mehrere Tiles: erst zu einem Grid mergen (gemeinsamer Origin/Step), dann meshen — sonst entstehen Nähte (DOSSIER: merge_grids).

Alternativweg (XYZ, exakt wie DOSSIER): .xyz.zip laden → mit fflate (npm, schnellster Inflate im Browser) entpacken → ASCII E N Z parsen → gleiches Grid. Robust, aber überträgt mehr Bytes als der COG-Range-Weg. Für den Port empfehle ich COG primär, XYZ als Fallback.

Bibliotheken: geotiff@3.0.5, fflate (XYZ-Variante), three@0.185.0. geotiff.js · 3D-Terrain aus GeoTIFF mit Three.js.

Ableitungen wie in DOSSIER (alle aus dem Grid, in Phase 4 portierbar):

  • Höhenlinien (Marching-Squares auf dem Grid; npm d3-contour oder marchingsquares) — für 2D-Plan.
  • TIN / Patch (Delaunay aus den Punkten; npm delaunator) — alternatives Mesh.
  • Geschlossenes Gelände-Volumen (Boden N m unter tiefstem Punkt) → gefüllte Querschnitte beim Schnitt-Cut (DOSSIER terrainVolume/terrainVolumeDepth).

B.3 Origin-Shift (Pflicht)

LV95-Koordinaten (~2.6e6) sprengen float32. Beim Import einmal shift = (eCenter, nCenter, zRef) festlegen, alle Geometrien shift rechnen, und shift am Projekt persistieren (für Re-Import / Geo-Referenz / Norden). DOSSIER: origin_shift/shift_lv95, plus „Auto-Zoom auf Import" (ROADMAP §11). Damit bleibt das Modell metergenau und der Rückweg in echte LV95-Koordinaten (Export, weitere swisstopo-Abfragen) ist + shift.

B.4 Parzelle + Orthofoto

  • Parzelle: identify(...cadastralwebmap..., returnGeometry=true, geometryFormat=geojson) → Polygon (LV95) → shift → als geschlossene Polylinie auf Ebene 01 Vermessung. Attribute number/egris_egrid am Objekt/Projekt speichern.
  • Orthofoto: WMTS swissimage-Kacheln über die Modell-Bbox stitchen → eine Textur, als Material auf das Gelände-Mesh oder auf eine georeferenzierte Plane (DOSSIER: add_ortho_plane, mit UV-Shift gegen Tile-Nähte). Für 3D ist 3857 einfacher, für exakte 2D-Lage 2056.

B.5 OSM-Overpass als weltweiter Fallback (Phase 4)

Ausserhalb der Schweiz (oder wenn nur 2D-Footprints/Straßen reichen): DOSSIER hat einen Overpass-Importer (https://overpass-api.de/api/interpreter, POST) mit 7 Kategorien (Straßen/Gebäude/Wasser/Wasserläufe/Grün/Wege). Liefert OSM-Ways → Polylinien. Im Browser identisch nutzbar (fetch POST). Overpass koordiniert in WGS84 → mit proj4→LV95→shift. Hinweis: Overpass-CORS ist beim Haupt-Server meist offen, kann aber je nach Mirror variieren; ggf. anderen Mirror wählen. Overpass API.

B.6 Was sich von DOSSIER nicht 1:1 portieren lässt

  • Rhino-_-Import für DXF/DWG/OBJ und _-MeshPatch/Delaunay-Commands gibt es im Browser nicht → ersetzen durch JS-Parser/Algorithmen (OBJ: three-OBJLoader; Delaunay: delaunator; Contours: d3-contour).
  • Filesystem-Cache neben der .3dm → Browser: IndexedDB-Cache (Cache-API für Kacheln). Passt zur ROADMAP-Phase 5 (IndexedDB-Persistenz).
  • IFC-Import von swissBUILDINGS3D 3.0 → über web-ifc (ohnehin im Stack, Phase 4).

Teil C — SIA 416 (Flächen/Volumen) & SIA 421 + DOSSIER-Logik

C.1 SIA 416 — Flächen- und Volumenhierarchie

SIA 416:2003 „Flächen und Volumen von Gebäuden" ist die in der CH gültige Norm und Berechnungsbasis für Kostenplanung/Flächennachweise. Sie kennt vier Bereiche: GSF (Grundstück), GF (Geschossflächen), AGF (Aussengeschossflächen), GV (Volumen). Maßgeblich ist die effektive Geometrie (keine fiktiven Zuschläge mehr). Quellen: SIA 416 Übersicht (siworks/DBV) · SIA-Shop 416/2003 · Flächenkennzahlen SIA 416 (Ginesta, PDF).

Hierarchie & Formeln (verifiziert):

GSF  Grundstücksfläche
GF   Geschossfläche  = KF + NGF
 ├─ KF   Konstruktionsfläche      (Wände/Stützen; tragend KFT + nicht tragend KFN)
 └─ NGF  Nettogeschossfläche      = NF + VF + FF
      ├─ NF   Nutzfläche          = HNF + NNF
      │    ├─ HNF  Hauptnutzfläche   (zweckbestimmte Hauptnutzung: Wohnen, Büro …)
      │    └─ NNF  Nebennutzfläche   (Lager, Bad/WC, Abstell-, Nebenräume)
      ├─ VF   Verkehrsfläche       (Erschließung: Flure, Treppen, Lifte)
      └─ FF   Funktionsfläche      (Gebäudetechnik: Heizung, Lüftung, Technik)
AGF  Aussengeschossfläche         (Balkone, Terrassen, gedeckte Aussenflächen)
GV   Gebäudevolumen [m³]
Abk. Deutsch Inhalt (Kurz)
GSF Grundstücksfläche Parzellenfläche (aus Kataster, Teil A.6)
GF Geschossfläche allseits umschlossene + überdeckte Grundrissflächen, geschossweise
KF Konstruktionsfläche Bauteile (Wände/Stützen), nicht begehbar; KFT tragend / KFN nicht tragend
NGF Nettogeschossfläche begehbare Fläche innerhalb der Umschließung = NF+VF+FF
NF Nutzfläche tatsächlich nutzbar = HNF+NNF
HNF Hauptnutzfläche zweckbestimmte Hauptnutzung
NNF Nebennutzfläche dienende Nebenräume (Lager, Bad, WC)
VF Verkehrsfläche horizontale/vertikale Erschließung
FF Funktionsfläche Gebäudetechnik
AGF Aussengeschossfläche Balkone/Terrassen u.ä.
GV Gebäudevolumen umbauter Raum [m³]

Versionshinweis: Es kursiert eine Revision SIA 416:2017 mit präzisierten Begriffen, in der Praxis wird aber breit weiter 416:2003 referenziert. Für unser Tool reicht die Klassifikation HNF/NNF/VF/FF/GF/AGF + Bilanz; die genaue Auflage nur als Label dokumentieren. Verbindliche Definitionen stehen im kostenpflichtigen Normtext (SIA-Shop) — die hier zitierten freien Quellen stimmen in der Struktur überein.

C.2 SIA 421 — Flächengliederung für Bewirtschaftung/Vermietung

SIA 421:2006 „Flächengliederung und Mengenangaben" (Korrigenda C1:2014) baut auf der SIA-416-Systematik auf und gliedert Flächen für Immobilien-Bewirtschaftung und Vermietung (Mietflächen, Nutzungseinheiten, Zuordnung von VF/FF zu Mietern). Relevant, sobald wir Mietflächen-/Bewirtschaftungs-Auswertungen wollen (über den reinen Architektur-Nachweis hinaus). Für den ersten Wurf nicht zwingend — SIA 416 reicht für Flächennachweis und Raumschema. SIA 421 ist die natürliche Erweiterung, wenn Property-Management-Features kommen. Quellen: SIA 421:2006 (PDF Inhalt) · Korrigenda C1:2014 (PDF).

C.3 Wie DOSSIER SIA macht (Vorlage für den Port)

Quellcode: rhino/elemente.py (Räume) + rhino/elemente_uebersicht.py (Bilanz/CSV). Kernpunkte, die wir 1:1 übernehmen:

Datenmodell pro Raum. Ein Raum ist eine geschlossene Outline-Curve + ein Text-Stempel. Klassifikation über das Feld dossier_raum_sia mit Werten {"", hnf, nnf, vf, ff, gf, agf} (_RAUM_SIA_KINDS). Weitere Felder: name, nummer, funktion (wohnen|schlafen|bad|kueche|essen|flur|…), personen (für Personenbelegung/Brandschutz), Rundung, Stempel-Layout.

Flächen-/Umfangsberechnung (_raum_amp): Fläche aus AreaMassProperties (≙ in JS Shoelace-Formel über das Polygon), Umfang = Kurvenlänge, plus Zentroid für den Stempel. Im Browser: Polygon-Fläche selbst rechnen (Shoelace), kein Mesh nötig — exakt und schnell. Rundungsstufen (_format_area): exakt|0.01|0.1|0.5|1 (z.B. 0.5 = round(a*2)/2).

SIA-Bilanz (compute_sia_bilanz, scope = total | geschoss:<id>): summiert Raumflächen je Klasse, dann:

NF  = HNF + NNF
NGF = NF + VF + FF        (GF/AGF separat aggregiert, zählen nicht in NGF)

(genau die Formeln aus C.1). Ergebnis je Geschoss + Total.

Farb-/Darstellungs-Konvention (_SIA_COLORS_HEX, Pastell): HNF rot #e8a8a8, NNF orange #e8c498, VF gelb #e8d878, FF hellblau #a8c8e0, GF grau #d0d0d0, AGF hellgrün #c0d8c0. Umgesetzt als regelbasierte Overrides (_build_sia_preset_rules, Preset „SIA-Raeume"): Bedingung user_string == code → Outline-Farbe + Solid-Hatch. → Passt 1:1 zur geplanten Overrides-Engine (ROADMAP §2c/§11).

Export (_cmd_export_raeume, _export_bilanz): CSV, Semikolon + UTF-8-BOM (CH/DE-Excel), Dezimal-Komma. Raumliste: Nummer; Name; Geschoss; Funktion; SIA; Fläche; Fläche gerundet; Umfang. Bilanz: eine Spalte je Geschoss + Total, Zeilen je Kategorie. → Im Browser: Blob + Download (kein SaveFileDialog), gleiche CSV-Struktur. Optional direkt .xlsx via sheetjs/exceljs.

Layer-Routing: GF→61_GF, AGF→62_AGF, Rest→60_RAEUME (_layer_path_for_raum_sia) — damit Geschossflächen-Outlines getrennt schalt-/exportierbar sind. Übersetzt sich auf unsere Ebenen-Codes (60 Räume).

Was wir im Port besser/anders machen:

  • Fläche per Shoelace statt Rhino-Mass-Props (0 Deps).
  • Bilanz reaktiv aus dem semantischen Modell (Zustand-Store) statt Doc-Scan.
  • Space = Slab-/Raum-Polygon mit siaClass im Datenmodell (ROADMAP: Space { boundary, name }), Bilanz als abgeleitete Sicht.

Teil D — Umsetzungsplan (Endpunkte · Libs · Phase)

Reihenfolge orientiert sich an der ROADMAP (SIA = Phase 2, Geo = Phase 4) und an „größter Nutzen zuerst, geringste Abhängigkeit zuerst".

Phase 2 — SIA-Räume (kein Netz, reine Logik)

Endpunkte: keine. Libs: keine (Shoelace selbst), optional exceljs/sheetjs für .xlsx.

  1. Space-Modell: { boundary[], geschossId, name, nummer, funktion, siaClass∈{hnf,nnf,vf,ff,gf,agf}, personen }.
  2. computeArea (Shoelace) + Umfang; Rundungsstufen (exakt|0.01|0.1|0.5|1) wie DOSSIER _format_area.
  3. computeSiaBilanz(scope){hnf,nnf,nf,vf,ff,ngf,gf,agf,count,personen} mit nf=hnf+nnf, ngf=nf+vf+ff.
  4. SIA-Farbpalette + Stil-Override (Outline-Farbe/Solid-Fill) in der Overrides-Engine.
  5. Raumstempel-Renderer (Felder-Layout) + CSV-Export (Semikolon, UTF-8-BOM, Komma) für Raumliste und Bilanz. Ergebnis: SIA-416-Flächennachweis + Raumschema, Excel-kompatibel — vor jeder Geo-Arbeit nutzbar.

Phase 4a — Geo-Grundlage: Koordinaten + Standortabfrage

Endpunkte: SearchServer (Geocoding), height (Punkt-Z), identify (Parzelle, cadastralwebmap-farbe). Libs: proj4@2.20.9 (+ @types/proj4).

  1. proj4-EPSG:2056-Def + Helfer lv95↔wgs84, bboxLv95→bboxWgs84 (DOSSIER-Logik).
  2. Origin-Shift-Mechanik + Persistenz am Projekt (shift = bbox-Center), Auto-Zoom.
  3. Adresssuche → Zentrum; „Gelände-Höhe holen" (height); „Parzelle holen" → Polygon auf Ebene 01 Vermessung (+ EGRID/Nummer am Projekt). Ergebnis: Projekt ist georeferenziert; Parzelle + Adresse + Geländehöhe vorhanden.

Phase 4b — Gelände-Mesh + Orthofoto

Endpunkte: STAC swissalti3d (COG .tif, 2056) + profile.json; WMTS swissimage. Libs: geotiff@3.0.5, three@0.185.0, optional fflate (XYZ-Fallback), d3-contour/marchingsquares (Höhenlinien), delaunator (TIN).

  1. STAC-Query (bbox) → COG-Tiles; geotiff.js Range-Read → Grid; Tiles mergen.
  2. Grid → THREE.BufferGeometry (DOSSIER mesh_from_grid/merge_grids); Sub-Sampling auf globalem LV95-Raster; Normalen.
  3. Optional: Höhenlinien (2D-Plan), TIN, geschlossenes Volumen (Schnitt-Füllung).
  4. WMTS-swissimage-Kacheln → Textur auf Mesh/Plane (DOSSIER add_ortho_plane).
  5. Geländeschnitt im 2D-Plan via profile.json entlang der Schnittlinie. Ergebnis: echtes Gelände mit Orthofoto unter dem Gebäude; Geländeschnitte.

Phase 4c — Nachbargebäude + weltweiter Fallback

Endpunkte: 3D-Tiles ch.swisstopo.swissbuildings3d.3d/v1/tileset.json (Anzeige) oder STAC swissbuildings3d_2 .obj/.ifc (Import); OSM overpass-api.de. Libs: @loaders.gl/3d-tiles@4.4.3 oder 3DTilesRendererJS; three-OBJLoader; web-ifc (für 3.0-IFC); proj4.

  1. Kontext-Anzeige: 3D-Tiles in den Three-Scenegraph streamen (kein Download).
  2. Bedarf an echter Geometrie (Verschattung/Abstand): STAC-OBJ-Tile → Mesh-Import → shift.
  3. Ausserhalb CH / nur 2D: Overpass-POST → Ways → Polylinien (Ebene 70 OSM). Ergebnis: Nachbarschaftskontext (CH 3D, weltweit OSM).

Querschnitt (alle Geo-Phasen)

  • Caching: IndexedDB für STAC-Antworten + COG-Bytes + Kacheln (ersetzt DOSSIERs Disk-Cache); Cache-Schlüssel = Tile-ID/URL.
  • Defensive HTTP: Timeouts, Retry/Backoff, 402/429 abfangen, Größen-Limit pro Tile (DOSSIER: 200-MB-Guard).
  • Attribution: „© swisstopo" sichtbar einblenden, „© OpenStreetMap-Mitwirkende" bei OSM.
  • Worker: GeoTIFF-Parsing + Mesh-Bau im Web-Worker (Comlink, ROADMAP-Stack), UI bleibt flüssig.

Empfohlener Library-Satz (npm, aktuell)

proj4@2.20.9 · geotiff@3.0.5 · three@0.185.0 · fflate (XYZ) · @loaders.gl/3d-tiles@4.4.3 oder 3DTilesRendererJS · delaunator · d3-contour · web-ifc (im Stack) · exceljs/sheetjs (optional, .xlsx).


Quellen