Schnitt/Ansicht: SectionOutput aus render3d an die Zeichenebenen anbinden

- render3d/web.rs: GPU-freies WASM-Binding cut_section_json(model_json, p, n)
  → JSON {cutPolygons, visibleEdges, hiddenEdges} in (u,v)-Metern.
- src/plan/toSection.ts (neu): SectionOutput-Typen, sectionPlaneFromLevel()
  leitet die Schnittebene aus linePoints/directionSign ab, computeSection()
  flacht über projectToModel3d ab und ruft das Binding.
- src/engine/engine3d.ts (neu): geteilter memoisierter pkg3d-Loader, damit
  3D-Viewport und Schnittpfad EINE mod.default()-Init teilen.
- generatePlan.ts: generateSectionPlan() übersetzt SectionOutput in
  bestehende Primitive (Cut = polygon mit Poché-Schraffur, sichtbare Kante =
  line solid, verdeckte Kante = line dashed) — keine neue Primitive-Art nötig.
- App.tsx: SectionPlanView ersetzt den Stub für Ebenen vom Typ Schnitt/Ansicht;
  rendert dasselbe PlanView, mit lokalisierten Hinweisen (lädt/keine Linie/Fehler).
- i18n de/en: section.*-Schlüssel.
- Öffnungen erscheinen korrekt (Brüstung/Sturz-Teilrechtecke) über die
  projectToModel3d-Teilkörper-Zerlegung.

Gates: tsc -b 0, build grün (WASM = eigener Lazy-Chunk), render3d cargo test 29/29,
wasm32 --features web check grün.
This commit is contained in:
2026-07-03 18:37:49 +02:00
parent 3402e6ac96
commit 056ca2c288
8 changed files with 514 additions and 30 deletions
+23
View File
@@ -0,0 +1,23 @@
// Gemeinsamer Lade-Einstieg für das render3d-WASM-Modul (pkg3d, gebaut über
// `npm run build:engine3d`). EINMAL geladen + initialisiert und memoisiert:
// `mod.default()` (der wasm-bindgen-Init) darf nur EINMAL laufen — ein zweiter
// Init würde die Closures des ersten verwerfen („closure invoked recursively or
// after being dropped"). Sowohl der 3D-Viewport (useWasm3dRenderer) als auch die
// Schnitt-/Ansichts-Pipeline (plan/toSection) teilen sich daher DIESE Instanz.
//
// Bewusst schwach typisiert (`any`): das echte `.d.ts` entsteht erst beim
// wasm-Build; die Aufrufer legen ihre eigene Minimal-Schnittstelle darüber.
let enginePromise: Promise<any> | null = null;
/** Lädt das WASM-Modul einmalig und gibt das initialisierte Modul zurück. */
export function loadEngine3d(): Promise<any> {
if (!enginePromise) {
enginePromise = (async () => {
const mod: any = await import("./pkg3d/render3d.js");
await mod.default(); // lädt render3d_bg.wasm
return mod;
})();
}
return enginePromise;
}