karim c5c60d3df5 2D: nach dem ersten getippten Wert bleibt das andere Feld ebenfalls fix
Nutzer-Feedback zum vorigen Commit: das Einfrieren beim Tab-Öffnen
gefiel, aber sobald man einen Wert (z. B. Länge) eintippte und Enter
drückte, sprang der ANDERE Wert (Winkel) sofort wieder auf die Maus um
-- gewünscht war stattdessen: Enter fixiert BEIDE Werte (den getippten
UND den beim Öffnen eingefrorenen), und erst ein explizites Tab in das
andere Feld gibt die Maus für GENAU dieses Feld wieder frei.

Vereinfachung statt Zusatzmechanismus: `locks` wird beim ÖFFNEN (erstes
Tab) nicht mehr leer gelassen, sondern SOFORT mit beiden aktuellen
Werten (Länge+Winkel bzw. bei geführten Kanten nur der eine Abstands-
Wert) befüllt -- die ohnehin vorhandene Locked/Live-Mischung greift
dadurch von Anfang an vollständig, ein separater "eingefroren"-Zustand
(gripFrozenPointRef/edgeFrozenPointRef aus dem vorigen Commit) wird
dadurch überflüssig und wieder entfernt. Zykeln (weiteres Tab bei schon
offenem Feld) wechselt jetzt zum anderen Feld UND löst NUR dessen Lock
(delete locks[nextActive]) -- das verlassene Feld bleibt exakt auf
seinem letzten Wert (getippt oder eingefroren) fixiert. Getippte Werte
(submitGripEditValue/submitEdgeEditValue) sowie Escape-Verhalten
(global = ganzen Drag verwerfen, in der Befehlszeile = nur Feld
schließen) bleiben unverändert.

tsc/vitest 922/922 grün.
2026-08-22 00:24:51 +02:00

Dossier

Open-Source-CAAD (Computer Aided Architecture Design). Modelliert ein Gebäude aus semantischen Bauteilen und zieht daraus saubere, normgerechte 2D-Pläne — ohne Revit. Desktop-App — auf macOS über Tauri, auf Linux über eine Electron-Shell (weil Tauris Linux-Webview WebKitGTK kein zuverlässiges WebGPU bietet, das die Rendering-Engines brauchen); dieselbe Codebasis läuft auch im Browser (eingeschränkt, ohne native Fenster/Dateisystem-Integration).

Das ist die eigenständige Neuimplementierung des Rhino-Plugins DOSSIER: dieselbe Denkweise (Geschosse, Kategorie-Ebenen, mehrschichtige Bauteile, Prioritäts- Verschneidung), aber mit eigenem Datenmodell + eigener Rendering-Engine (Rust/WASM/WebGPU, intern „Nordstern" genannt) statt Rhino-Aufsatz.

Grundgedanke

Es gibt ein semantisches Modell als einzige Wahrheit. Jede Ansicht — 3D, Grundriss, Schnitt, Ansicht, PDF — wird daraus abgeleitet. Darstellung (Detailgrad, Linienstärken, Schraffuren) wird erst beim Rendern angewandt, nie in die Geometrie eingebacken. Wer eine Wand verschiebt, verschiebt sie überall.

Konkret heißt das auch: Der Grundriss entsteht nicht aus einem zerschnittenen 3D-Mesh, sondern analytisch aus den Bauteil-Parametern (Wandachsen + Dicken → Linien, Öffnungen → Lücken + Symbol). PDF-Export ist derselbe Plan, nur mit echten mm-Stiftstärken statt Bildschirm-Hairlines. Schnitte und Ansichten laufen über eine eigene, analytische Rust-Pipeline (kein Hidden-Line-Removal nötig) und sind seit Juli live im 3D-Viewport verdrahtet, nicht nur ein Spike.

Stand heute

Aus dem ursprünglichen Risiko-Spike ist binnen weniger Wochen ein funktionsreiches Desktop-BIM-Tool geworden: eigenes semantisches Gebäudemodell, zwei eigene Rust/WASM-Rendering-Engines, IFC/DXF/PDF/STL/OBJ- Export, Swisstopo-Import, SIA-416-Flächen, Materialbibliothek, Layouts/ Plansätze, native Tauri-Fenster. ~91.000 Zeilen TypeScript + ~19.500 Zeilen Rust (ohne Tests), 891 Vitest-Tests, alle grün.

Funktioniert (Auszug, nicht abschliessend):

  • Semantisches Modell mit mehrschichtigen Wänden, L-Eck-Gehrung und Prioritäts-T-/X-Stössen (joinPriority am Component) — konsistent in Grundriss, 3D-Viewport und 3D-Live-Schnitt.
  • Parametrische Wände, Decken, Treppen (gerade/L/Wendel), Dächer (Flach/Pult/Sattel/Walm/Mansarde/Zelt), Stützen, SIA-416-Räume mit automatischer Bilanz + CSV-Export.
  • Türen & Fenster gehostet in Wänden, mit Rahmen/Zarge/Kämpfer/Oberlicht, Detailgrad grob/mittel/fein, echte Rechteck-Löcher im 3D-Wandkörper.
  • Rhino-artiges Kommandosystem mit getippten Koordinaten (5,3 · r5,3 · 5<45) und Tab-Feld-Zyklus; Snapping, Grips, Trim/Split/Join, 2D-Booleans.
  • Live 2D↔3D-Schnitt: eine Schnittebene im 3D-Viewport folgt derselben Prioritäts-Logik wie der 2D-Plan-Schnitt (Rust-Port, keine Diskrepanz).
  • Vektor-Export: PDF (Einzel- und Mehrseiten-Layouts), DXF, IFC4 (mit echten Fenster-/Tür-Löchern), STL/OBJ, CSV-Bauteilliste.
  • Materialbibliothek: 13 gebündelte PBR-Starter plus Live-Suche der kompletten ambientCG-Bibliothek (1K/2K/4K, On-Demand-Download).
  • Layouts/Plansätze mit mehreren Viewports pro Blatt, Ausschnitte (View-Snapshots), Kamera-Presets, Norden-Rotation.
  • Import: DXF/DWG, Swisstopo (swissBUILDINGS3D/-ALTI3D/SWISSIMAGE, radiusgenau zugeschnitten), OSM-Kontextimport, .lin/.pat.
  • Native Desktop-Integration (Tauri): eigene randlose Fenster, native Speichern/Öffnen-Dialoge, eigenes .obp-Dateiformat mit OS-Level-Lock gegen Doppelöffnen, mehrere native Zusatzfenster (Resources, Settings, …).
  • Resource Manager (Component/Hatch/Line/Typ-Editoren), regelbasierte Overrides, Panel-System (dockbar/floatend), i18n (de/en).

Bewusst noch offen (Auszug):

  • Echtes Mesh-Boolean für Öffnungen — funktioniert heute über achsparallele Rechteck-Löcher; ein generisches CSG-Boolean existiert bereits (trucksolid/csgrs), ist aber nicht an die Wand-Pipeline angeschlossen.
  • 3D-Griffsystem: Feld-Controller (Tab-Zyklus) und Snapping fehlen für 3D-Grip-Drag (im 2D vollständig vorhanden).
  • DWG/DXF-Domänenimport (Entitäten → echte Wände/Öffnungen) — Lesen funktioniert, das Mapping auf das Modell ist unbegonnen; DWG-Schreiben fehlt.
  • make2D-Kommando (3D-Ansicht → flacher 2D-Plan mit Füllungen).
  • Bekannte, noch nicht bereinigte Doppelspur Door[]/Opening[] im Modell.

Stack

Shell Tauri auf macOS (WKWebView+WebGPU) · Electron/Chromium auf Linux (WebKitGTK kann kein WebGPU) — beide randlos, eigene Titelleiste, gemeinsame React-App
Frontend React + TypeScript + Vite
3D eigener Rust/WASM/WebGPU-Renderer „Nordstern" (render3d, Default), Three.js als leichtgewichtiger Zweitpfad
2D-Plan eigener Rust/WASM/WebGPU-Renderer (render2d), plus ein TS/WebGL2-Renderer (plan/glPlan), plus SVG (PlanView.tsx, immer als Interaktions-/Fallback-Ebene aktiv)
Geometrie eigener 2D-Kernel (src/geometry/kernel2d.ts); ein Rust-Port (src-tauri/kernel2d) existiert nur als Paritätstest, läuft nicht produktiv
CSG/Extrusion trucksolid-Crate (truck + csgrs), fürs Extrude-Kommando
Export eigener IFC4-Writer, jspdf/svg2pdf.js (Vektor-PDF), eigener DXF-Writer, STL/OBJ
Import dxf-parser, @mlightcad/libredwg-web (DWG), eigene .lin/.pat-Parser
Materialien jszip (ambientCG-Zip-Entpacken), three.js TextureLoader

Der ursprünglich geplante OCCT/opencascade.js-HLR-Pfad für Schnitte ist komplett entfernt (weder Dependency noch Code) — abgelöst durch die analytische Rust-Schnitt-Pipeline (siehe Grundgedanke oben).

Entwicklung

npm install
npm run dev        # Vite, http://localhost:5187
npm run tauri:dev  # Tauri-Fenster (macOS — nativer Zielrahmen dort)
npm run electron   # Electron-Fenster (Linux — WebGPU über Chromium statt WebKitGTK)
npx tsc -b         # Typecheck
npm run build      # tsc -b && vite build
npm test           # vitest run

WASM-Engines nach Rust-Änderungen neu bauen (nur .rs committen, src/engine/pkg*/ ist gitignored):

npm run build:engine     # render2d
npm run build:engine3d   # render3d
npm run build:truck      # trucksolid

render3d/Wasm3DViewport-Änderungen sind nicht per Puppeteer/Browser verifizierbar — im laufenden tauri:dev-Fenster selbst testen.

Aufbau

src/
  model/       semantisches Modell (types, joins, parametricWalls, roomStamp, terrain)
  geometry/    2D-Kernel (offset/trim/fillet/intersect, ceiling/opening/roomArea/stair/roof/column)
  commands/    Rhino-artiges Befehlssystem (engine, parser, registry, cmds/)
  tools/       interaktive Zeichenwerkzeuge + Snapping + Transformationen
  plan/        Grundriss-Ableitung (generatePlan) + PlanView (SVG) + glPlan (WebGL2) + Rust-Bindings
  viewport/    Viewport3D (Three.js) + Wasm3DViewport (Rust/wgpu „Nordstern", Default)
  export/      IFC4-, PDF-, DXF-, STL/OBJ-, CSV-Export aus derselben Plan-/Modell-Struktur
  materials/   ambientCG-Live-Suche + gebündelte Starter-Bibliothek + PBR-Runtime
  panels/      dockbares Panel-System + die einzelnen Paletten
  state/       eigener Store (useSyncExternalStore) + Slices (project/selection/view/layout/…)
  native/      Tauri-only: native Fenster, macOS-Menüleiste, Fenster-Chrome
  ui/          App.tsx-Shell, Top-Bar, Resource Manager, Kontextmenü, Kommandozeile
  io/          Import/Export (DXF, DWG, .lin, .pat), Swisstopo/LV95, OSM-Kontext
  i18n/        Wörterbücher de/en
src-tauri/     5 eigenständige Rust-Crates (render2d/render3d/kernel2d/trucksolid/
               dwgimport, je headless UND per wasm-pack baubar) + der Tauri-Host selbst

Konventionen

  • Bezeichner im Code sind englisch, an Vectorworks-Terminologie angelehnt (Design Layer, Component, Hatch, Wall Style). UI-Texte sind deutsch, immer über t('key') — keine hartcodierten Strings im JSX.
  • Intern alles in Metern; Anzeige via formatM.

Weiterlesen

Dieses README ist die einzige Doku im öffentlichen Repo — STATUS.md, ARCHITECTURE.md, ROADMAP.md, HANDOVER.md, PENDENZEN.md, CONVENTIONS.md und docs/ sind bewusst per .gitignore ausgeschlossen (interne Arbeitsnotizen/Backlog, kein öffentlicher Anspruch auf Vollständigkeit oder Aktualität) und daher hier absichtlich nicht verlinkt.

Lizenz

Copyright © 2026 Karim Gabriele Varano. Veröffentlicht unter der GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later) — siehe LICENSE. Dossier ist Teil der openbureau-Suite.

Die AGPL verlangt, dass auch bei Betrieb als Netzwerk-/Webdienst der (ggf. geänderte) Quellcode für die Nutzer verfügbar gemacht wird. Drittkomponenten behalten ihre jeweiligen Lizenzen (siehe „Über"-Dialog in der App).


Die UI ist deutsch; Schweizer Spezifika (SIA-416-Flächen, Swisstopo-Geodaten) sind ein bewusster Differenzierer.

S
Description
Browser-BIM — standalone browser port of the DOSSIER Rhino plugin (semantic model, 2D/3D derived views, drawing tools)
Readme AGPL-3.0 155 MiB
2026-07-31 14:17:46 +02:00
Languages
TypeScript 78.8%
Rust 13.7%
JavaScript 4.2%
CSS 3.2%