Dach-Schichtlogik: RoofType/Layer[] wie Decken (3D mehrschichtig)
Kernthema der BIM-Tiefe (Designdoc docs/design/bim-elements-depth-study.md, P0):
Dächer bekommen einen mehrschichtigen Aufbau analog WallType/CeilingType.
- Modell: RoofType { layers: Layer[] }, Project.roofTypes, Roof.roofTypeId
(Roof.thickness bleibt einschichtiger Fallback). Resolver roofLayers()/
roofTotalThickness() — wiederverwendet den bestehenden Layer-Typ.
- 3D (emitRoofs): je Schicht ein eigenes Mesh mit Bauteilfarbe, entlang der
Flächennormalen unter die vorige gestapelt (Eindeckung aussen → Verkleidung
innen). Ohne roofTypeId einschichtiger thickness-Slab (Default-Dachfarbe).
- UI: Dachtyp-Dropdown im Dach-Panel (leer = einschichtig). Default-Dachtyp
'Steildach gedämmt' in sampleProject.
- +2 Tests (Schicht-Meshes/Stapelung; einschichtig = Slab+Giebel).
Offen (Designdoc): 2D-Schnitt-Poché der Dachschichten, RoofType-ResourceManager-
Tab, Traufe/Ortgang getrennt. 668/668 grün; 3D-Optik vom Nutzer in Tauri prüfen.
This commit is contained in:
@@ -202,6 +202,18 @@ export const sampleProject: Project = {
|
||||
],
|
||||
},
|
||||
],
|
||||
roofTypes: [
|
||||
{
|
||||
id: "roof-warm",
|
||||
name: "Steildach gedämmt",
|
||||
// Aussen (Eindeckung) → innen (Verkleidung); Bauteile aus der Bibliothek.
|
||||
layers: [
|
||||
{ componentId: "brick", thickness: 0.04 }, // Eindeckung (Ziegel, Platzhalter)
|
||||
{ componentId: "insulation", thickness: 0.22, jointLineStyleId: "thin" }, // Sparren/Dämmung
|
||||
{ componentId: "render-int", thickness: 0.0125 }, // Innenverkleidung (GK)
|
||||
],
|
||||
},
|
||||
],
|
||||
// Bauteil-Typen (Bibliothek) — Tür/Fenster/Treppe, analog Wand-/Deckenstile.
|
||||
// Elemente referenzieren sie per `typeId`; ohne Referenz gilt Inline-Verhalten.
|
||||
doorTypes: [
|
||||
|
||||
+49
-1
@@ -276,6 +276,21 @@ export interface CeilingType {
|
||||
layers: Layer[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ein Dachtyp (Dachaufbau) = geordneter Schichtaufbau EINES Daches, senkrecht
|
||||
* zur Dachfläche gestapelt (aussen/Eindeckung → innen/Verkleidung) — das
|
||||
* geneigte Gegenstück zu `WallType`/`CeilingType`. Nutzt denselben `Layer`-Typ.
|
||||
* Typische Folge: Eindeckung (Ziegel/Blech) → Konterlattung/Lattung → Unterdach
|
||||
* → Sparren/Dämmung → Dampfbremse → Innenverkleidung. Ein Dach ohne `roofTypeId`
|
||||
* fällt auf die einschichtige `Roof.thickness` zurück (rückwärtskompatibel).
|
||||
*/
|
||||
export interface RoofType {
|
||||
id: string;
|
||||
name: string;
|
||||
/** Aussen (Eindeckung) → innen (Verkleidung), analog `WallType.layers`. */
|
||||
layers: Layer[];
|
||||
}
|
||||
|
||||
// ── Bauteil-Typen: Tür / Fenster / Treppe ──────────────────────────────────
|
||||
// Wiederverwendbare Stile (Presets) für Türen, Fenster und Treppen — analog
|
||||
// `WallType`/`CeilingType` (Bibliothek im Projekt, referenziert per `typeId`).
|
||||
@@ -1053,8 +1068,18 @@ export interface Roof {
|
||||
ridgeAxis: "x" | "y";
|
||||
/** Traufhöhe (absolutes Z, Meter); fehlt ⇒ Oberkante des Geschosses. */
|
||||
baseElevation?: number;
|
||||
/** Dachdicke (Meter, senkrecht zur Fläche gemessen). */
|
||||
/**
|
||||
* Dachdicke (Meter, senkrecht zur Fläche) — Fallback/Override. Ohne
|
||||
* {@link roofTypeId} ist es die einschichtige Gesamtdicke; mit `roofTypeId`
|
||||
* bleibt es als reiner Fallback bestehen (die Schichtsumme des Typs gilt).
|
||||
*/
|
||||
thickness: number;
|
||||
/**
|
||||
* Verweis auf einen Dachtyp (Dachaufbau) aus `Project.roofTypes` — mehrschichtig
|
||||
* (Eindeckung/Lattung/Dämmung/Verkleidung), analog `Ceiling.ceilingTypeId`.
|
||||
* Fehlt er, gilt die einschichtige {@link thickness}.
|
||||
*/
|
||||
roofTypeId?: string;
|
||||
/** Optionale Übersteuerung der Strich-/Umrissfarbe; sonst Kategorie-Farbe. */
|
||||
color?: string;
|
||||
}
|
||||
@@ -1950,6 +1975,11 @@ export interface Project {
|
||||
* `Ceiling.wallTypeId` gegen `wallTypes` auf (siehe `getCeilingType`).
|
||||
*/
|
||||
ceilingTypes?: CeilingType[];
|
||||
/**
|
||||
* Dachtypen (Dachaufbauten) — mehrschichtig, analog `ceilingTypes`. Optional;
|
||||
* Dächer ohne `roofTypeId` lösen über die einschichtige `Roof.thickness` auf.
|
||||
*/
|
||||
roofTypes?: RoofType[];
|
||||
/**
|
||||
* Türtypen-Bibliothek (Türstile), analog `wallTypes`. Optional, damit
|
||||
* bestehende Projekte/Tests ohne `doorTypes` gültig bleiben; Türen ohne
|
||||
@@ -2110,6 +2140,24 @@ export const ceilingThickness = (project: Project, ceiling: Ceiling): number =>
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Schichtaufbau eines Daches (aussen/Eindeckung → innen/Verkleidung). Mit
|
||||
* {@link Roof.roofTypeId} die Schichten des Dachtyps; sonst eine EINSCHICHTIGE
|
||||
* synthetische Schicht aus {@link Roof.thickness} (leere `componentId` ⇒ der
|
||||
* Renderer nutzt seine Default-Dachfarbe).
|
||||
*/
|
||||
export const roofLayers = (project: Project, roof: Roof): Layer[] => {
|
||||
if (roof.roofTypeId) {
|
||||
const rt = (project.roofTypes ?? []).find((t) => t.id === roof.roofTypeId);
|
||||
if (rt && rt.layers.length > 0) return rt.layers;
|
||||
}
|
||||
return [{ componentId: "", thickness: Math.max(0, roof.thickness) }];
|
||||
};
|
||||
|
||||
/** Gesamtdicke eines Daches (Meter, senkrecht zur Fläche) = Summe der Schichten. */
|
||||
export const roofTotalThickness = (project: Project, roof: Roof): number =>
|
||||
roofLayers(project, roof).reduce((s, l) => s + Math.max(0, l.thickness), 0);
|
||||
|
||||
/**
|
||||
* Löst den {@link DoorType} einer Tür-Öffnung auf, oder `undefined` (keine
|
||||
* `typeId` bzw. unbekannt ⇒ Inline-Verhalten). Bewusst NICHT werfend — der
|
||||
|
||||
Reference in New Issue
Block a user