Files
DOSSIER-STANDALONE/src/model/sampleProject.ts
T
karim 68a0459d0e Schnittebenen 2D↔3D Phase 1+2, native Fenster, Hell/Dunkel-Theme, SWISSIMAGE-Import
- 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)
2026-07-20 10:51:37 +02:00

584 lines
21 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.81.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.04.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.04.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: [],
};