# BIM-Elementtiefe — Tür, Fenster, Dach, Decke ("wirklich 1:1") ## 0. Zweck und Abgrenzung DOSSIER modelliert Bauteile heute semantisch (kein reines Zeichenprogramm) und hat für Wand/Decke bereits eine mehrschichtige Aufbaulogik (`Component[]` via `WallType`/`CeilingType`). Türen und Fenster haben seit `docs/design/window-editor-vectorworks-study.md` einen dedizierten, phasierten Ausbauplan (Flügeltabelle, Verglasung, Sonnenschutz). Was fehlt, ist die gleiche Tiefe für **Dach** (keine Schichtlogik, keine Mansard- Untertypen, kein Kehl-/Gaubenmodell) und für die **Decken-Randterminierung** (Deckenrand als reines Polygon ohne Kantendetail). Dieses Dokument nimmt die vier Bauteile Tür, Fenster, Dach, Decke und hält sie gegen die reale Tiefe vollständiger BIM-Programme (Vectorworks Architektur, ArchiCAD, Revit, Allplan). Ziel ist NICHT, jedes Feature dieser Programme zu kopieren, sondern zu benennen, welche Lücken einen echten "1:1-Zuwachs" für ein Einfamilienhaus-/Wohnbau-Tool wie DOSSIER bringen — und welche reiner Ballast wären (Abschnitt 6). Für Fenster/Tür dupliziert dieses Dokument NICHT die Mapping-Tabelle aus `window-editor-vectorworks-study.md` — es referenziert sie und ergänzt, was dort fehlt (v. a. Tür-Tiefe, die die Studie nur am Rand behandelt, und die architektonischen Grenzen des heutigen Öffnungsmodells). Für Wand-Schichtlogik siehe `docs/design/parametric-walls.md` (Raster/Modul-Regeln, nicht Gegenstand hier) und `docs/design/elements.md` (ältere Gesamtplanung, Stand vor der aktuellen `Component`/`Layer`-Implementierung — dort abweichende Typnamen wie `Slab`/`ProfileDef`, hier durchgängig der IST-Code zitiert). Alle IST-Aussagen sind mit Datei:Zeile belegt (verifiziert per Lesen des Codes, Stand dieses Commits). Status-Legende der Lücken-Tabellen: **✓** vorhanden und gerendert · **~** Feld existiert, Renderer liest es nicht oder nur grob · **✗** fehlt vollständig. Priorität P0 (grösster 1:1-Zuwachs, bald) … P3 (Ballast, nur auf Nachfrage). Aufwand grob in Personentagen (PT). --- ## 1. Gemeinsames Fundament: das Schicht-Muster Der zentrale Baustein, den DOSSIER bereits hat und der sich wiederverwenden lässt, ist `Component`/`Layer`: - `Component` (`src/model/types.ts:196`) — ein Bauteil-Material: Poché-Farbe (`color`/`foreground`/`background`), Schnitt-Schraffur (`hatchId`) UND Ansichts-Schraffur (`viewHatchId`, für unaufgeschnittene Aufsicht), optionales PBR-Material (`material`), Kürzel (`abbrev`) und ein Verschneidungs-Rang (`joinPriority`, `types.ts:241`) für die Boolean- Dominanz am Stoss. - `Layer` (`types.ts:245`) — eine Schicht: `componentId` + `thickness` + optionaler Fugen-Linienstil (`jointLineStyleId`). - `WallType` (`types.ts:260`) und `CeilingType` (`types.ts:273`) sind BEIDE nur `{ id, name, layers: Layer[] }` — bewusst derselbe Typ, "das horizontale Gegenstück zum WallType" (Kommentar `types.ts:266-271`). Das Muster ist also bereits zweimal (Wand, Decke) verifiziert: `ceilingThickness()` (`types.ts:2104`) summiert die Layer-Dicken, `emitSlabs()` (`src/plan/toWalls3d.ts:1352-1419`) stapelt sie im 3D als einzelne `RSlab`-Scheiben proportional in `[zBottom, zTop]`, `addCeilingPoche` (`src/plan/generatePlan.ts:2453`) zeichnet die Aufsicht mit der Ansichts-Schraffur der ERSTEN Schicht, und `toSection.ts:633` (`splitSlabLayers`) zerlegt die Decke im ECHTEN Schnitt in Einzel-Bänder je Schicht (mit `resolveCeilingSectionStyle`, `generatePlan.ts:591`, als Schraffur-/Farbquelle). **Der Dach-Vorschlag in Abschnitt 4 ist im Kern: dasselbe Muster ein drittes Mal anwenden.** Das ist der günstigste Weg zu echter Dach-1:1-Tiefe, weil Layer-Resolver, Schraffur-Ketten (`resolveHatch`/`resolveForeground` etc., `generatePlan.ts:409-536`) und die 3D-Stapel-Logik bereits bestehen und nur auf einen neuen Aufbau-Typ angewendet werden müssen statt neu erfunden. Architektonische Randbemerkung: `Project` führt bereits `wallTypes`, `ceilingTypes?`, `doorTypes?`, `windowTypes?`, `stairTypes?` (`types.ts:1936-1958`) als eigene Bibliotheken — aber **kein `roofTypes?`**. `Roof` (`types.ts:1022`) trägt nur ein einzelnes `thickness: number` (`types.ts:1044`), keinen Aufbau-Verweis. Das ist die strukturelle Lücke, die Abschnitt 4 schliesst. --- ## 2. Tür (Door) ### 2.1 Was ein vollständiges BIM-Tool bietet | Bereich | Typische Parameter (VW/ArchiCAD/Revit/Allplan) | |---|---| | Bauart | Dreh-, Schiebe- (auf/vor Wand), Falt-, Pendel-, Karusselltür, reiner Durchbruch | | Blattzahl/-teilung | 1-/2-flügelig, Gangflügel + Standflügel (unterschiedliche Breite), Seitenteile links/rechts | | Blattausführung | glatt, kassettiert, Glasfüllung (Anteil/Sprossenbild), Brandschutz-/Schallschutz-Kennwert | | Rahmen/Zarge | Zarge vs. Blockrahmen, Rahmenbreite je Kante, Zargentiefe, Bekleidung/Abdeckleiste, Falz | | Schwelle | ohne, Alu-Flachschwelle, Anschlagdichtung, Bodenanschluss/Gefälle bei Aussentüren | | Sturz/Oberlicht | festverglastes Oberlicht mit eigenem Rahmen, Kämpfer, Sprossenbild | | Seitenteile | fest verglaste Seitenteile links/rechts, eigene Breite | | Form | rechteckig, Rundbogen, Segmentbogen, Stichbogen — bei Aussen-/Haustüren verbreitet | | Beschlag | Drücker/Knauf-Typ, Schild, Schliesszylinder, Bänder sichtbar/verdeckt | | 2D-Darstellung | Blatt + Schwenkbogen (Grundriss), eigene Ansichtssymbolik in Schnitt/Elevation, Sturzlinien | | Material/Schichten | Blatt-Kernaufbau (bei Brand-/Schallschutztüren mehrschichtig, analog Wand) | | IFC-Rolle | `IfcDoor` mit `IfcDoorType` (PredefinedType), `OverallWidth/Height`, `IfcDoorPanelProperties`, Void in der Wirtswand | ### 2.2 IST in DOSSIER `Opening` mit `kind: "door"` (`src/model/types.ts:1068`) referenziert optional einen `DoorType` (`types.ts:296`). Vorhanden am Typ: `kind` ("dreh"/"schiebe"/"wandoeffnung", :303), `leafCount` (1|2, :305), `leafStyle` ("glatt"/"kassette"/"glas", :307), `glazingRatio` (:309), `frameThickness`/ `frameDepth`/`frameKind`("zarge"/"blockrahmen")/`frameWidth` (:311-328), `insetFromFace`/`insetFace` (:335-337), `transomHeight` (:343), `threshold` (:349). Am Element selbst: `swing`/`hinge`/`swingAngle`/ `openingDir` (:1104-1108), `lintelLines` (Sturzlinien, :1119) und `doorType: "normal"|"wandoeffnung"` (:1100) — ein zweites, mit `DoorType.kind` teilweise redundantes Feld. Renderer-Konsum, real geprüft: - **2D-Blatt ist IMMER einflügelig.** `addOpeningSymbol` (Tür-Zweig, `src/plan/generatePlan.ts:2091-2213`) zeichnet genau EINE Blattlinie (`sym.hinge → sym.openEnd`) und EINEN Schwenkbogen — `DoorType.leafCount` wird an keiner Stelle in `generatePlan.ts` gelesen (kein Treffer für `leafCount` im ganzen Plan-Renderer). Eine zweiflügelige Tür sieht im Plan aus wie eine einflügelige. - **3D genauso**: `resolveOpeningFrame` (`src/plan/toWalls3d.ts:1861-1886`) setzt für Türen hart `wingCount: 1`, unabhängig von `leafCount`. - `leafStyle` wirkt NUR binär: `"glas"` schaltet eine volle Verglasung frei (`glazed: dt.leafStyle === "glas"`, `toWalls3d.ts:1883`) — `glazingRatio` (Teilverglasung, z. B. 60 % Glasanteil im oberen Blattbereich) wird an keiner Stelle gelesen. "kassette" (Kassettentür) hat keine eigene Geometrie, fällt auf dieselbe Quader-Darstellung wie "glatt" zurück. `frameKind: "blockrahmen"` wirkt NUR im 2D-Rahmenband (`generatePlan.ts:1996`, `isBlock`), im 3D gibt es keinen Unterschied zur Zarge (`frameMeshesForOpening`, `toWalls3d.ts:1936`, kennt kein `frameKind`). - `threshold` steuert `hasSill` im 3D-Rahmen (`toWalls3d.ts:1880`), was einen einfachen Schwellen-Riegel zeichnet — kein eigenes Schwellenprofil, keine Gefälle-/Dichtungsdarstellung. - Es gibt eine ZWEITE, ältere Tür-Repräsentation: `Door` (`types.ts:1333`, `project.doors: Door[]`) mit eigenem Symbol-Renderer `addDoorSymbol` (`generatePlan.ts:1840-1899`) — strukturell identisch zum `Opening`-Pfad, aber ohne jeden Typ-Bezug. Zwei parallele Datenwege für dieselbe Bauteilart sind selbst technische Schuld, nicht nur ein BIM-Feature-Gap. - Form (Rundbogen etc.) existiert nicht: `Opening.width`/`height` sind ein reines Rechteck, `wallGaps`/`buildWallFootprints` (`generatePlan.ts:1363-1457`) schneiden nur rechteckige Bänder aus der Wand-Poché. - IFC-Export: `IfcDoor` wird erzeugt (`src/export/exportIfc.ts:30-31`), aber als reine Box-Geometrie ohne `IfcDoorType`/`PredefinedType` und ohne `IfcOpeningElement`-Void (bewusste Design-Entscheidung, siehe Kommentar `exportIfc.ts:18-31`: das Loch steckt bereits im geschnittenen Wand-Mesh). ### 2.3 Lücken (Tür) | Feature | Status | Priorität | Aufwand | |---|---|---|---| | Zweiflügelige Tür rendert 2 Blätter (2D+3D) | ✗ (`leafCount` ungelesen) | **P0** | 2 PT | | Teilverglasung nach `glazingRatio` (2D-Linie + 3D-Split) | ✗ | P1 | 1.5 PT | | Kassettentür eigene Blattgeometrie (Füllungsfelder) | ✗ | P2 | 2 PT | | `frameKind` (Blockrahmen) auch im 3D wirksam | ~ | P1 | 1 PT | | Seitenteile (feste Verglasung links/rechts der Tür) | ✗ | P1 | 2 PT | | Rundbogen-/Segmentbogen-Türform | ✗ | P2 | 4 PT (braucht gekrümmten Wandausschnitt, s. §5.3) | | Schwellenprofil (Alu-Flachschwelle, Dichtung) statt Riegel | ✗ | P2 | 1 PT | | `Door`/`Opening`-Doppelpfad konsolidieren | technische Schuld | P1 | 3 PT (Migration) | | Beschlag (Drücker/Knauf) als Mesh + 2D-Symbol | ✗ | P2 | 1.5 PT | | IFC `IfcDoorType`/PredefinedType/OverallWidth-Height-Properties | ~ | P2 | 1 PT | ### 2.4 Umsetzungsvorschlag **Modell**: `DoorType.leafs?: { width: number; hingeSide: "left"|"right"; fixed?: boolean }[]` analog `WindowType.sashes` (`SashDef`, `types.ts:367`) — bewusst dieselbe Struktur, damit `resolveSashSpans` (`toWalls3d.ts:2019`) UND die 2D-Pfostenlinien-Logik direkt wiederverwendet werden können, statt eine Tür-eigene Variante zu bauen. Ein `fixed: true`-Leaf ist das Seitenteil. `glazingRatio` wandert vom Skalar zu einer klaren Geometrie: Kämpferhöhe innerhalb des Blatts, gerendert wie das bestehende Oberlicht (`transomHeight`), nur INNERHALB des Blattrahmens statt darüber. **2D**: `addOpeningSymbol` (Tür-Zweig) über die Leaf-Liste iterieren statt einer festen Blattlinie; pro Leaf ein eigenes `hinge`/`swing` (Default: alternierend wie bei Fenstern, `sashesOfWindowType`, `types.ts:2132`). **3D**: `resolveOpeningFrame` liefert `wingCount = leafs.length` statt hart 1; `frameMeshesForOpening` (bereits generisch über `params.sashes`) übernimmt die Mehrflügel-Darstellung ohne Änderung — das ist der Vorteil der Struktur-Wiederverwendung. **UI**: Im Tür-Editor (sofern nach dem Muster von `window-editor-vectorworks-study.md` gebaut) eine Flügeltabelle wie bei Fenstern, nur mit Tür-Vokabular (Gangflügel/Standflügel statt Flügel 1/2). --- ## 3. Fenster (Window) Für Fenster existiert bereits eine vollständige Referenzmatrix in `docs/design/window-editor-vectorworks-study.md` §2 (Basiseinstellungen, Grösse, Brüstung, Rahmen, Flügeltabelle, Laibung/Form/Ober-Unterlicht, Sonnenschutz/Beschlag, Attribute/IFC) mit eigener P0–P3-Phasierung. Diese Studie ist der massgebliche Bezugspunkt; hier nur die Delta-Punkte, die dort fehlen oder seither vom IST abweichen. ### 3.1 IST-Ergänzung (was die Studie nicht/knapp behandelt) - `WindowType.glazing` (einfach/zweifach/dreifach) ist bis heute NICHT renderwirksam — bestätigt weiterhin: `glazingPanesOf()` (`types.ts:2149`) wird von `glassPanesForOpening` in `toWalls3d.ts` konsumiert, aber die Studie selbst vermerkt (Zeile 61-65 dort), dass der 2D-Pfad die Scheibenzahl weiterhin allein aus `DetailLevel` ableitet, nicht aus `glazingPanes`. Das ist über ein Jahr nach der Studie noch offen — ein Hinweis, dass P0/P1-Posten aus Fenster-Studien real liegen bleiben, wenn niemand sie explizit nachzieht. - `sillBoard` (Fensterbank keine/innen/aussen/beide, `types.ts:447`) ist weiterhin ungenutzt (kein Treffer für `sillBoard` in `toWalls3d.ts` oder `generatePlan.ts` ausserhalb der Typ-Definition und des Editors) — entspricht dem in der Studie als P1 markierten "Fensterbank erstellen". ### 3.2 Architektonische Grenze: gekrümmte Öffnungen Sowohl die Fenster-Studie (§2.6, "Form Eckig/Schräg/Spitz/Rund", P2, 4 PT) als auch dieser Auftrag nennen Rundbogen-/Spitzbogenfenster. Das ist teurer, als die Aufwandschätzung suggeriert, weil das gesamte Öffnungsmodell auf GERADEN Bändern basiert: `buildWallFootprints`/`wallGaps` (`generatePlan.ts:1363-1457`) schneiden ein rechteckiges Intervall `[from,to]` entlang der Wandachse aus der Poché, `openingAxisBox` (`toWalls3d.ts:1739`) baut im 3D ebenso einen achsparallelen Quader. Eine Bogenform braucht entweder (a) eine gekrümmte Zusatzkontur, die die Rechteck-Aussparung oben kappt (2D: zusätzliche Polygon-Boolean gegen die Poché; 3D: gekrümmte Deckfläche statt ebenem Sturz) oder (b) ein komplett neues, polygonbasiertes Öffnungsmodell. Vorschlag: (a) zuerst — ein `headShape: "eckig"|"segment"|"spitz"|"rund"` mit Zusatzparametern (Stichhöhe/Radius), das NUR die obere Kante der bestehenden Rechteck-Öffnung ersetzt, während Pfosten/Sohlbank rechteckig bleiben. Deckt die reale Mehrheit der Fälle (Haustür mit Rundbogen, Dachflächenfenster-Giebel) ohne das Kernmodell umzubauen. ### 3.3 Lücken (Fenster, Delta zur Studie) | Feature | Status | Priorität | Aufwand | |---|---|---|---| | `glazing`/`glazingPanes` 2D-wirksam (Scheibenzahl statt nur DetailLevel) | ~ (weiter offen seit Studie) | **P0** | 1 PT | | `sillBoard` gerendert (2D-Kontur + 3D-Box) | ✗ | P1 | 2 PT | | Kopfform (Rundbogen/Spitzbogen/Schräge) über Zusatzkontur | ✗ | P2 | 5 PT (s. §3.2) | | Echtes Sprossengitter (Glasteilung UNABHÄNGIG von Flügelrahmen) | ✗ | P1 | 2 PT | | Alle übrigen Fenster-Lücken | siehe window-editor-vectorworks-study.md §2/§4 | — | — | --- ## 4. Dach (Roof) ### 4.1 Was ein vollständiges BIM-Tool bietet | Bereich | Typische Parameter | |---|---| | Grundform | Pult, Sattel, Walm, Krüppelwalm, Zeltdach, Mansarde (mit Untertyp Giebel-/Walm-/Zeltmansarde), Flach/Terrassendach, Sheddach, Tonnendach, freie Neigungsflächen je Kante | | Grundriss | beliebiges Polygon (nicht nur Rechteck), automatische Kehlen/Grate über Straight-Skeleton bei L-/T-/U-Grundrissen | | Neigung | je Dachfläche einzeln editierbar, unterschiedliche Neigungen je Seite | | Schichtaufbau | Eindeckung (Ziegel/Blech/Bitumen), Lattung, Konterlattung, Unterdach/-spannbahn, Sparren/Dämmung zwischen Sparren, Dampfbremse, Innenverkleidung — analog Wandaufbau, mit Deckenanschluss | | Überstand | Traufe und Ortgang UNABHÄNGIG editierbar (Betrag + Ausbildung), Aufschiebling (Neigungsknick am Traufende), Ortganddetail (Windbrett, Blech) | | Kniestock/Drempel | vertikale Wandaufkantung zwischen Deckenoberkante und Dach-Traufpunkt, definiert First-/Trauf-Geometrie mit | | Öffnungen im Dach | Dachflächenfenster (schräg, in der Dachebene), Dachgauben (Schlepp-, Sattel-, Walm-, Spitzgaube, Fledermausgaube) als eigenständige Sekundärdächer mit eigenem First | | First/Grat/Kehl/Ortgang | eigene Linientypen in 2D-Ansicht (Dachaufsicht) UND im Schnitt sichtbar (Sparrenlage, Dämmstärke) | | Material/Poché | Dachfläche in der Aufsicht mit Eindeckungs-Symbol/-Schraffur (Ziegel-Textur o. Ä.), im Schnitt Vollschichten wie eine geneigte Wand | | IFC-Rolle | `IfcRoof` (aggregiert `IfcRoofType`), Dachflächen selbst oft als `IfcSlab`-artige Elemente mit `IfcMaterialLayerSetUsage`, Gauben als eigene `IfcRoof`/`IfcBuildingElementProxy`-Unterobjekte | ### 4.2 IST in DOSSIER `Roof` (`src/model/types.ts:1022-1047`) rechnet ausschliesslich auf der **Bounding-Box** des Umrisses (Kommentar `types.ts:1016-1020`: "First entlang einer Hauptachse ... die gängige, intuitive Vereinfachung"). Geometrie kommt aus `roofGeometry()`/`computeCanonical()` (`src/geometry/roof.ts:80-267`), explizit **"ohne Straight-Skeleton"** (Kommentar `roof.ts:5`). Unterstützte `RoofShape` (`types.ts:1013`): flach/pult/sattel/walm/mansarde/zelt — je EINE feste Berechnung, keine Untertypen. Mansarde hat eine feste, nicht editierbare Knick-Geometrie (`d1 = halfD * 0.4`, `roof.ts:181` — 40 % der Tiefe von der Traufe, hart codiert, keine Möglichkeit den Umbruchpunkt zu verschieben). Konkrete, verifizierte Lücken: - **Kein Schichtaufbau.** `Roof.thickness` (`types.ts:1044`) ist ein einzelner Skalar. Er wird an KEINER Stelle im Code gelesen (`grep "roof.thickness"` über `toWalls3d.ts`/`generatePlan.ts`/`roof.ts` liefert null Treffer) — das Feld existiert im Typ, ist aber komplett tot. Die 3D-Dachfläche ist eine unendlich dünne, einfarbige Fläche (`emitRoofs()`, `src/plan/toWalls3d.ts:1670-1684`: nur `plane.pts`/ `gable`-Fans, EINE Farbe `ROOF_RGB` bzw. `roof.color`, keine Dicke, keine Materialschichten). - **Kein `RoofType`.** `Project` hat `wallTypes`, `ceilingTypes?`, `doorTypes?`, `windowTypes?`, `stairTypes?` (`types.ts:1936-1958`), aber kein `roofTypes?`. Es gibt keinen Bauteil-Bibliothekseintrag für Dächer. - **2D-Grundriss zeigt keine Poché.** `addRoof()` (`src/plan/generatePlan.ts:2549-2605`) zeichnet AUSSCHLIESSLICH Linien (Traufe/First/Grat/Knick, je feste Strichstärke `ROOF_EAVES_MM`/ `ROOF_RIDGE_MM`/`ROOF_HIP_MM`) — keine Fläche, keine Schraffur, keine Materialkennzeichnung. Deckungsgleich mit Wand/Decke, die BEIDE eine Poché-Füllung mit Schraffur haben (`addWallPoche`, `addCeilingPoche`), bleibt das Dach in der Aufsicht ein reines Liniendiagramm. - **Kein Schnitt.** `src/plan/toSection.ts` hat KEINE Roof-Behandlung (kein Treffer für `roof`/`Roof` im gesamten Datei-Grep). Ein Vertikalschnitt durch ein Gebäude mit Satteldach zeigt heute keine Dachlinie, keine Sparrenlage, keine Firstprojektion — ein Kernstück der BIM-1:1-Erwartung fehlt vollständig. - **Kein IFC.** `exportIfc.ts` erzeugt `IfcWall`, `IfcSlab`, `IfcDoor`/ `IfcWindow`, `IfcStair`, `IfcBuildingElementProxy` (Kommentar `exportIfc.ts:18-36`) — `Roof`/`IfcRoof` ist in der Abbildungsliste NICHT aufgeführt und wird beim Export komplett übersprungen. - **Kein Straight-Skeleton, kein L-Grundriss mit Kehle.** Ein L-förmiger Baukörper mit durchgehendem Satteldach (Kehle an der Innenecke) lässt sich nicht abbilden — die BBox-Rechnung würde ein Rechteck über die ganze L-Ausdehnung legen. - **Keine Gauben, keine Dachfenster.** Kein Treffer für Gaube/Dormer im gesamten `src`-Baum (verifiziert per Suche). - **Kein Kniestock als Bauteilbeziehung.** `baseElevation` (`types.ts:1042`) erlaubt zwar, die Traufhöhe manuell über die Geschoss-Oberkante zu heben (ein Kommentar in `ObjectInfoPanel.tsx:549` erwähnt das explizit als Nutzungsmuster), aber es gibt keine Wand-Dach-Kopplung, die einen Drempel/Kniestock als eigenes, vermasstes Bauteil führt — der Nutzer muss die Zahl manuell abstimmen. - **Traufe/Ortgang nicht unabhängig.** `overhang` (`types.ts:1038`) ist EIN Wert "ringsum" — Traufüberstand und Ortgangüberstand (oft unterschiedlich, z. B. 0.5 m Traufe / 0.3 m Ortgang) sind nicht trennbar. - **UI**: `ObjectInfoPanel.tsx:479-561` bietet volle Instanz-Bearbeitung (shape/ridgeAxis/pitch/pitchUpper/width/depth/overhang/thickness/ baseElevation), aber keine Typ-/Stil-Verwaltung (kein `ResourceManager`- Eintrag für Dächer, anders als Wand/Decke/Tür/Fenster/Treppe). ### 4.3 Dach-Schichtlogik — konkreter Vorschlag (Kernthema dieses Dokuments) Der Vorschlag überträgt exakt das `WallType`/`CeilingType`-Muster: ``` export interface RoofType { id: string; name: string; /** Aussen (Eindeckung) → innen (Verkleidung), analog WallType.layers. */ layers: Layer[]; } ``` Kein neuer Layer-Typ nötig — `Layer` (`types.ts:245`) ist bereits "Bauteil + Dicke + optionaler Fugen-Linienstil", unabhängig davon ob sie horizontal (Decke), vertikal (Wand) oder GENEIGT (Dach) gestapelt wird, weil die Stapel-Richtung beim jeweiligen Renderer entschieden wird, nicht im Datentyp. Typische Schichtfolge eines Steildachs (Eindeckung → Konterlattung → Lattung → Unterdach/Unterdeckbahn → Sparren+Dämmung → Dampfbremse → Innenverkleidung/GKB) bildet sich 1:1 auf `Layer[]` ab, jede Schicht bekommt ein `Component` mit eigener Schraffur/Farbe/Material wie bei Wand/Decke. `Roof.thickness: number` wird zu `Roof.roofTypeId?: string` (Verweis, analog `Ceiling.ceilingTypeId`) mit optionaler `thicknessOverride?: number` — exakt das Muster aus `Ceiling.thickness?` (`types.ts:952-953`, "Optionale Übersteuerung der Gesamtdicke ... sonst Typ-Dicke"). `Project.roofTypes?: RoofType[]` ergänzt die Bibliothek. **3D-Konsum**: `emitRoofs()` (`toWalls3d.ts:1670`) baut heute EINE Dreiecksfläche je Dachfläche+Giebel. Mit Layern wird daraus — analog `emitSlabs()` (`toWalls3d.ts:1352-1419`, das bereits genau diese Proportional-Stapel-Logik für Decken hat) — ein Stapel PARALLEL versetzter Flächen entlang der Flächennormalen (nicht entlang Z wie bei der Decke, sondern entlang der Dachflächen-Normalen `n`, siehe `RoofGeometry.planes` in `roof.ts:19-21`). Jede Schicht wird zum eigenen `RMesh` mit eigener Farbe/ Schraffur-Metadaten (`RCutMeta`, wie bei `emitSlabs`). Der Versatz macht zugleich die Dachdicke sichtbar (heute unendlich dünn) — ein Nebengewinn ohne Mehraufwand. **2D-Konsum (Grundriss/Aufsicht)**: `addRoof()` bekommt eine Poché-Fläche analog `addCeilingPoche` — Füllung mit der `viewHatchId` der obersten Schicht (Eindeckungssymbol), gerahmt von den bestehenden Traufe/First/Grat/Knick- Linien (die bleiben unverändert, sie sind flächen-unabhängig). **2D-Konsum (Schnitt, der grössere Umbau)**: `toSection.ts` braucht einen neuen Roof-Zweig. Ansatz: die Dachebene mit der Schnittebene schneiden (Ebene-Ebene-Schnitt, da `RoofPlane` eben ist), daraus ein Liniensegment je betroffener Dachfläche gewinnen, dann `Layer[]` senkrecht ZUR Dachneigung als Bandsequenz auftragen (wie `resolveWallBands`, `toWalls3d.ts:521`, aber gedreht um den Neigungswinkel `pitchDeg`) und mit `splitSlabLayers`-Logik (`toSection.ts:633`) füllen. Das ist der aufwendigste Einzelposten dieses Dokuments (siehe Prioritätsliste), aber ohne ihn bleibt "Dach im Schnitt" eine reine Lücke. **UI**: Ein `RoofType`-Eintrag im `ResourceManager` (`src/ui/ResourceManager.tsx`), identisch zum bestehenden Ceiling-Typ-Editor (Schicht-Liste, Dicke, Bauteil-Zuweisung) — kein neues UI-Paradigma. ### 4.4 Dach 1:1 — Formen, Kehlen, Gauben (konkreter Vorschlag) Reihenfolge nach Aufwand/Nutzen, NICHT alles auf einmal: 1. **Traufe/Ortgang trennen**: `overhang` → `{ eaves: number; gable: number }`. Kleine, lokale Änderung in `roof.ts` (zwei statt einer Offset-Variable je nach Kantentyp), grosser optischer Gewinn (das ist die häufigste Rückmeldung "sieht nicht echt aus" bei Steildächern mit gleich langem Überstand allseitig). 2. **Mansard-Untertyp** (`mansardVariant: "walm"|"giebel"|"zelt"`, wie in der älteren Planung `elements.md:298` bereits vorgesehen, aber nie gebaut): steuert nur, wie die STIRNSEITE der Mansarde behandelt wird (heute IMMER `gables` = vertikale Giebelfläche, `roof.ts:200-203`) — bei "walm" wird daraus eine geneigte Fläche wie beim Walmdach. Mittlerer Aufwand, da die Mansard-Berechnung (`roof.ts:176-206`) bereits alle Eckpunkte hat, nur die Gable-Erzeugung muss konditional werden. 3. **Editierbarer Mansard-Knickpunkt** (`kinkDepthRatio?: number` statt hart `0.4`, `roof.ts:181`) — 0.5 PT, reine Parametrisierung einer bestehenden Konstante. 4. **Krüppelwalm** (`hipTruncation?: number`, 0 = voller Walm, 1 = voller Giebel/Sattel): der First bleibt voll lang, nur ein kleines Walmstück am First-Ende — technisch eine Variation der bestehenden `walm`-Berechnung (`roof.ts:147-174`, der First-Verkürzungs-Faktor `halfD` wird parametrisiert statt fix). 5. **Dachflächenfenster** (kein neues Bauteil — ein `Opening`-ähnliches Element, das in eine Dachfläche statt eine Wand einschneidet): neuer `hostRoofId`-Pfad, eigenständiger Vorschlag; lohnt sich erst NACH der Schichtlogik, weil das Fenster sonst nicht "in die Dämmebene" passt. 6. **Gauben** (Schlepp-/Sattelgaube als eigenständiges Sekundär-`Roof` mit eigenem `outline`/`baseElevation`, das in die Hauptdachfläche einschneidet): grösster Einzelposten, weil er eine echte Boolean-Verschneidung zwischen zwei Dachkörpern braucht (ähnlich der bestehenden Wand-Boolean-Dominanz über `joinPriority`, aber räumlich in 3D). Realistisch erst nach einem Mesh-Boolean-Werkzeug (die begonnene truck-Integration, `src-tauri/trucksolid/`, ist ein Kandidat dafür). 7. **L-/T-Grundriss mit Kehle (Straight-Skeleton)**: bewusst NICHT vor 6, weil es die Bounding-Box-Vereinfachung komplett ersetzt (neue Geometrie-Engine, kein inkrementeller Ausbau von `roof.ts`) — separates, grosses Vorhaben, siehe Prioritätsliste. ### 4.5 Lücken (Dach) | Feature | Status | Priorität | Aufwand | |---|---|---|---| | `RoofType`/`Layer[]`-Schichtaufbau (Modell) | ✗ (`thickness` toter Skalar) | **P0** | 3 PT | | 3D-Schichten (gestapelte Flächen entlang Normalen) | ✗ | **P0** | 3 PT | | 2D-Aufsicht-Poché (Eindeckungssymbol) | ✗ | P1 | 1.5 PT | | Dach im Vertikalschnitt (Ebene-Ebene-Schnitt + Bänder) | ✗ | **P0** | 5 PT | | Traufe/Ortgang getrennter Überstand | ✗ | **P0** | 1 PT | | Mansard-Untertyp (Walm/Giebel/Zelt-Stirn) | ✗ | P1 | 2 PT | | Editierbarer Mansard-Knick | ✗ | P2 | 0.5 PT | | Krüppelwalm | ✗ | P2 | 1.5 PT | | Dachflächenfenster | ✗ | P2 | 4 PT | | Gauben (Boolean-Einschnitt) | ✗ | P3 | 8+ PT | | L-/T-Grundriss, Straight-Skeleton-Kehle | ✗ | P3 | 10+ PT | | `RoofType`-Ressourcen-UI | ✗ | P1 (folgt aus RoofType) | 1 PT | | IFC `IfcRoof`-Export | ✗ | P2 | 1.5 PT | --- ## 5. Decke (Ceiling / Slab) ### 5.1 Was ein vollständiges BIM-Tool bietet | Bereich | Typische Parameter | |---|---| | Grundfläche | beliebiges Polygon inkl. Aussparungen (Treppenauge, Schacht, Kamindurchbruch) | | Schichtaufbau | Rohdecke, Trittschalldämmung, Estrich, Bodenbelag — analog Wand, mit Deckenspiegel/Untersicht (abgehängte Decke, Akustikplatten) als eigene Schicht(en) | | Randausbildung | gerader Rand, auskragender Balkon-/Vordachrand mit thermischer Trennung (Isokorb/Randdämmstreifen), Randschalung/Abschalungsprofil, Attika-Anschluss, Tropfkante | | Deckenspiegel | abgehängte Untersicht mit eigener Höhe/Raster (Akustik-/Gipskarton-Decke), UNABHÄNGIG von der tragenden Rohdecke | | Öffnungen | Deckenaussparungen als eigene, editierbare Polygone (nicht nur Gesamtumriss) | | Neigung | geneigte Decke (Garagenrampe, Terrasse mit Gefälle) — nicht nur horizontal | | 2D-Darstellung | Aufsicht mit Ansichts-Poché (unaufgeschnitten), Schnitt mit Vollschichten je Lage, Deckenspiegel-Plan (reflected ceiling plan) als eigene Zeichnungsart | | IFC-Rolle | `IfcSlab` (PredefinedType FLOOR/ROOF/BASESLAB), `IfcMaterialLayerSetUsage` für den Schichtaufbau, `IfcCovering` für abgehängte Decken | ### 5.2 IST in DOSSIER `Ceiling` (`types.ts:928-1000`) hat bereits die stärkste Tiefe der vier Bauteile in diesem Dokument: geschlossenes Umriss-Polygon (`outline`), `ceilingTypeId` mit Legacy-Fallback auf `wallTypeId` (`getCeilingType`, `types.ts:2089`), volle Attribut-Override-Kette (`foreground`/`background`/ `strokeWeight`/`hatchId` + `*Source`, wie bei `Wall`) und unabhängige vertikale Bindung von OK/UK über `VerticalAnchor` (`top?`/`bottom?`, `types.ts:990-999` — "floor"-gebunden oder "custom"-Z, exakt wie bei `Wall.top`/`Wall.bottom`, `types.ts:887-893`). 3D-Schichtstapel ist implementiert (`emitSlabs`, `toWalls3d.ts:1352-1419`), Schnitt-Schichtsplit ebenfalls (`splitSlabLayers`, `toSection.ts:633`). Verifizierte Lücken: - **Keine Aussparungen.** `Ceiling.outline: Vec2[]` ist EIN geschlossenes Polygon (`types.ts:936-939`) — kein `openings?: Vec2[][]` für Treppenauge/Schacht/Kamin. Ein Treppenloch in der Decke muss heute über die Aussenkontur der Decke "herumgeschnitten" werden (Decke als komplexes, nicht-konvexes Polygon), nicht als saubere Innenaussparung. (`elements.md:217` sah dieses Feld in der älteren Planung explizit vor, es wurde nie in `types.ts` übernommen.) - **Kein Randdetail.** Die Decke ist über die gesamte `outline` exakt `thickness` dick, EINHEITLICH. Es gibt kein Feld für eine abweichende Randausbildung (Aufkantung, Randdämmstreifen, Tropfkante, andere Dicke am Balkonrand). Ein auskragender Balkon lässt sich zwar über eine erweiterte `outline` modellieren, bekommt aber zwangsläufig denselben Vollschicht- Aufbau wie die Innendecke — eine thermisch getrennte Balkonplatte (Isokorb) ist nicht abbildbar. - **Kein Deckenspiegel.** Abgehängte Untersicht (Akustik-/GKB-Decke mit eigener, tieferer Kote) existiert nicht als eigenes Konzept — nur der tragende Aufbau über `ceilingTypeId`. Ein "Deckenspiegel-Plan" (reflected ceiling plan) fehlt als Zeichnungsart komplett (`DrawingLevelKind`, `types.ts:722`, kennt nur "floor"/"section"/ "elevation"/"drawing"). (Randbemerkung: Beleuchtungsplanung/Deckenspiegel ist ein Elektro-Thema und damit bewusst ausserhalb des DOSSIER-Kernscopes — siehe "nicht bauen", Abschnitt 6. Die reine Geometrie einer zweiten, tiefer liegenden Fläche bleibt aber ein legitimer BIM-1:1-Punkt.) - **Keine Neigung.** `top`/`bottom` sind je EIN `VerticalAnchor` (ein Z-Wert), keine Neigungsebene — eine geneigte Garagen-/Terrassendecke ist nicht modellierbar, nur über mehrere ebene Teildecken behelfsweise annäherbar. - **2D-Aufsicht nutzt nur die erste Schicht.** `addCeilingPoche` (`generatePlan.ts:2453-2536`) liest `wt.layers[0]` (Kommentar/Code `generatePlan.ts:2465`) für die Ansichts-Schraffur — bei einer mehrschichtigen Decke (z. B. Beton unten, Dämmung oben) zeigt die Aufsicht immer nur die OBERSTE (erste) Schicht, was für eine unaufgeschnittene Draufsicht baupraktisch korrekt ist (man sieht von unten die Untersicht/erste Lage), aber nicht konfigurierbar ist, welche Lage als "sichtbare" gilt, falls der Deckenaufbau umgekehrt sortiert wäre. - IFC: `IfcSlab` wird erzeugt (`exportIfc.ts:28`), aber laut Kopfkommentar (`exportIfc.ts:38-41`) bewusst OHNE `IfcMaterialLayerSet`/-`Usage` — der Export verliert den Schichtaufbau, den DOSSIER intern bereits hat. ### 5.3 Deckenrand/Randterminierung — vertieft Der Nutzer nennt explizit "Deckenränder, Stirnabschlüsse, Anschluss an Wand/ Aussenkante, auskragende Ränder, Randabschalung" als Schwerpunkt. IST-Bild: keines davon existiert als eigenes Konzept — die Decke ist ein reines Extrusions-Polygon. Konkreter Vorschlag, dreistufig nach Aufwand: 1. **Aussparungen** (`Ceiling.openings?: Vec2[][]`) — niedrigster Aufwand, grösster praktischer Nutzen (Treppenauge ist im Wohnbau der Regelfall, nicht die Ausnahme). 2D: zusätzliche Ausschnitts-Polygone in `addCeilingPoche` (Loch im Fill, zusätzliche Randlinien). 3D: `emitSlabs` bekommt Löcher im Extrusions-Profil (analog dem bereits vorhandenen Loch-Schnitt bei Wand-Öffnungen, `wallMeshCut.ts`, als Vorlage). 2. **Randschicht-Override** (`Ceiling.edgeOverride?: { ringOffset: number; ceilingTypeId: string }` — ein schmaler Innenring der Decke entlang des Randes bekommt einen ANDEREN Layer-Aufbau, z. B. mit zusätzlicher Randdämmschicht oder reduzierter Dicke für eine Tropfkante). Technisch: `emitSlabs` erzeugt für den Ringbereich einen zweiten Layer-Stapel mit dem Override-Typ, geometrisch als Offset-Polygon-Differenz (`outline` minus `outline.offset(-ringOffset)`), eine Operation, die für Wandbänder bereits ähnlich existiert (`buildWallFootprints`). 3. **Thermisch getrennte Auskragung (Isokorb-Fall)**: ein eigenes, sekundäres `Ceiling`-Objekt für den auskragenden Teil mit eigenem `ceilingTypeId` (dünnerer/anderer Aufbau) UND eigener `top`/`bottom`- Bindung, das an die Hauptdecke stösst — kein neues Feld nötig, nur eine UI-Erleichterung ("Deckenrand abtrennen"-Werkzeug, das die Decke entlang einer gewählten Kante in zwei `Ceiling`-Objekte teilt). Niedrigster Modell-Aufwand, weil er das bestehende Mehrfach-Decken-Prinzip nutzt statt ein neues Konzept einzuführen. ### 5.4 Lücken (Decke) | Feature | Status | Priorität | Aufwand | |---|---|---|---| | Aussparungen (`openings?: Vec2[][]`) in 2D+3D | ✗ | **P0** | 3 PT | | Randschicht-Override (Ringzone anderer Aufbau) | ✗ | P1 | 3 PT | | Deckentrenn-Werkzeug für Isokorb-Fall (UI, kein neues Modellfeld) | ✗ | P1 | 1.5 PT | | Geneigte Decke (Rampe/Gefälle) | ✗ | P2 | 3 PT | | Deckenspiegel (zweite, abgehängte Fläche) | ✗ | P3 | 2 PT (reine Geometrie) | | IFC `IfcMaterialLayerSetUsage` für Decke (UND Wand) | ~ (bewusst ausgelassen) | P2 | 2 PT | | Konfigurierbare "oberste Schicht" für Aufsicht-Poché | ✓ implizit (Layer-Reihenfolge = Sortierung) | — | — | --- ## 6. Konsolidierte Priorisierung (über alle vier Bauteile) Sortiert nach "1:1-Zuwachs pro Aufwand", nicht nach Aufwand allein: 1. **Dach-Schichtaufbau (Modell + 3D-Stapel)** — schliesst die grösste strukturelle Lücke (totes `thickness`-Feld, kein `RoofType`) und liefert sofort sichtbaren Tiefengewinn im 3D (§4.3, ~6 PT gesamt). 2. **Traufe/Ortgang getrennter Überstand** — 1 PT, sofortiger optischer Sprung bei jedem Steildach-Projekt (§4.4 Punkt 1). 3. **Zweiflügelige Tür rendert wirklich 2 Blätter** — das `leafCount`-Feld existiert seit der Türtyp-Einführung, wird aber komplett ignoriert; sehr sichtbarer Bug-artiger Gap (§2.3, 2 PT). 4. **Deckenaussparungen** — Treppenauge ist der Wohnbau-Regelfall, heute nur über Umweg (nicht-konvexes Aussenpolygon) lösbar (§5.3 Punkt 1, 3 PT). 5. **Fenster-Glazing 2D-wirksam** — seit über einem Jahr als P0 in der Fenster-Studie dokumentiert und weiterhin offen; niedriger Aufwand, sollte nicht liegen bleiben (§3.1, 1 PT). 6. **Dach im Vertikalschnitt** — grösster Einzelposten (5 PT), aber ohne ihn bleibt jeder Gebäudeschnitt mit Steildach unvollständig; das ist die Art Lücke, die bei einer Bemusterung/Baueingabe sofort auffällt. 7. **Deckenrand-Override / Isokorb-Trennwerkzeug** — folgt danach, weil er auf demselben Mehrfach-Decken-Prinzip aufbaut wie Punkt 4. 8. **Mansard-Untertyp + editierbarer Knick** — mittlere Priorität, weil Mansarde in der Schweiz/Süddeutschland baupraktisch häufig ist und die heutige starre 40 %-Konstante sichtbar unrealistisch wirkt. 9. **Tür/Fenster-Rahmentiefe** (asymmetrische Rahmenbreiten, Beschlag, Kopfform) — bewusst NACH den strukturellen Lücken, weil sie additive Detailverbesserungen an einem bereits funktionierenden Pfad sind, während 1–7 fehlende oder falsch dargestellte Kernfunktionen betreffen. 10. **Gauben, L-Grundriss/Kehle, Dachflächenfenster** — grösste Einzel- Aufwände (8–10+ PT), architektonisch am voraussetzungsreichsten (Boolean- Werkzeug bzw. neue Geometrie-Engine); erst nach 1–9 angehen. ### 6.1 NICHT bauen (VW/Revit-Ballast ohne Nutzen für DOSSIER) - **Vollständiger Massketten-/Bezugsapparat** (VW B1..B5/H1..H7, Roh-/Fertigmass-Umschaltung) — DOSSIER arbeitet mit lichten Massen, das genügt für ein Schweizer Wohnbau-/Kleinprojekt-Tool (bereits so in `window-editor-vectorworks-study.md` §5 entschieden, hier bestätigt für Dach/Decke: keine Dach-Rohmass-/Fertigmass-Unterscheidung). - **Sichtbarkeitsmatrix 3D-Objekte × Ansichten** (Augen-Tabelle je Kategorie×Ansicht×Detailstufe) — DOSSIERs Layer-Sichtbarkeit + `DetailLevel` deckt den praktischen Bedarf; eine volle Matrix ist Verwaltungsaufwand ohne Mehrwert für Einzelprojekte. - **Eckfenster/Eckdach als generischer Sonderfall über zwei Wirtsbauteile** — seltene Geometrie, hoher Modellierungsaufwand (zwei Hosts, ein Element); bei Bedarf als manueller Workaround (zwei separate Öffnungen) lösbar. Ebenso: freie Neigungsflächen je Dachkante (VW erlaubt jede Kante einzeln zu kippen) — für die abgedeckten Standardformen (Pult/Sattel/Walm/ Mansarde/Zelt/Krüppelwalm) nicht nötig; wer eine Freiform-Dachlandschaft braucht, ist besser mit den `ExtrudedSolid`/truck-Werkzeugen bedient. - **Vollständige Beschlags-/Baubeschlag-Bibliothek** (Marken-Beschlagsätze, Schliessplan) — Beschlag als generisches Griff-Mesh (§2.4) genügt für die visuelle 1:1-Wirkung; eine Beschlags-PRODUKTBIBLIOTHEK ist Kataloggeschäft, kein CAD-Kernfeature. - **Deckenspiegel als vollwertige Beleuchtungsplanung** (Leuchtenraster, Lichtberechnung) — reine Geometrie einer zweiten Fläche ist ok (P3), die Elektro-/Lichtplanungslogik selbst liegt ausserhalb des Tool-Zwecks. - **IFC `IfcOpeningElement`/Void-Semantik nachrüsten** — bewusste Design-Entscheidung im bestehenden Export (`exportIfc.ts:22-27`), NICHT revidieren: die heutige "Loch steckt im Mesh"-Lösung liefert visuelle Parität in jedem Viewer ohne Boolean-Pflicht beim Empfänger; der reine IFC4-Purismus (Wand als parametrische Extrusion + Void) würde bestehende, bewusst getroffene Trade-offs zunichtemachen. - **Straight-Skeleton/Kehlen und Gauben SOFORT** — nicht "nicht bauen", aber bewusst zurückgestellt (§6, Punkt 10): ohne die Schichtlogik (Punkt 1) vorher zu bauen, würde jede Kehlen-/Gauben-Lösung auf dem unendlich dünnen, ungeschichteten Dach aufsetzen und müsste bei Einführung der Schichten ohnehin neu gefasst werden.