68a0459d0e
- Schnittebenen: 3D-Live-Schnitt folgt der gewählten Grundriss-Schnittlinie (section3dCutId/sectionPlaneFromLevel), Schalter "Im 3D schneiden" im Objekt-Info, Doppelklick auf Schnittlinie springt in 2D-Schnittansicht, unsichtbare Ebenen blenden ihre Führungslinie aus - Eigene native Tauri-Fenster für Kontext-Import/Zeichnungsebenen/ Ebenen-Einstellungen/Ressourcen/Einstellungen + klassische Menüleiste (AppMenuBar) neben der Wortmarke - Hell/Dunkel-Umschalter (Einstellungen → Darstellung), persistiert, flackerfrei vor erstem Render gesetzt - SWISSIMAGE-Luftbild-Import (swisstopo WMS) als Kontext-Hintergrundebene - UI-Politur: Werkzeug-Panel Symbole/Liste umschaltbar, Topbar-Quick-Access- Icons entfernt, Zahnrad→Einstellungen in Panel-Köpfen, Footerbar/ Snap-Marker/Maß-HUD auf helle Pillen-Sprache umgestellt - Neues Dachziegel-Material (RoofingTiles013A)
584 lines
21 KiB
TypeScript
584 lines
21 KiB
TypeScript
import type { Project } from "./types";
|
||
import { recomputeFloorElevations } from "./types";
|
||
import { MATERIAL_LIBRARY } from "../materials/library";
|
||
import { materialFromAsset } from "../materials/runtime";
|
||
|
||
// Bibliotheks-Materialien für die Basis-Components ab Werk (PBR-Texturen,
|
||
// s. `src/materials/library.ts`). Zuordnung nur, wo ein Bibliotheks-Asset
|
||
// sinnvoll passt — Wärmedämmung und Zementestrich bleiben bewusst ohne
|
||
// Zuweisung (kein passendes Asset in der Bibliothek), statt zu raten.
|
||
const PLASTER_ASSET = MATERIAL_LIBRARY.find((a) => a.id === "Plaster001")!;
|
||
const BRICK_ASSET = MATERIAL_LIBRARY.find((a) => a.id === "Bricks104")!;
|
||
const CONCRETE_ASSET = MATERIAL_LIBRARY.find((a) => a.id === "Concrete048")!;
|
||
const ROOF_TILE_ASSET = MATERIAL_LIBRARY.find((a) => a.id === "RoofingTiles013A")!;
|
||
|
||
// Demo-Haus mit zwei Geschossen:
|
||
// EG — rechteckiger Raum (5 × 4 m) mit einer Tür in der Südwand.
|
||
// OG — rechteckiger Raum (5 × 3 m) ohne Tür.
|
||
// Maße in Metern. Die Außenwand ist ein realistischer SIA-naher
|
||
// Schichtaufbau (außen → innen).
|
||
//
|
||
// Zwei UNABHÄNGIGE Achsen (Dokumentmodell nach DOSSIER):
|
||
// • drawingLevels — Geschosse (EG, OG) + Platzhalter Schnitt/Ansicht.
|
||
// • layers — Grafik-Kategorie-Baum (Codes/Namen/Farben/lw 1:1 aus DOSSIER,
|
||
// DEFAULT_LAYER_SCHEMA in launcher/src/App.jsx). 21 Türen/Fenster ist hier
|
||
// als Kind von 20 Wände gehängt.
|
||
export const sampleProject: Project = {
|
||
id: "demo",
|
||
name: "Demo-Haus",
|
||
// ── Ressourcen-Bibliotheken (zentral verwiesen per id) ──────────────────
|
||
// Linienstile: aufgeräumt auf kanonische VOLLLINIEN je Strichstärke (dash=null)
|
||
// + eine gestrichelte Linie. Früher gab es drei funktional identische 0.13-
|
||
// Volllinien ("thin"/"hatch-line"/"joint-massive") — zusammengeführt auf "thin"
|
||
// ("Volllinie 0.13"); Schraffur-/Schichtfugen-Referenzen zeigen jetzt darauf.
|
||
// (Die ids bleiben stabil, damit geladene Projekte + interne Referenzen halten.)
|
||
lineStyles: [
|
||
{ id: "hatch-hair", name: "Volllinie 0.02", weight: 0.02, color: "#1a1a1a", dash: null },
|
||
{ id: "thin", name: "Volllinie 0.13", weight: 0.13, color: "#1a1a1a", dash: null },
|
||
{ id: "medium", name: "Volllinie 0.25", weight: 0.25, color: "#1a1a1a", dash: null },
|
||
{ id: "thick", name: "Volllinie 0.5", weight: 0.5, color: "#0a0a0a", dash: null },
|
||
// Gestrichelte Haarlinie für die Dämmung (Striche quer durch die Wanddicke).
|
||
{ id: "hatch-dash", name: "Dämmungsstrich", weight: 0.02, color: "#1a1a1a", dash: [0.35, 0.3] },
|
||
],
|
||
// Schraffuren: color = Linien-/Vollfüllfarbe des Musters; angle in Grad.
|
||
// "none" = keine Schraffur (nur Component-Füllung).
|
||
// Grundeinstellung aller Linien-Schraffuren: schwarze Haarlinie (color) auf
|
||
// weißem Grund (die zugehörigen Bauteile tragen weiße Füllfarbe).
|
||
hatches: [
|
||
{ id: "none", name: "Ohne", pattern: "none", scale: 1, angle: 0, color: "#1a1a1a" },
|
||
{
|
||
id: "insulation",
|
||
name: "Wärmedämmung",
|
||
pattern: "insulation",
|
||
scale: 1,
|
||
angle: 0,
|
||
color: "#1a1a1a",
|
||
lineStyleId: "thin",
|
||
},
|
||
{
|
||
id: "diagonal",
|
||
name: "Diagonal",
|
||
pattern: "diagonal",
|
||
scale: 1,
|
||
angle: 45,
|
||
color: "#1a1a1a",
|
||
lineStyleId: "thin",
|
||
},
|
||
{
|
||
id: "crosshatch",
|
||
name: "Kreuzschraffur",
|
||
pattern: "crosshatch",
|
||
scale: 1,
|
||
angle: 0,
|
||
color: "#1a1a1a",
|
||
lineStyleId: "thin",
|
||
},
|
||
{
|
||
id: "solid-concrete",
|
||
name: "Beton (voll)",
|
||
pattern: "solid",
|
||
scale: 1,
|
||
angle: 0,
|
||
color: "#9aa0a6",
|
||
lineStyleId: "thin",
|
||
},
|
||
// ── SIA-Schnittschraffuren (Haarlinie) ──────────────────────────────────
|
||
// Dichte Teilung (scale < 1; Muster-Kachel = 8·scale) für den SIA-Look.
|
||
// Beton: Kreuzschraffur, absolut 45° (bildschirmfest, NICHT wandbezogen).
|
||
{
|
||
id: "sia-concrete",
|
||
name: "Beton (Kreuz)",
|
||
pattern: "crosshatch",
|
||
scale: 0.5,
|
||
angle: 45,
|
||
color: "#1a1a1a",
|
||
lineStyleId: "hatch-hair",
|
||
},
|
||
// Backstein: Diagonale, 45° RELATIV zur Wandachse (dreht mit der Wand mit).
|
||
{
|
||
id: "sia-brick",
|
||
name: "Backstein (Diagonal)",
|
||
pattern: "diagonal",
|
||
scale: 0.5,
|
||
angle: 45,
|
||
relativeToWall: true,
|
||
color: "#1a1a1a",
|
||
lineStyleId: "hatch-hair",
|
||
},
|
||
// Dämmung: DURCHGEZOGENE (nicht gestrichelte) Linien QUER durch die Wanddicke
|
||
// (senkrecht zur Wandachse), wandbezogen. Basiswinkel 0 = Musterlinie steht
|
||
// senkrecht zur Wandrichtung; durchgezogene Haarlinie, dichte Teilung.
|
||
{
|
||
id: "sia-insulation",
|
||
name: "Dämmung (Strich)",
|
||
pattern: "diagonal",
|
||
scale: 0.45,
|
||
angle: 0,
|
||
relativeToWall: true,
|
||
color: "#1a1a1a",
|
||
lineStyleId: "hatch-hair",
|
||
},
|
||
],
|
||
// Bauteil-Materialien: color = Poché-Füllung im Grundriss UND 3D-Diffusfarbe;
|
||
// joinPriority höher = läuft am Stoß durch (für spätere T-Stöße).
|
||
components: [
|
||
{
|
||
id: "render-ext",
|
||
name: "Aussenputz",
|
||
color: "#d8d2c7",
|
||
hatchId: "none",
|
||
joinPriority: 10,
|
||
material: materialFromAsset(PLASTER_ASSET),
|
||
},
|
||
// Weißer Grund unter den durchgezogenen Dämmungs-Haarlinien (quer zur Wand).
|
||
// Kein passendes Bibliotheks-Asset (Dämmung) → bewusst ohne `material`.
|
||
{ id: "insulation", name: "Wärmedämmung", color: "#ffffff", hatchId: "sia-insulation", joinPriority: 20 },
|
||
{
|
||
id: "brick",
|
||
name: "Backstein",
|
||
color: "#8c5544",
|
||
hatchId: "sia-brick",
|
||
joinPriority: 50,
|
||
material: materialFromAsset(BRICK_ASSET),
|
||
},
|
||
{
|
||
id: "render-int",
|
||
name: "Innenputz",
|
||
color: "#efece6",
|
||
hatchId: "none",
|
||
joinPriority: 10,
|
||
material: materialFromAsset(PLASTER_ASSET),
|
||
},
|
||
// Dacheindeckung (Tonziegel) — eigenes Bauteil statt des früheren
|
||
// "brick"-Platzhalters, damit Dächer eine ECHTE Ziegel-Textur zeigen
|
||
// (Stil „Texturiert") statt der Backstein-Fassadentextur. `color` (Flach-
|
||
// Fallback für „Schattiert") entspricht dem bisherigen `ROOF_RGB` in
|
||
// toWalls3d.ts, damit der Nicht-Textur-Look unverändert warm/terracotta bleibt.
|
||
{
|
||
id: "roof-tiles",
|
||
name: "Dachziegel",
|
||
color: "#b8735c",
|
||
hatchId: "sia-brick",
|
||
joinPriority: 15,
|
||
material: materialFromAsset(ROOF_TILE_ASSET),
|
||
},
|
||
// Für spätere T-Stöße: Beton als durchlaufender Backbone (höchste Priorität).
|
||
{
|
||
id: "concrete",
|
||
name: "Beton",
|
||
color: "#9aa0a6",
|
||
hatchId: "sia-concrete",
|
||
joinPriority: 100,
|
||
material: materialFromAsset(CONCRETE_ASSET),
|
||
},
|
||
// Zementestrich — oberste Schicht des mehrschichtigen Deckenaufbaus (Decken-Stile).
|
||
// Kein passendes Bibliotheks-Asset (Estrich) → bewusst ohne `material`.
|
||
{ id: "screed", name: "Zementestrich", color: "#c9c2b3", hatchId: "diagonal", joinPriority: 30 },
|
||
],
|
||
wallTypes: [
|
||
{
|
||
id: "aw",
|
||
name: "Aussenwand 34.5 cm",
|
||
// Schichten außen → innen; Priorität lebt jetzt am Component.
|
||
layers: [
|
||
{ componentId: "render-ext", thickness: 0.02 },
|
||
// Innere Fuge der Dämmung trifft auf den Backstein (massiv↔massiv) → 0.13 mm.
|
||
{ componentId: "insulation", thickness: 0.16, jointLineStyleId: "thin" },
|
||
{ componentId: "brick", thickness: 0.15 },
|
||
{ componentId: "render-int", thickness: 0.015 },
|
||
],
|
||
},
|
||
{
|
||
// Verputzte Backstein-Innenwand (beidseitig Innenputz) — für den T-Stoß-Test:
|
||
// eine Querwand, die mit beiden Enden an die Innenflächen der Aussenwände stösst.
|
||
id: "iw",
|
||
name: "Innenwand Mauerwerk verputzt 15 cm",
|
||
layers: [
|
||
{ componentId: "render-int", thickness: 0.015 },
|
||
{ componentId: "brick", thickness: 0.12 },
|
||
{ componentId: "render-int", thickness: 0.015 },
|
||
],
|
||
},
|
||
],
|
||
// Deckenstile (Decken-Aufbau-Typen) — das liegende Gegenstück der Wandstile.
|
||
// Schichten oben (OK) → unten (UK), analog zur Wand außen → innen.
|
||
ceilingTypes: [
|
||
{
|
||
id: "dg-massiv",
|
||
name: "Geschossdecke mehrschichtig",
|
||
layers: [
|
||
// Estrich (schwimmend) → Trittschalldämmung.
|
||
{ componentId: "screed", thickness: 0.06 },
|
||
// Innere Fuge der Dämmung trifft auf die Betondecke (massiv) → 0.13 mm.
|
||
{ componentId: "insulation", thickness: 0.04, jointLineStyleId: "thin" },
|
||
// Betondecke (Rohdecke, tragend) — innerste/unterste Schicht.
|
||
{ componentId: "concrete", thickness: 0.2 },
|
||
],
|
||
},
|
||
],
|
||
roofTypes: [
|
||
{
|
||
id: "roof-warm",
|
||
name: "Steildach gedämmt",
|
||
// Aussen (Eindeckung) → innen (Verkleidung); Bauteile aus der Bibliothek.
|
||
layers: [
|
||
{ componentId: "roof-tiles", thickness: 0.04 }, // Eindeckung (Tonziegel)
|
||
{ 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: [
|
||
{
|
||
id: "door-standard",
|
||
name: "Zimmertür 0.9 m",
|
||
kind: "dreh",
|
||
leafCount: 1,
|
||
leafStyle: "glatt",
|
||
frameThickness: 0.05,
|
||
frameKind: "zarge",
|
||
frameWidth: 0.06,
|
||
defaultWidth: 0.9,
|
||
defaultHeight: 2.0,
|
||
},
|
||
{
|
||
// Aussentür: Blockrahmen, in die Aussenschale zurückgesetzt, mit Oberlicht.
|
||
id: "door-entry",
|
||
name: "Haustür Blockrahmen (Oberlicht)",
|
||
kind: "dreh",
|
||
leafCount: 1,
|
||
leafStyle: "glas",
|
||
glazingRatio: 0.35,
|
||
frameThickness: 0.07,
|
||
frameKind: "blockrahmen",
|
||
frameWidth: 0.09,
|
||
insetFromFace: 0.14,
|
||
insetFace: "aussen",
|
||
transomHeight: 0.45,
|
||
threshold: true,
|
||
defaultWidth: 1.1,
|
||
defaultHeight: 2.1,
|
||
},
|
||
],
|
||
windowTypes: [
|
||
{
|
||
id: "window-standard",
|
||
name: "Fenster 1.2 × 1.4 m",
|
||
kind: "drehkipp",
|
||
wingCount: 1,
|
||
glazing: "zweifach",
|
||
frameThickness: 0.06,
|
||
frameWidth: 0.06,
|
||
defaultSillHeight: 0.9,
|
||
defaultWidth: 1.2,
|
||
defaultHeight: 1.4,
|
||
},
|
||
{
|
||
// Zweiflügliges Fenster mit Kämpfer, Oberlicht und Schichteinzug.
|
||
id: "window-double",
|
||
name: "Fenster 2-flügl. + Oberlicht",
|
||
kind: "drehkipp",
|
||
wingCount: 2,
|
||
mullionRows: 1,
|
||
glazing: "dreifach",
|
||
frameThickness: 0.07,
|
||
frameWidth: 0.07,
|
||
insetFromFace: 0.12,
|
||
insetFace: "aussen",
|
||
transomHeight: 0.4,
|
||
defaultSillHeight: 0.85,
|
||
defaultWidth: 1.8,
|
||
defaultHeight: 1.9,
|
||
},
|
||
],
|
||
stairTypes: [
|
||
{
|
||
// Standard: normale Ortbeton-Laufplatte (schräge, offene Untersicht).
|
||
id: "stair-standard",
|
||
name: "Betontreppe 1.0 m",
|
||
structure: "beton",
|
||
closedRisers: true,
|
||
treadThickness: 0.05,
|
||
nosing: 0.03,
|
||
railing: "keine",
|
||
defaultWidth: 1.0,
|
||
},
|
||
{
|
||
id: "stair-massiv",
|
||
name: "Massivtreppe (auf Sockel)",
|
||
structure: "massiv",
|
||
closedRisers: true,
|
||
treadThickness: 0.04,
|
||
nosing: 0.03,
|
||
railing: "keine",
|
||
defaultWidth: 1.0,
|
||
},
|
||
{
|
||
// Offene Wangentreppe: schwebende Tritte (unten offen), zum direkten
|
||
// Vergleich mit der Massivtreppe — im ObjectInfoPanel der Treppe zuweisen.
|
||
id: "stair-wange-holz",
|
||
name: "Wangentreppe Holz (offen)",
|
||
structure: "wange",
|
||
closedRisers: false,
|
||
treadThickness: 0.05,
|
||
nosing: 0.03,
|
||
railing: "keine",
|
||
defaultWidth: 1.0,
|
||
},
|
||
{
|
||
// Aufgesattelte Treppe mit geschlossenen Setzstufen (Tritt + Setzstufe,
|
||
// aber unten offen — der Raum darunter bleibt frei).
|
||
id: "stair-aufgesattelt",
|
||
name: "Aufgesattelt (Setzstufen)",
|
||
structure: "aufgesattelt",
|
||
closedRisers: true,
|
||
treadThickness: 0.05,
|
||
nosing: 0.025,
|
||
railing: "keine",
|
||
defaultWidth: 1.0,
|
||
},
|
||
],
|
||
// Oberste Schnitte: Geschosse + Schnitt/Ansicht + freie Zeichnung.
|
||
// baseElevation wird über recomputeFloorElevations gestapelt: EG=0, OG=2.6.
|
||
drawingLevels: recomputeFloorElevations([
|
||
{ id: "eg", name: "Erdgeschoss", kind: "floor", visible: true, locked: false, floorHeight: 2.6, cutHeight: 1.0 },
|
||
{ id: "og", name: "Obergeschoss", kind: "floor", visible: true, locked: false, floorHeight: 2.6, cutHeight: 1.0 },
|
||
{
|
||
id: "schnitt-a",
|
||
name: "Schnitt A",
|
||
kind: "section",
|
||
visible: true,
|
||
locked: false,
|
||
linePoints: [{ x: -1, y: 2 }, { x: 6, y: 2 }],
|
||
directionSign: 1,
|
||
},
|
||
{
|
||
id: "ansicht-sued",
|
||
name: "Ansicht Süd",
|
||
kind: "elevation",
|
||
visible: true,
|
||
locked: false,
|
||
// Ansichtslinie südlich des Demo-Hauses, Blick nach Norden (+y) — damit
|
||
// die Demo-Ansicht sofort rendert (analog zur gesäten Schnitt-A-Linie).
|
||
linePoints: [{ x: -1, y: -2 }, { x: 6, y: -2 }],
|
||
directionSign: 1,
|
||
shadows: true,
|
||
},
|
||
{ id: "detail-1", name: "Detail 1", kind: "drawing", visible: true, locked: false },
|
||
]),
|
||
// Grafik-Kategorie-Baum (DOSSIER-Codes 1:1).
|
||
layers: [
|
||
{ code: "00", name: "Raster", color: "#484850", lw: 0.13, visible: true, locked: false },
|
||
{ code: "01", name: "Vermessung", color: "#707078", lw: 0.18, visible: true, locked: false },
|
||
{ code: "10", name: "Situation", color: "#909090", lw: 0.18, visible: true, locked: false },
|
||
{ code: "11", name: "Strasse", color: "#a89070", lw: 0.18, visible: true, locked: false },
|
||
{ code: "12", name: "Gebäude", color: "#888888", lw: 0.25, visible: true, locked: false },
|
||
{ code: "13", name: "Bäume", color: "#50a050", lw: 0.13, visible: true, locked: false },
|
||
{ code: "14", name: "Höhenlinien", color: "#909050", lw: 0.18, visible: true, locked: false },
|
||
{
|
||
code: "20",
|
||
name: "Wände",
|
||
color: "#0a0a0a",
|
||
lw: 0.35,
|
||
visible: true,
|
||
locked: false,
|
||
children: [
|
||
{ code: "21", name: "Türen/Fenster", color: "#5080c8", lw: 0.25, visible: true, locked: false },
|
||
{ code: "22", name: "Möbel", color: "#909090", lw: 0.13, visible: true, locked: false },
|
||
{ code: "25", name: "Stützen", color: "#c87050", lw: 0.5, visible: true, locked: false },
|
||
],
|
||
},
|
||
{ code: "30", name: "Decken", color: "#605850", lw: 0.35, visible: true, locked: false },
|
||
{ code: "31", name: "Dächer", color: "#7a4a3a", lw: 0.35, visible: true, locked: false },
|
||
{ code: "40", name: "Treppen", color: "#4a6a58", lw: 0.35, visible: true, locked: false },
|
||
{ code: "35", name: "Träger", color: "#a87858", lw: 0.5, visible: true, locked: false },
|
||
{ code: "50", name: "Text", color: "#d0d0d0", lw: 0.13, visible: true, locked: false },
|
||
{ code: "60", name: "Räume", color: "#5a7a9a", lw: 0.13, visible: true, locked: false },
|
||
{ code: "90", name: "Referenzen", color: "#585860", lw: 0.13, visible: true, locked: false },
|
||
{ code: "99", name: "Konstruktion", color: "#404048", lw: 0.13, visible: true, locked: false },
|
||
],
|
||
walls: [
|
||
// ── EG: 5 × 4 m Raum (CCW) ──
|
||
// Süd (unten)
|
||
{ id: "W1", type: "wall", floorId: "eg", categoryCode: "20", start: { x: 0, y: 0 }, end: { x: 5, y: 0 }, wallTypeId: "aw", height: 2.6 },
|
||
// Ost (rechts)
|
||
{ id: "W2", type: "wall", floorId: "eg", categoryCode: "20", start: { x: 5, y: 0 }, end: { x: 5, y: 4 }, wallTypeId: "aw", height: 2.6 },
|
||
// Nord (oben)
|
||
{ id: "W3", type: "wall", floorId: "eg", categoryCode: "20", start: { x: 5, y: 4 }, end: { x: 0, y: 4 }, wallTypeId: "aw", height: 2.6 },
|
||
// West (links)
|
||
{ id: "W4", type: "wall", floorId: "eg", categoryCode: "20", start: { x: 0, y: 4 }, end: { x: 0, y: 0 }, wallTypeId: "aw", height: 2.6 },
|
||
// Innere Querwand (Mauerwerk verputzt): teilt den Raum in zwei. Beide Enden
|
||
// treffen mittig auf die Innenflächen von W1 (unten) und W3 (oben) → zwei
|
||
// Mittelspannen-T-Stösse; computeJoins schneidet die Querwand bündig an.
|
||
{ id: "W9", type: "wall", floorId: "eg", categoryCode: "20", start: { x: 2.4, y: 0 }, end: { x: 2.4, y: 4 }, wallTypeId: "iw", height: 2.6 },
|
||
|
||
// ── OG: 5 × 3 m Raum (CCW), keine Tür ──
|
||
// Süd (unten)
|
||
{ id: "W5", type: "wall", floorId: "og", categoryCode: "20", start: { x: 0, y: 0 }, end: { x: 5, y: 0 }, wallTypeId: "aw", height: 2.6 },
|
||
// Ost (rechts)
|
||
{ id: "W6", type: "wall", floorId: "og", categoryCode: "20", start: { x: 5, y: 0 }, end: { x: 5, y: 3 }, wallTypeId: "aw", height: 2.6 },
|
||
// Nord (oben)
|
||
{ id: "W7", type: "wall", floorId: "og", categoryCode: "20", start: { x: 5, y: 3 }, end: { x: 0, y: 3 }, wallTypeId: "aw", height: 2.6 },
|
||
// West (links)
|
||
{ id: "W8", type: "wall", floorId: "og", categoryCode: "20", start: { x: 0, y: 3 }, end: { x: 0, y: 0 }, wallTypeId: "aw", height: 2.6 },
|
||
],
|
||
doors: [
|
||
{
|
||
id: "D1",
|
||
type: "door",
|
||
hostWallId: "W1",
|
||
categoryCode: "21",
|
||
position: 0.8, // Startkante 0.8 m ab Wand-Start → Tür x 0.8–1.7, links von W9 (x=2.4)
|
||
width: 0.9,
|
||
height: 2.1,
|
||
swing: "left", // schlägt nach innen (in den Raum) auf
|
||
hinge: "start",
|
||
},
|
||
],
|
||
// Öffnungen (Fenster/Türen) — ein Beispiel-Fenster in der EG-Südwand (W1,
|
||
// frei von der Tür) und in der EG-Nordwand (W3). Kategorie „21" (Türen/Fenster).
|
||
openings: [
|
||
{
|
||
id: "O1",
|
||
type: "opening",
|
||
hostWallId: "W1",
|
||
categoryCode: "21",
|
||
kind: "window",
|
||
typeId: "window-standard",
|
||
position: 3.0, // Startkante 3.0 m → Fenster x 3.0–4.0, rechts von W9 mit Massiv-Abstand
|
||
width: 1.0,
|
||
height: 1.2,
|
||
sillHeight: 0.9,
|
||
},
|
||
{
|
||
id: "O2",
|
||
type: "opening",
|
||
hostWallId: "W3",
|
||
categoryCode: "21",
|
||
kind: "window",
|
||
typeId: "window-standard",
|
||
// Startkante 0.6 m ab W3-Start (x=5) → Fenster x 3.0–4.4, rechts von W9 (x=2.4)
|
||
// mit sichtbarer Massiv-Wand dazwischen (die Querwand stösst auf Mauerwerk).
|
||
position: 0.6,
|
||
width: 1.4,
|
||
height: 1.3,
|
||
sillHeight: 0.9,
|
||
},
|
||
],
|
||
// Decken (Slabs) — Geschossdecke über dem EG (= Boden des OG). Umriss = EG-
|
||
// Grundriss (5 × 4 m). Kategorie „30 Decken", mehrschichtiger Deckenstil
|
||
// „dg-massiv" (Estrich + Trittschalldämmung + Betondecke, 30 cm), OK bündig
|
||
// mit dem EG-Wandkopf (baseElevation + floorHeight = 2.6 m). `wallTypeId`
|
||
// bleibt als LEGACY-Rückfall gesetzt (siehe `getCeilingType`).
|
||
ceilings: [
|
||
{
|
||
id: "C1",
|
||
type: "ceiling",
|
||
floorId: "eg",
|
||
categoryCode: "30",
|
||
outline: [
|
||
{ x: 0, y: 0 },
|
||
{ x: 5, y: 0 },
|
||
{ x: 5, y: 4 },
|
||
{ x: 0, y: 4 },
|
||
],
|
||
wallTypeId: "aw",
|
||
ceilingTypeId: "dg-massiv",
|
||
},
|
||
],
|
||
// Dach — Satteldach über dem Baukörper (5×4), First entlang X (längere Seite),
|
||
// 0.4 m Traufüberstand. Sitzt auf der OG-Oberkante (roofBaseElevation-Default).
|
||
roofs: [
|
||
{
|
||
id: "RF1",
|
||
type: "roof",
|
||
floorId: "og",
|
||
categoryCode: "31",
|
||
outline: [
|
||
{ x: 0, y: 0 },
|
||
{ x: 5, y: 0 },
|
||
{ x: 5, y: 4 },
|
||
{ x: 0, y: 4 },
|
||
],
|
||
shape: "sattel",
|
||
pitchDeg: 30,
|
||
overhang: 0.4,
|
||
ridgeAxis: "x",
|
||
thickness: 0.2,
|
||
},
|
||
],
|
||
// Treppen — eine gerade Beispieltreppe im EG entlang der Ostwand, steigt ins OG
|
||
// (totalRise = Geschosshöhe). Kategorie „40 Treppen".
|
||
stairs: [
|
||
{
|
||
id: "ST1",
|
||
type: "stair",
|
||
floorId: "eg",
|
||
categoryCode: "40",
|
||
shape: "straight",
|
||
typeId: "stair-standard",
|
||
start: { x: 3.7, y: 0.4 },
|
||
dir: { x: 0, y: 1 },
|
||
runLength: 3.2,
|
||
width: 1.0,
|
||
totalRise: 2.6,
|
||
stepCount: 15,
|
||
up: true,
|
||
},
|
||
],
|
||
// Räume (SIA-416-Flächen) — ein Beispielraum im EG (lichte Innenkontur des
|
||
// 5×4-m-Umrisses, Aussenwände Typ „aw" 0.345 m dick → Innenmaß 4.655×3.655 m
|
||
// ≈ 17.01 m²). Kategorie „45 Räume", SIA-Blatt HNF (Hauptnutzfläche).
|
||
rooms: [
|
||
{
|
||
id: "R1",
|
||
type: "room",
|
||
floorId: "eg",
|
||
categoryCode: "60",
|
||
siaCategory: "HNF",
|
||
name: "Wohnen",
|
||
// Lichte Innenkontur = Wandachse ± halbe Wanddicke (Typ „aw": Putz aussen
|
||
// 0.02 + Dämmung 0.16 + Backstein 0.15 + Putz innen 0.015 = 0.345 m Gesamt-
|
||
// dicke → 0.1725 m je Seite). Der Raumumriss liegt damit exakt auf der
|
||
// Innenfläche der Wand, nicht in der Wand-Poché.
|
||
boundary: [
|
||
{ x: 0.1725, y: 0.1725 },
|
||
{ x: 4.8275, y: 0.1725 },
|
||
{ x: 4.8275, y: 3.8275 },
|
||
{ x: 0.1725, y: 3.8275 },
|
||
],
|
||
color: "#6b7280",
|
||
stampAnchor: { x: 2.5, y: 2.0 },
|
||
},
|
||
],
|
||
// Freie 2D-Zeichengeometrie — anfangs leer; wird mit den Zeichenwerkzeugen
|
||
// gefüllt (docs/design/drawing-tools.md).
|
||
drawings2d: [],
|
||
// Kontext-Schicht (importierte/abgeleitete Geometrie) — anfangs leer; wird
|
||
// über den DXF-Import bzw. die Gelände-Generierung gefüllt.
|
||
context: [],
|
||
};
|
||
|
||
/**
|
||
* Leeres Projekt (nur Bibliotheken, keine Geometrie) — für manuelle Tests, die
|
||
* ohne das Demo-Haus starten wollen (z. B. Standort-Import auf leerer Fläche).
|
||
*/
|
||
export const emptyProject: Project = {
|
||
...sampleProject,
|
||
id: "empty",
|
||
name: "Leeres Projekt",
|
||
walls: [],
|
||
doors: [],
|
||
openings: [],
|
||
ceilings: [],
|
||
roofs: [],
|
||
stairs: [],
|
||
rooms: [],
|
||
columns: [],
|
||
extrudedSolids: [],
|
||
drawings2d: [],
|
||
context: [],
|
||
};
|