Files
DOSSIER-STANDALONE/docs/welle-c-hlr-spike/FEASIBILITY.md
T
karim 8fd8987b70 2D-Plan-Renderer auf WebGL2 (GPU) + akkumulierter Funktionsstand
Neuer GPU-Renderer fuer den Grundriss (src/plan/glPlan/): Earcut-Tessellierung
(konkav-faehig), gehrte Linienzuege (Miter), echte Papier-mm-Strichbreiten im
Massstab (repliziert den SVG-printStrokeVb-Pfad), Hybrid mit scharfem SVG-Text-
Overlay. GPU ist der Standardpfad; der SVG-Renderer bleibt automatischer Fallback,
falls WebGL2/Shader nicht verfuegbar sind. Imperativer Pan (rAF + CSS-transform)
fuer fluessige Interaktion ohne React-Re-Render je Frame.

Enthaelt zudem den bisher nicht committeten Arbeitsstand des Browser-BIM
(Oeffnungen, Treppen, Raeume, Decken, DXF-Export, Materialbibliothek, Kontext-
Import, Tauri-Compute-Boundary-PoC).
2026-07-02 00:12:39 +02:00

6.4 KiB
Raw Blame History

Welle C — HLR-Spike: Feasibility-Report

2D-Vektor-Schnitte/-Ansichten aus dem 3D-Modell via Hidden-Line-Removal (HLR) mit opencascade.js (OCCT-WASM). Isolierter De-Risking-Spike, NICHT in die App verdrahtet. Einheiten: Meter.

Ergebnis (kurz)

HLR funktioniert in diesem Browser-Projekt. opencascade.js initialisiert im Vite-Build, und der HLR-Lauf liefert korrekte, getrennte sichtbare/verdeckte 2D-Kanten. Verifiziert im echten Browser (Chromium via Vite-Dev-Server) an einer L-Wand + Bodenplatte, Front-Ansicht:

Messwert Wert
Sichtbare Kanten (sharp) 9
Verdeckte Kanten 16
Reine HLR-Rechenzeit ~21 ms
WASM-Größe (unkomprimiert) 62.8 MB (65 864 037 Bytes)
WASM-Größe (gzip) ~19.6 MB
WASM-Fetch (lokal, Dev) ~113 ms
Modul-Init (Emscripten instanziieren) ~450 ms (Browser) / ~680 ms (Node)

Beweis-Artefakte: hlr-elevation-proof.svg / .png in diesem Ordner — sichtbare Kanten durchgezogen, verdeckte gestrichelt. Die Zeichnung liest sich als korrekte Hidden-Line-Ansicht (Silhouette + sichtbare Front-Kanten voll, verdeckte hinten gestrichelt).

Der genutzte API-Pfad (wichtig!)

Der geplante klassische Pfad (HLRBRep_Algo/HLRBRep_PolyAlgo + HLRBRep_HLRToShape/HLRBRep_PolyHLRToShape) ist im prebuilt Vollbuild 1.1.1 NICHT verfügbar: diese Klassen sind nur als Handle_…-Smart-Pointer gebunden, ohne konstruierbare Roh-Klasse und ohne den HLRToShape-Extraktor. Ein direkter Aufbau darüber ist damit nicht möglich.

Verwendeter, funktionierender Pfad: HLRAppli_ReflectLines — der High-Level- OCCT-Wrapper, der intern GENAU den exakten HLR-Algorithmus (HLRBRep_Algo) fährt. Er ist als Klasse gebunden und liefert getrennt sichtbare/verdeckte Kanten nach Kanten-Typ:

const rl = new oc.HLRAppli_ReflectLines(shape);
rl.SetAxes(dirX, dirY, dirZ, atX, atY, atZ, upX, upY, upZ); // Ortho-Projektion
rl.Perform();
const T = oc.HLRBRep_TypeOfResultingEdge;
// (typ, visible, in3d) → in3d=false liefert 2D-projizierte Kanten (Z≈0)
const visSharp   = rl.GetCompoundOf3dEdges(T.HLRBRep_Sharp,   true,  false);
const visOutline = rl.GetCompoundOf3dEdges(T.HLRBRep_OutLine, true,  false);
const hidSharp   = rl.GetCompoundOf3dEdges(T.HLRBRep_Sharp,   false, false);

Kanten-Extraktion: TopExp_Explorer_2(compound, TopAbs_EDGE, TopAbs_SHAPE)TopoDS.Edge_1(current)new BRepAdaptor_Curve_2(edge)FirstParameter/LastParameter/Value(u) (gp_Pnt mit .X() .Y() .Z()).

embind-Überladungen sind versioniert (_1, _2, …) und die Nummerierung im Vollbuild folgt NICHT der Argumentzahl. Empirisch verifiziert: BRepPrimAPI_MakeBox_1(dx,dy,dz), BRepPrimAPI_MakeBox_3(gp_Pnt, gp_Pnt), BRepAlgoAPI_Fuse_3(a, b), gp_Pnt_3(x,y,z). Bei einem Versionswechsel des Pakets müssen diese Suffixe neu geprüft werden (Fehlermeldung nennt die erwartete Parameterzahl).

Vite-/package.json-Änderungen (genau)

  • package.json: Dependency opencascade.js@^1.1.1 (Vollbuild).
  • vite.config.ts (additiv, analog zum bestehenden LibreDWG-Muster):
    • Zwei Aliase → virtuelle Module auf die echten Paket-Dateien: virtual:occt-gluedist/opencascade.wasm.js, virtual:occt-wasm-urldist/opencascade.wasm.wasm?url.
    • optimizeDeps.exclude: ["opencascade.js"] (esbuild kommt mit dem UMD-Wrapper + Node-Shims der Glue nicht klar → Vor-Bündeln ausschließen).
  • src/section/occt-wasm.d.ts: Ambient-Stubs für die zwei virtuellen Module.
  • Geladen wird per dynamischem Import in src/section/occt.ts → die 62-MB- WASM landet NICHT im Haupt-Bundle, sondern als separater Lazy-Chunk + Asset.

Verifiziert: vite build der App bleibt grün und unverändert groß (kein OCCT-Chunk, da der Spike nicht verdrahtet ist). Ein Lib-Build, der hlr.ts referenziert, splittet OCCT sauber in einen eigenen Glue-Chunk + WASM-Asset ab. tsc ist für die neuen Dateien grün. (npm run build schlägt aktuell in tsc -b fehl — ausschließlich wegen fehlender i18n-Keys in den parallel bearbeiteten Dateien commands/cmds/stair.ts / state/*, NICHT wegen dieses Spikes.)

Dateien dieses Spikes

  • src/section/hlr.ts — Kernmodul: Box-Specs → Fuse → HLR → 2D-Polylinien (hlrFromBoxes, hlrShape, VIEWS, hlrToSvg).
  • src/section/occt.ts — Lazy-Loader + schmale Typ-Fassade + Lade-Metriken.
  • src/section/occt-wasm.d.ts — Ambient-Deklarationen der virtuellen Module.
  • docs/welle-c-hlr-spike/ — dieser Report + Proof-SVG/-PNG.

Bewertung für Welle C

Viabel. Der exakte HLR liefert saubere, normgerechte Vektor-Kanten mit korrekter Sichtbarkeit — genau das, was Schnitt/Ansicht brauchen und was reines three.js-Kanten-Projizieren nicht robust liefert (dort fehlt echte Flächen-Verdeckung). Die 2D-Polylinien passen direkt in die bestehende SVG-Plan-Pipeline (Pt2/Vec2-kompatibel).

Der Kostenpunkt ist die WASM-Größe (62.8 MB / ~19.6 MB gzip). Für einen Spike akzeptabel; für Produktion zu groß, um sie eager zu laden.

Empfohlener Integrations- + Größenreduktions-Plan

  1. Lazy laden (bereits so gebaut): OCCT erst bei erster Schnitt-/Ansichts- Erzeugung dynamisch importieren; Ladezustand in der UI anzeigen. Der Grundriss läuft weiter ohne OCCT (parametrisch, wie bisher).
  2. Web-Worker: HLR im Worker fahren, damit der UI-Thread frei bleibt (die WASM ist groß, aber der HLR-Lauf selbst ist mit ~20 ms günstig).
  3. Größe reduzieren — lohnt sich klar: ein Custom-Build von opencascade.js (das Paket unterstützt make.py/Docker-Build mit einer Symbol-Whitelist). Für Welle C reicht ein minimaler Satz: BRepPrimAPI_* (bzw. der spätere Solid-Erzeuger), BRepAlgoAPI_Fuse/Common, HLRAppli_ReflectLines + HLRBRep_TypeOfResultingEdge, TopExp_Explorer, TopoDS, BRepAdaptor_Curve, gp_*. Erfahrungswerte solcher Minimal-Builds liegen bei ~515 MB WASM statt 62 MB — Aufwand: ein reproduzierbarer Docker-Build in CI, der die .wasm/.js als Projekt-Asset eincheckt. Alternativ die beta 2.0 prüfen (moderneres Build-System, evtl. bereits schlankere Module + die klassischen HLR-Klassen konstruierbar).
  4. Fallback, falls die Größe untragbar bleibt: three.js-basierte Kanten-Extraktion (EdgesGeometry) + eigene Sichtbarkeit via Depth-Peeling / GPU-Occlusion. Deutlich mehr Eigenaufwand, weniger robust bei Verschneidungen — daher nur zweite Wahl; OCCT-HLR bleibt der empfohlene Weg.