Commit Graph

303 Commits

Author SHA1 Message Date
karim 476f31ccad Kontextmenü-/Editor-State aus App.tsx in useContextMenuState() extrahiert
Bündelt layerClipboard, menu, editor, nativeLayerSettingsCode,
stampEditorRoomId und editTextId in einem eigenen Hook (Teil der
laufenden App.tsx-Verkleinerung).
2026-07-21 19:31:19 +02:00
karim 85f386a496 App.tsx: Hell/Dunkel-State nach theme/useThemeMode.ts
Reiner Umzug von useState + Setter-Wrapper (persistiert in localStorage via
themeMode.ts) in einen eigenen Hook. Verhaltensgleich.
2026-07-21 16:24:33 +02:00
karim 43ea7c5d8e App.tsx: Dialog-Sichtbarkeits-State nach state/useDialogState.ts
Reiner Umzug von neun useState-Deklarationen (Ressourcen-Fenster, Layout-
Ansicht, Import-/Export-/Einstellungs-Dialoge, Drop-Feedback) in einen
eigenen Hook — bewusst KEIN Store-Slice (dieser State ist laut den
Original-Kommentaren explizit lokal/transient, keine Undo/Redo- oder
Cross-Component-Relevanz). Verhaltensgleich.
2026-07-21 16:15:59 +02:00
karim b621a7da64 App.tsx entschlackt: Kontextmenüs nach src/menus/, Views nach src/views/
Reiner Umzug (verhaltensgleich, byte-identische Funktionskörper): Kontextmenü-
Builder (buildMenuItems + layer/level/plan/viewport-Menüs) nach
src/menus/contextMenu.tsx; InlineEditor sowie Content/LevelPlanView/
SectionPlanView (der View-Router der Hauptansicht) nach src/views/. App.tsx
7130 → 5917 Zeilen. Setzt die in CONVENTIONS.md/state-architecture.md
vorgesehene, bisher nie umgesetzte Struktur endlich um (STATUS.md §4.3).

Dazu ein unabhängiger CSS-Fix: .plan-selected (Auswahl-Hervorhebung im 2D-Plan)
fehlte die fill-opacity, die zwei Regeln weiter unten bei .plan-marquee/
.tool-preview-fill schon gesetzt ist. Im Dunkel-Theme ist --accent-dim
transparent (zufällig unauffällig), im neuen Standard-Hell-Theme aber fast
deckend weiss — dadurch verdeckte die Auswahl die Schraffur der gewählten
Wand/Decke/des Raums vollständig.
2026-07-21 14:47:40 +02:00
karim 5516b745a9 Doku: STATUS.md (Codebase-Analyse) + Kern-Docs an den Ist-Zustand angeglichen
Vollständige Bestandsaufnahme der Codebasis als neue STATUS.md (Kennzahlen,
Feature-Inventar, Mist-Liste: toter Code, verwaiste WASM-Crates,
Doku-Widersprüche). ARCHITECTURE.md/README.md/CONVENTIONS.md waren noch auf
dem Tag-1-Planungsstand (Electron/Three.js/OpenCascade/Zustand/HLR-Worker) und
beschrieben nicht mehr, was tatsächlich gebaut wurde (eigene Rust/WASM-Engines,
eigener Store, analytische Rust-Schnitt-Pipeline, Tauri auf macOS + Electron
auf Linux). ROADMAP.md und HANDOVER.md als historisch markiert (Hinweis-Box),
Inhalt unverändert.
2026-07-21 13:35:58 +02:00
karim 76c9d164c9 Materialbibliothek: statisches Broad-Set entfernt, Live-ambientCG bleibt
Der aus der Desktop-Session übernommene statische 88er-Katalog listete 75
Materialien ohne mitgelieferte Texturen (kaputte Thumbnails in der
Schnellauswahl). Bibliothek auf die 13 tatsächlich gebündelten Starter
gekürzt; Fetch-Script und der zugehörige .gitignore-Block entfernt. Alles
darüber hinaus läuft über die bereits vorhandene Live-Suche (1K/2K/4K).
2026-07-21 13:35:44 +02:00
karim 78d3e6a955 Fix: doppelten RoofingTiles013A-Eintrag nach Rebase entfernt 2026-07-20 11:05:08 +02:00
karim a009a5e9b4 Materials-Feature: Bibliothek + Fetch-Script + Manifest (aus Desktop-WIP übernommen) 2026-07-20 11:03:30 +02:00
karim b9e330ecb7 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
karim 51e57c368b swissBUILDINGS3D-Import: auf den gesuchten Radius zuschneiden statt die ganze STAC-Kachel zu liefern
Jede STAC-Kachel (DXF) liefert ALLE Gebäude der Kachel als EIN gemeinsames
Mesh (parseDxf sammelt alle 3DFACE/Polyface-Entities eines Files in denselben
Puffer) — ohne Zuschnitt landete bei einem Import IMMER die komplette Kachel
im Modell, teils mehrere Kilometer über den gesuchten Suchradius hinaus.
Live gegen echte STAC-Daten verifiziert: zwei 1.4 km auseinanderliegende
Adressen (gleiche Kachel) lieferten vorher IDENTISCHE, unclipped Geometrie
(62532 Dreiecke); danach jeweils nur die ~400 Dreiecke im eigenen Suchradius.

clipMeshToBbox schneidet + kompaktiert das Mesh (nicht referenzierte Ecken
entfernt, Indizes neu gemappt) — sonst sähe jede Verbraucher-Logik, die roh
über `positions` statt `indices` iteriert (Bounding-Box, Kamera-Fit), weiter
die volle ungeschnittene Ausdehnung.
2026-07-12 21:35:31 +02:00
karim 932a229f09 Fenster/Tür: 2D und 3D setzen "aussen" jetzt auf dieselbe Wandfläche
Nutzer-Report: "im 2D innen bündig und im 3D aussen bündig". Root Cause: das
2D-Vorzeichen für insetFace:"aussen" (windowSymbol) war gegenüber der echten
Aussenschicht der Wand (erste Wandtyp-Schicht, kleinster Achs-Offset in
addWallPoche/pushSegment) invertiert — "aussen" landete am inneren
Wandputz statt am äusseren. Dieselbe Vorzeichenverwechslung steckte auch in
addOpeningFrameBand (Tür-Rahmenband), den Sturzlinien und dem Rollladenkasten.
Die 3D-Seite (openingAxisBox/resolveFrameNormalRange) war bereits korrekt
(zwei kompensierende Vorzeichen ergaben zufällig das richtige Ergebnis) und
bleibt unverändert.

+1 Regressionstest, der 2D- und 3D-Rahmenposition direkt gegen die bekannte
Aussenschicht der Wand prüft.
2026-07-12 21:24:48 +02:00
karim da0f066e49 Fenster: Rahmen-Kontur in Aufsicht separat von den geschnittenen Laibungsblöcken stylebar
Bisher teilten sich die geschnittenen Laibungs-/Stulp-Blöcke (O-Blöcke,
Schnittfläche des Rahmenmaterials) und die durchlaufende Rahmen-Kontur
zwischen ihnen (Aufsicht, nicht geschnitten) dieselbe frameLine-Farbe. Neues
Opening.frameViewLine übersteuert nur noch die Kontur; ohne Angabe fällt sie
weiterhin auf frameLine zurück (bisheriges Verhalten unverändert). frameLine
im UI zu "Rahmen (Schnitt)" umbenannt, um die beiden Kategorien zu unterscheiden.
2026-07-12 20:19:20 +02:00
karim 5be49c5557 Neuer Bezugspunkt: Projekt nach Kataster-/3D-Import auf praktischen Ursprung verschieben
Nach einem Standort-Import landet die Kontext-Geometrie dort, wo der gesuchte
Ort war — das kann weit vom bisherigen Modell-Ursprung liegen. Neuer Befehl
"georef" (Button in SitePanel) verschiebt das GESAMTE Projekt per Klick so,
dass der gewählte Punkt zum neuen Ursprung wird; geoAnchor wandert automatisch
mit, der reale LV95-Bezug bleibt exakt erhalten (rekonstruierbar, auch beim
späteren Export). Bewusst nur Translation, keine Rotation — mehrere Felder
(Roof.ridgeAxis, Column.rotation, Text-/Bild-Rotation) sind achsen-/winkel-
gebunden und bräuchten bei einer Drehung eigene Sorgfalt.
2026-07-12 20:13:22 +02:00
karim 0ab3f70277 Kontext-Objekte im 3D-Viewport anwählbar (Klick, Bounding-Box-Highlight, Löschen)
Importierte Gebäude/Terrain-Meshes waren bisher nur ein Eintrag im Geo-Panel,
nicht direkt im 3D anwählbar. Raycast/Pick-Geometrie um Kontext-Meshes
erweitert, Auswahl-Kanal (selectedContextObjectIds) ergänzt, Highlight als
Bounding-Box-Umriss (volles Dreiecks-Wireframe wäre bei grossen Importen zu
dicht), Entf-Taste löscht die Auswahl, SitePanel hebt sie in der Liste hervor.
2026-07-12 19:54:00 +02:00
karim 02c36bd35b Georeferenzierung: persistenter Standort-Bezug statt Neuberechnung je Import
Neues Project.geoAnchor: verbindet EINEN Modell-Punkt mit seiner realen
LV95-Koordinate. Bisher berechnete jeder Standort-Import (Gebäude/Terrain/
OSM) unabhängig einen neuen Bezug aus der jeweils gesuchten Adresse — bei
mehreren Importen mit leicht unterschiedlichen Suchbegriffen landete
importierter Kontext lagefalsch zueinander.

Der erste Import in einem Projekt setzt den Bezug automatisch (Modell-(0,0)
= gesuchter Ort) und speichert ihn; alle weiteren Importe verwenden densel-
ben Bezug, unabhängig vom neu gesuchten Ort (der bestimmt nur noch WOVON
Daten geladen werden, nicht mehr WOHIN sie im Modell platziert werden).
UI: Anzeige des aktiven Bezugs im Import-Dialog mit Zurücksetzen-Option.

Löst das strukturelle Problem noch nicht vollständig (der Bezug sitzt immer
bei Modell-(0,0) — passt nur, wenn das eigene Gebäude dort gezeichnet ist),
aber behebt die akute Inkonsistenz zwischen mehreren Importen.
2026-07-12 19:33:16 +02:00
karim 450932a0c3 DXF-Import: Polyface-Mesh-Faces (POLYLINE) wurden nie erkannt — swissBUILDINGS3D-Gebäude blieben leer
Root Cause für „Gebäude-Import funktioniert nicht": Die installierte
dxf-parser-Version liefert Face-Vertex-Indizes NICHT als `faces`-Array,
sondern als vier einzelne Felder (Gruppencodes 71–74: faceA/faceB/faceC/
faceD). Unser addPolyfaceMesh/isMeshPolyline prüfte auf ein `faces`-Array,
das in dieser Version nie existiert — jede POLYLINE-Polyface-Mesh (exakt das
Format der swissBUILDINGS3D-DXF-Kacheln) ergab dadurch 0 Dreiecke, obwohl
Positionen geschrieben wurden. Live gegen echte swissBUILDINGS3D-Kacheln
verifiziert: vorher 0 Meshes, jetzt tausende Dreiecke mit realistischen
Schweizer Höhenwerten. +3 Tests (rohes DXF, nicht gemockt, deckt auch die
zugrundeliegende Bibliothek ab), Suite 794 grün.
2026-07-12 19:22:53 +02:00
karim eabc71c5e8 swissBUILDINGS3D-Import: Absturz bei riesigen Kacheln behoben, Übersprungene sichtbar gemacht
Nutzer-Report „funktioniert nicht": Der Import stürzte mit einem harten
RangeError ab, sobald eine STAC-Kachel entpackt die maximale JS-String-Länge
überschritt (DXF komprimiert stark — eine Kachel unter dem 150-MB-Limit kann
trotzdem >700 MB unkomprimierten Text ergeben, real reproduziert für ein
dicht bebautes Stadtzentrum). downloadAssetText prüft jetzt zusätzlich die
JSZip-interne unkomprimierte Grössenschätzung VOR dem Entpacken und fängt
verbleibende Fehler (Netzwerk/ZIP/String-Länge) sicher ab, statt zu werfen.

Zu grosse/fehlgeschlagene Kacheln wurden bisher stumm übersprungen (0 Gebäude,
keine Erklärung — sah wie ein Bug aus). fetchBuildings3d liefert jetzt
skippedTiles mit; der Dialog zeigt „X Kachel(n) übersprungen, zu gross" statt
eines wortlosen Leer-Ergebnisses.
2026-07-12 19:15:45 +02:00
karim ba7136d8a2 3D-Kanten: falsche Diagonalen auf doppelseitigen Meshes (Dach/Glas) behoben
Kontext-Meshes (Dach, Fenster-Glas/-Rahmen, künftig swissBUILDINGS3D-Import)
werden von append_context_mesh IMMER doppelseitig aufgebaut (jedes Dreieck +
gespiegelte Rückseite mit invertierter Normale), weil die Mesh-Pipeline
Backface-Culling aktiv hat. Die Kanten-Erkennung sah dadurch an JEDER Kante
ein exakt entgegengesetztes Normalen-Paar (Vorder-/Rückseite desselben
Dreiecks) und wertete das fälschlich als Knick — jede Flächen-Innendiagonale
eines doppelseitigen Meshes wurde gezeichnet (Nutzer-Report: sichtbare
Dreiecks-Diagonalen auf Dach und Fensterglas im "Schattiert mit Kanten"-Modus).

Fix: Rückseiten-Duplikate (Normalen-Paar mit dot ≈ -1) werden vor der Rand-/
Knick-Entscheidung zusammengeführt (ein Vertreter je Original-Dreieck) —
danach gilt dieselbe Logik wie bei einseitigen Meshes (Wände), unabhängig
davon ob doppelseitig gerendert wurde. +5 Tests (doppelseitige Varianten der
bestehenden Fälle), 88/88 grün mit --features render.
2026-07-12 19:10:06 +02:00
karim b68fd7f58e 3D-Ansicht: neuer Darstellungsmodus "Schattiert mit Kanten" (BIM-Look)
Neuer RenderStyle::ShadedEdges in render3d: wie "shaded" (echte Bauteilfarben,
beleuchtet), zusätzlich dunkle Modell-Kanten obenauf wie bei "hidden" — der
typische Revit/ArchiCAD-Look, der bisher fehlte (nur reines Weiss+Kanten via
"hidden" oder reine Bauteilfarben ohne Kanten via "shaded" waren möglich).
Nutzt dieselbe tiefengebiaste Flächen-Pipeline wie "hidden", damit die Kanten
sauber obenauf liegen (kein Z-Fighting). +6 Rust-Tests (--features render,
83/83 grün). Als neue Option "shaded-edges" in beiden Darstellungsart-
Dropdowns der 3D-Oberleiste; Three.js-Fallback ignoriert den Wert graceful
(fällt auf shaded zurück, bekommt bewusst keine neuen Features).
2026-07-12 18:59:05 +02:00
karim 7a098443f9 Fenster: Linienstärke/Farbe (sashLine) wirkt jetzt auch bei 1:100
Die einzige bei "grob" sichtbare Glaslinie war fest codiert (weder Opening.
color noch die neuen Kategorie-Übersteuerungen griffen dort). Nutzt jetzt
sashLine (Fenster-Kategorie), konsistent mit mittel/fein.
2026-07-12 18:52:08 +02:00
karim 31d8dd7916 Fenster: Flügelstoss-Blöcke separat von Laibungs-Enden steuerbar (sashLine statt frameLine)
windowSymbol trug beide Blocktypen (Laibungs-Enden UND Flügelstoss-Marken)
im selben meetingMarks-Array, dadurch übersteuerte frameLine auch die Marke
zwischen den Flügeln — Nutzer wollte diese separat regelbar. Aufgeteilt in
jambMarks (Laibungs-Enden, zählt zu "Rahmen") und meetingMarks (Flügelstoss,
zählt zu "Fenster"/sashLine).
2026-07-12 18:51:09 +02:00
karim f8383256a8 Attribute: Farbfeld zeigt nur noch ein Quadrat statt zwei
ColorHexField stellte Swatch UND natives <input type="color"> sichtbar
nebeneinander dar (zusätzlich zum separaten Hex-Textfeld) — wirkte wie zwei
Farbfelder pro Zeile. Hex-Textfeld entfernt, natives Color-Input liegt jetzt
unsichtbar über dem Swatch (öffnet die native Palette beim Klick auf das
einzige sichtbare Quadrat). Betrifft alle Attribute-Farbfelder in der App,
nicht nur die neuen Fenster-Linien-Felder.
2026-07-12 18:48:25 +02:00
karim 269aef80e2 Fenster: Farbe/Strichstärke je Linien-Kategorie im Attribute-Panel einstellbar
Neue per-Öffnung-Übersteuerung (Opening.frameLine/sashLine/sillLineStyle,
je {color?, weight?}) für Blendrahmen+Stulp-/Laibungsblöcke, Flügelrahmen/
Sprossen und die Auf-/Untersicht-Sims-Andeutung separat. Fehlt eine
Übersteuerung, gilt weiterhin der bisherige Default (Opening.color/Haarlinie).
UI: drei neue Zeilen (Farbfeld + Strichstärke) im Objekt-Info-Panel bei
selektiertem Fenster.
2026-07-12 18:45:28 +02:00
karim c9da774703 Grundriss: Oberlicht-Andeutung (opening-transom) entfernt
Zeigte immer eine gestrichelte Linie quer über die Öffnung bei transomHeight>0
— auf der Wandachse, unabhängig davon, ob die horizontale Schnittebene den
Kämpfer überhaupt trifft. Ein Kämpfer/Oberlicht ist ein Höhen-, kein
Grundriss-Merkmal; die Linie war daher architektonisch nicht aussagekräftig
(Nutzer-Report, dieselbe Kategorie Fehler wie die entfernte Brüstungslinie).
Betrifft Fenster UND Türen (gemeinsame addOpeningFrameBand-Funktion).
2026-07-12 18:35:11 +02:00
karim 7bf2245522 Fenster: konfigurierbare Auf-/Untersicht-Andeutung im Grundriss (WindowType.sillLine)
Ersatz für die entfernte pauschale Brüstungslinie: wählbar aussen/innen/beide
Flächen + Blickrichtung Auf-/Untersicht (Aufsicht dünn gepunktet, Untersicht
gestrichelt wie die übrigen Überkopf-Projektionen), an der tatsächlichen
Rahmenkante statt der Wandachse. Default aus (kein Feld gesetzt = keine Linie).
UI-Feld im Fenstertyp-Editor.
2026-07-12 18:32:19 +02:00
karim b32f1569fd Fenster-Grundriss: pauschale Brüstungslinie entfernt
Lief immer auf der Wandachse, unabhängig von der tatsächlichen Rahmen-
position/-grösse — Nutzer-Report „liegt falsch". Ersatz kommt als gezielt
konfigurierbare Auf-/Untersicht-Andeutung (nächster Commit).
2026-07-12 18:29:29 +02:00
karim aa46686cad Fenster-Grundriss: keine Glaslinie mehr im Feld, auch nicht bei fein
Die dünne Glaslinie (fein: Doppellinie) lief mittig durchs Glasfeld, egal wo
und wie gross das Fenster war — Nutzer wollte dort keine Haarlinie, weder bei
mittel (schon vorher entfernt) noch bei fein. Blendrahmen + Flügelrahmen +
Rahmenblöcke an Laibung/Flügelstoss bleiben als Kontur bestehen.
2026-07-12 18:25:02 +02:00
karim eec56dc535 Fenster-Grundriss: keine separate Trennlinie mehr neben dem Rahmenblock am Flügelstoss
Der Rahmenblock (voller Profilquerschnitt) und eine dünne window-mullion-
Linie lagen an derselben Stelle übereinander — überflüssig, der Block markiert
den Stoss bereits vollständig. Nur noch für Alt-Fenster ohne Typ (kein Block
verfügbar) bleibt die Linie bestehen.
2026-07-12 18:20:28 +02:00
karim ac269f91c5 3D-Wände: Top folgt der Dach-Unterkante statt sie zu durchdringen (Z-Fighting-Fix)
Wände wurden bisher unabhängig von Dächern mit fixer Höhe emittiert, während
Dächer separat gerendert wurden — wo eine geneigte Dachfläche den flachen
Wand-Top kreuzte, überlappten sich beide Volumen (Z-Fighting im 3D-Viewer,
Nutzer-Report mit Screenshot).

roofUndersideAt (geometry/roof.ts) liefert die Dach-Unterkante an einem
Grundriss-Punkt (Ebenengleichung je Dachfläche, dieselbe Herleitung wie im
Vertikalschnitt). clipPieceToRoofs (toWalls3d.ts) zerlegt betroffene Wand-
Achsenstücke in feine Schritte (~15 cm) und klemmt jeden auf die dort lokal
gemessene Dach-Unterkante — eine Treppenstufen-Annäherung an eine echte
geneigte Giebelwand-Stirnfläche (render3d-Wandkörper haben nur einen flachen
Top; eine echte Schrägfläche bräuchte einen neuen Mesh-Pfad). Ohne Dach im
selben Geschoss bleibt das Verhalten unverändert (kein Overhead).
2026-07-12 18:15:22 +02:00
karim 2a6ef1c0a8 Fenster-Grundriss: Rahmen-/Stulp-Blöcke über volle Rahmentiefe, plus Laibungs-Blöcke an den Enden
Die Stulp-Marken an Flügelstössen waren als kleines, von der Rahmentiefe
unabhängiges Quadrat gezeichnet statt als echter Profilquerschnitt über die
ganze Rahmentiefe (aussen bis innen). Zusätzlich fehlten die entsprechenden
Blendrahmen-Querschnittsblöcke an den beiden Laibungs-Enden komplett — jetzt
zeigt jedes Fenster dort einen Block, unabhängig von der Flügelanzahl.
2026-07-12 18:07:09 +02:00
karim 8a6556c099 Fenster-Grundriss: Sims/Stulp folgen der eingezogenen Rahmenkante, mittel ohne Glaslinie
Sims (Fensterbank) und Anschlag-Kerben nutzten pauschal die volle Wandfläche
statt der tatsächlichen (ggf. per insetFromFace eingezogenen) Rahmen-
Aussenkante — bei rückversetzten Rahmen sass die Fensterbank dadurch sichtbar
falsch. Stulp-Marken nutzen jetzt die bereits korrekt (tiefenbewusst) in
windowSymbol berechneten meetingMarks statt einer zweiten, abweichenden
Neuberechnung. Ausserdem: SIA fig. 37 (1:50) zeigt noch keine Glaslinie, nur
Rahmen + Stulp-Quadrat — die kommt gemäss fig. 38 erst bei 1:20 dazu.
2026-07-12 17:58:27 +02:00
karim f662578946 Standort-Import: echte swissBUILDINGS3D-Gebäude (2.0/3.0) + swissALTI3D-Terrain
Ersetzt die stark vereinfachte Box-Extrusion (vec25-Footprint + Pauschalhöhe
9m) durch echte Gebäudegeometrie aus den swissBUILDINGS3D-STAC-Kacheln (Wahl
zwischen Generation 2.0 stabil und 3.0 Beta, DXF-Kacheln über den bestehenden
dxfParser als Mesh eingelesen). Gelände kommt neu aus echten swissALTI3D-XYZ-
Rastern (0.5m/2m wählbare Punktdichte) statt der groben profile.json-Näherung.
Gemeinsames STAC-Client-Modul (stacApi.ts) für beide Quellen.
2026-07-12 17:38:47 +02:00
karim 875f95e9c1 Fenster: echte Sprossen-Spalten (mullionCols) analog Kämpfer-Zeilen
Vertikale Sprossenteilung im Glasfeld (mullionCols−1 Spalten), spiegelbildlich
zur bestehenden mullionRows-Logik: 3D-Rahmen-Riegel, Ansichts-Trennlinien +
Glasscheiben als echtes rows×cols-Raster, Eingabefeld im Fenstertyp-Editor und
im ResourceManager.
2026-07-12 17:38:21 +02:00
karim 126936faf0 Wand-Poché bei "grob" immer vollschwarz (SIA 400 Fig. 36)
Bisher war die Füllung bei Detailgrad "grob" nur schwarz, wenn das
dominante Wandbauteil selbst ein "solid"-Hatch-Pattern hatte — bei
mehrschichtigen Wandtypen (Backstein/Dämmung/Verputz) blieb sie weiss.
SIA 400 kennt bei 1:100 aber keine Materialunterscheidung, die Poché ist
immer vollschwarz. Fix + Regressionstest von Hermes/Qwen3 übernommen und
um den fehlenden Test sowie das Aufräumen der jetzt toten
backbonePocheFill-Hilfsfunktion ergänzt.
2026-07-12 16:20:36 +02:00
karim eb25c4e9c2 Kommentare Öffnungssymbole: DIN- durch SIA-Referenz ersetzen
Die Dreh-/Kipp-/Schiebe-Symbolik in Ansicht und 3D war fälschlich als
"DIN-Konvention" kommentiert (Grundlage ist SIA 400 B.9.1.3). Reine
Kommentar-/Doku-Korrektur, keine Verhaltensänderung.
2026-07-12 16:02:59 +02:00
karim 7e03c1476d Fenster im Grundriss: grob/mittel/fein nach SIA 400 klar unterscheiden
grob (1:100) zeigt nur eine schematische Glaslinie, mittel (1:50) einen
Blendrahmen mit Flügel-Trennlinien und Stulp-Quadrat je Flügelstoss, fein
(1:20) zusätzlich verschachtelte Flügelrahmen, Glas als Doppellinie
(Isolierverglasung) und zwei Stulp-Quadrate je Stoss — vorher waren mittel
und fein praktisch identisch. Referenz: SIA 400 Anhang B.9.1, Fig. 36–38
(docs/research/sia400-fenster-tueren.md).
2026-07-11 18:18:37 +02:00
karim da7392e7c6 Ansicht: Kämpfer-/Sprossen-Zeilen (mullionRows) im Fenster
Die 2D-Ansicht teilte das Glasfeld nur vertikal (Flügel) und beim Oberlicht,
ignorierte aber mullionRows — ein Fenster mit horizontaler Sprossenteilung sah
in der Ansicht ungeteilt aus, im 3D dagegen geteilt. Jetzt splittet die Ansicht
das Glasfeld je Flügel in mullionRows Zeilen mit Trennlinien, konsistent zum 3D.
2026-07-11 13:21:52 +02:00
karim 70cb30f1dd Schiebefenster-Öffnungssymbol (DIN-Pfeil) in Ansicht und 3D
Schiebeflügel hatten bisher kein Öffnungssymbol (nur Dreh/Kipp/Drehkipp). DIN
zeichnet für Schiebeelemente keinen Anschlag-Winkel, sondern einen Pfeil in
Laufrichtung — ergänzt in der 2D-Ansicht (toElevation) und im 3D-fein
(toWalls3d), Richtung aus der Griffseite. Test deckt Schiebe/Fest/Drehkipp ab.
2026-07-11 13:11:58 +02:00
karim e8c76e7e2a Ansicht robuster: exaktes Hidden-Line-Clipping, T-Stoss-Ecken, Öffnungsschatten
Die bisherigen Näherungen versagten bei realen Grundrissen: Bounding-Box-
Occlusion liess Linien hinterer Wände durch die Vorderfassade scheinen, sobald
eine Hinterwand höher/breiter war als die verdeckende; die Eckverlängerung
schloss nur exakt geteilte Endpunkte, keine T-/versetzten Stösse.

- Hidden-Line: jede Umriss-/Kantenlinie wird jetzt exakt gegen die näheren
  opaken Flächen (inkl. Öffnungs-Rahmenquads, da die Fassade um Öffnungen
  ausgespart ist) geclippt statt per Bbox verworfen. Verdeckte Teilstücke
  entfallen, überstehende bleiben — keine Durchsicht mehr.
- Ecken: Wandenden verlängern sich bis zur Aussenfläche jeder anstossenden
  Wand (L/T/X über Körper-Enthaltung), aber nur für fassaden-PARALLELE Wände —
  facaden-senkrechte Innenwände würden sonst als Balken vor die Fassade ragen.
- Öffnungen: Fenster/Türen werfen mit Schatten-Toggle einen Laibungs-/Reveal-
  schatten (Band unter dem Sturz + an der linken Laibung, 45° von links oben),
  sodass sie als Vertiefung lesen. Verdeckte Öffnungen werden ganz gecullt.

Neue Tests decken die konkreten Fehlerbilder ab (deckungsgleiche/höhere
Hinterwand, verdecktes Fenster, Reveal-Schatten an/aus).
2026-07-11 13:10:21 +02:00
karim 1183c02350 Fenster-Rahmentiefe: realistischer Default statt volle Wanddicke
Recherche zu Vectorworks/ArchiCAD/realem Fensterbau ergab: ein Rahmen ohne
explizite frameDepth füllte bisher die GESAMTE Wanddicke — echte Fenster sind
unabhängig von der Wanddicke nur ~70-90mm tief und sitzen mit sichtbarer
Laibung/Leibung in der Öffnung, statt als massiver Block über die volle Tiefe.
Neuer Default 70mm (2D-Grundriss und 3D konsistent), Glas-Falzmass von 3cm auf
2cm reduziert und Mehrfachverglasungs-Scheibendicke/-abstand kompakter, damit
Dreifachverglasung noch in den schlankeren Rahmen passt.
2026-07-11 12:50:10 +02:00
karim 0a47da14fa 3D-Öffnungen: Flügel-/Türblatt-Regression fixen; Ansicht: Eck-Joins, Durchsicht, Farbig-Modus
3D: Flügelrahmen sass fälschlich vor der Fassade (Rahmen-Glas-Rahmen-Sandwich)
und Türen hatten kein Blatt — beides aus dem letzten 'fein'-Merge. Flügelband
jetzt hinter die Blendrahmen-Vorderkante zurückgesetzt, Türblatt (Voll- und
Teilverglasung) ergänzt.

Ansicht: Wandboxen liefen achsenzu-achse ohne Eckverlängerung (dreieckige
Kerbe an jeder Gebäudeecke, sichtbar v.a. im Schlagschatten) — Wände mit
gemeinsamem Endpunkt verlängern sich jetzt um die halbe Nachbardicke. Die
Linien-Pipeline zeichnet alle Konturen in einem eigenen Durchgang über allen
Füllungen, wodurch Öffnungs-/Fugenlinien hinterer Fassaden durch nähere Wände
schienen — verdeckte Flächen/Öffnungen werden jetzt gar nicht mehr emittiert.
Farbig-Modus zeigte bisher nur Weiss statt Bauteilfarben; Wand/Dach/Fenster/
Tür tragen jetzt echte Farben, Mono bleibt die reine Linienzeichnung.
2026-07-11 12:38:13 +02:00
karim 5033d52bdf Merge: 3D-Öffnungen auf VW-fein-Niveau
Fenster/Türen im 3D deutlich plastischer (Nutzer-Referenz Vectorworks 'fein'):
- Flügelrahmen als eigener, ~12 mm vorstehender Körper (Blendrahmen →
  Flügelprofil → Glas ablesbar), jetzt ab Detailgrad 'mittel'
- DIN-Öffnungssymbole AUF dem Glas (dünne dunkle Prismen, frei orientiert
  via openingPlaneBox): Dreh/Kipp/Dreh-Kipp wie in der 2D-Ansicht, nur 'fein',
  nur je nicht-festem Flügel
- Fensterbank in 3D: Bank + Tropfkanten-Stufe, seitlich überstehend, aussen
  auskragend (sillBoard-Gating wie 2D)
- Tür-Zarge mit Umgriff: Bekleidungsring vor beiden Wandflächen (nur
  frameKind 'zarge'; Blockrahmen bleibt bündig)
Gating: grob nichts · mittel Rahmen/Flügel/Sims/Zarge · fein + Sprossen +
Symbole. +4 Mesh-Tests.
2026-07-11 03:00:32 +02:00
karim 7db02fc30d Model3dOptions.detail: Doc-Kommentar an neue Gating-Staffelung angepasst 2026-07-11 02:59:33 +02:00
karim 12117f3aeb 3D-Öffnungen im VW-Detail 'fein': verschachtelte Flügelrahmen, DIN-Symbole, Sims, Zargen-Umgriff
- Flügelrahmen sitzen in eigenem, ~12 mm nach aussen vorstehenden und flacheren
  Quer-Band (abgesetzte, plastische Schachtelung Blendrahmen -> Flügelrahmen ->
  Glas) statt flach mit dem Blendrahmen verschmolzen; jetzt bei mittel + fein.
- DIN-Öffnungssymbole (Dreh/Kipp/Dreh-Kipp) als sehr dünne, in der Öffnungsebene
  gedrehte dunkle Prismen knapp vor der Glasebene (neuer Helfer openingPlaneBox);
  nur bei fein, nur je nicht-festem Flügel, exakt wie in der 2D-Ansicht.
- Fensterbank (Sims) unter der Öffnung: Bank-Quader + dünnere Tropfkanten-Stufe,
  seitlich ueberstehend, nach aussen auskragend; Gating sillBoard (keine/innen aus,
  Default zeichnen) und DetailLevel (mittel + fein).
- Tuer-Zarge mit Umgriff: schmale Bekleidungs-Platte vor beiden Wandflaechen als
  Ring um die Oeffnung (nur frameKind 'zarge'; Blockrahmen bleibt buendig).
- Mesh-Tests je Feature: Anzahl/Farbe/BBox, sillBoard- und frameKind-Gating,
  Symbole nur fein/nicht-fest, Flügelrahmen-Vorstand.
2026-07-11 02:58:50 +02:00
karim 9cad47c14a Schnitt: Wand-Dämmschraffur zurück auf Achswinkel 90 (Sprossen quer)
Der vorige Flip (297f4ed) hatte die Wand mitgedreht — dort stand die
Orientierung aber schon richtig (Sprossen quer zur stehenden Schicht =
horizontal); nur die Decke war falsch. Jetzt empirisch am Demo-Schnitt
verifiziert: Wand 90 (Sprossen horizontal), Decke 90 (Sprossen vertikal) —
beide quer zur jeweiligen Schichtrichtung. 737/737 grün.
2026-07-11 02:53:18 +02:00
karim b1daf1eb30 Ansicht-Fenster im VW-Detail: Flügelrahmen, Sims mit Tropfkante, exakte Symbole
Nutzer-Referenz: drei ablesbare Konturen (Blendrahmen → Flügelprofil → Glas)
je Flügel; Fensterbank als zwei seitlich überstehende Bänder (Bank +
Tropfkante, Default an, aus bei sillBoard keine/innen); die DIN-Öffnungs-
symbole starten/enden jetzt EXAKT auf den Glasfeld-Ecken (Dreh: Spitze am
Bandseiten-Mittel des Glasfelds, Kipp: Spitze oben Mitte — wie VW; vorher
sassen die Anker auf der Flügelspanne statt dem Glasfeld). 737/737 grün.
2026-07-11 02:44:56 +02:00
karim 297f4ed733 Schnitt: Dämmschraffur-Orientierung + Terminierung bei Decken-Anschluss
Zwei Nutzer-Reports:
1. Wandrelative Muster (Dämmwellen) waren im Schnitt bei Wand UND Decke je
   90° verdreht: die geschnittene Wand STEHT (Achswinkel 0 statt 90), die
   geschnittene Decke LIEGT (Achswinkel 90 statt absolut) — beide Bänder
   bekommen jetzt die richtige Achse.
2. applyWallTermination terminiert jetzt auch bei blossem ANSCHLUSS (±5 cm):
   eine Decke, die nur bis zur Wand-Innenkante gezeichnet ist, beendet die
   Wand trotzdem (vorher liefen Innenputz/Backstein durch, weil die
   Prioritäts-Subtraktion echten Überlapp braucht — den es dort geometrisch
   nicht gibt). Demo-Verhalten (Outline auf Wandachse) unverändert korrekt:
   dort schneidet die Decke exakt die überlappte innere Wandhälfte.
737/737 grün.
2026-07-11 02:42:48 +02:00
karim 6b48ff296d Ansicht als Linienzeichnung (VW-Look): weisse Flächen + XOR-Silhouette
Nutzer-Referenz ('so sieht es ordentlich aus'): Architektur-Ansichten sind
Linienzeichnungen, keine Grauflächen. Umsetzung:
- Alle Flächen weiss (Fassade/Dach/Rahmen/Glas/Türblatt); Kanten tragen.
- Frontale Wand-/Deckenflächen je Tiefen-Gruppe: Flächen ohne Kontur, dann
  der Vereinigungs-UMRISS der Gruppe über Kanten-XOR (xorOutlineEdges) —
  Innenkanten der Pfeiler-/Sturz-/Geschoss-Teilboxen heben sich paarweise
  auf, übrig bleibt exakt die Silhouette inklusive der Öffnungslöcher.
- Dach + schräg angeschnittene Flächen behalten ihre eigene Kontur.
Painter-Verdeckung bleibt (weisse Füllung nah überdeckt fern). 737/737 grün;
headless verifiziert — deckungsgleich mit der VW-Referenz.
2026-07-11 02:33:46 +02:00
karim 7d3dab502c Schnitt entspiegelt: u-Achse = Betrachter-RECHTS (Rust + TS koordiniert)
Die Schnitt-u-Achse nutzte cross(normal, up) — die look_at-Konvention für
Blick entlang −z. Für einen Schnitt, den man entlang +normal betrachtet,
spiegelte das die Zeichnung (Blick nach Norden zeigte Osten links). Neu:
u = cross(up, normal) — wer nach Norden blickt, hat Osten rechts. Dieselbe
Entspiegelung wie zuvor in der Ansicht (fe0aa1b).

Koordiniert geändert: SectionPlane::u_axis (section.rs; section_fill nutzt
dieselbe Methode) + sectionUAxisModel (toSection.ts; Schicht-Orientierung
wallLayersReversedInU und Dach-Schnitt hängen daran und kippen konsistent
mit — die Aussenseite bleibt in der Zeichnung physisch aussen). Rust- und
TS-Tests auf die neue Konvention gespiegelt; Engine neu gebaut.
cargo 76/76, vitest 737/737.
2026-07-11 02:30:35 +02:00
karim 41ccb1ea29 Lineale oben + links in allen 2D-Ansichten (Vectorworks-Stil)
Screen-fixe Lineal-Leisten über dem sichtbaren Ausschnitt: Major-Ticks mit
Meter-Beschriftung ('5.000m', Schrittweite 1/2/5·10^n nach Zoom), Minor-Ticks,
gedrehte Beschriftung am linken Lineal, gelber Cursor-Marker je Achse, Ecke
oben links. pointerEvents none — Klicks gehen durch. Gilt für Grundriss,
Schnitt, Ansicht und Zeichnungs-Ebenen (PlanRulers in PlanView, Default an,
per showRulers-Prop abschaltbar). 737/737 grün; headless verifiziert.
2026-07-11 02:22:14 +02:00