Files
DOSSIER-STANDALONE/docs/welle-c-hlr-spike/FEASIBILITY.md
T
karim 3d2d4d6321 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

125 lines
6.4 KiB
Markdown
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.
# 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-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).
- `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.