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).
6.4 KiB
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: Dependencyopencascade.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-glue→dist/opencascade.wasm.js,virtual:occt-wasm-url→dist/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).
- Zwei Aliase → virtuelle Module auf die echten Paket-Dateien:
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
- 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).
- 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).
- 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 ~5–15 MB WASM statt 62 MB — Aufwand: ein reproduzierbarer Docker-Build in CI, der die.wasm/.jsals Projekt-Asset eincheckt. Alternativ die beta 2.0 prüfen (moderneres Build-System, evtl. bereits schlankere Module + die klassischen HLR-Klassen konstruierbar). - 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.