Analytische Eigen-Engine-Alternative zum OCCT-HLR-Spike: Schnittebene (Punkt+Normale) gegen extrudierte Fussabdruck-Prismen; Cut-Polygone in (u,v)-Schnittkoordinaten mit Komponenten-Referenz (spaetere Schraffur), Projektion der dahinterliegenden Kanten mit Verdeckungstest, getrennt visible/hidden. SectionOutput serde-serialisierbar (Meter). 26 Tests, Example section_svg schreibt docs/welle-c-hlr-spike/section-engine-proof.svg (L-Wand+Bodenplatte: Poché, durchgezogene sichtbare, gestrichelte verdeckte Kanten). Offene Punkte in docs/design/engine-section-pipeline.md.
7.2 KiB
Schnitt/Ansicht-Pipeline: analytische Prismen-Projektion (render3d::section)
Gegenstueck zum OCCT-WASM-HLR-Spike (
docs/welle-c-hlr-spike/FEASIBILITY.md): statt eines generischen CAD-Kernels nutzt dieser Ansatz eine Invariante des Modells, um Schnitt/Ansicht rein analytisch (kein Hidden-Line-Removal-Solver) zu berechnen. Implementiert insrc-tauri/render3d/src/section.rs.
Ansatz
Jedes Bauteil in diesem Modell ist ein Prisma: ein 2D-Grundriss-Fussabdruck-
Polygon (Wand-Band bzw. Decken-Umriss, siehe mesh.rs), konstant extrudiert
ueber ein Hoehenintervall [z0, z1]. Diese Einschraenkung — konstanter
Querschnitt ueber die gesamte Hoehe — macht die Schnittgeometrie trivial im
Vergleich zu generischem HLR:
- Schnitt einer vertikalen Ebene mit einem Prisma = 2D-Geraden/Polygon-
Clipping IM GRUNDRISS (die Schnittebene projiziert im Grundriss auf eine
Linie) → ein oder mehrere u-Intervalle, in denen die Linie das Fussabdruck-
Polygon durchquert. Jedes Intervall ×
[z0, z1]ist das Cut-Rechteck. Da die Hoehe unabhaengig von der Grundriss-Position ist, ist das Ergebnis immer ein Rechteck, nie ein Trapez — auch bei diagonalen Wandachsen. - Projektion/Ansicht (Kanten hinter der Ebene, in Blickrichtung) reduziert sich auf ein 2D-Sichtbarkeitsproblem im Grundriss kombiniert mit einem Hoehen-Ueberlappungstest: da alle Seitenflaechen der Prismen vertikal sind, genuegt ein Sichtstrahl-Test im Grundriss (verdeckt ein naeheres Prisma- Fussabdruckpolygon die Sichtlinie?) plus Ueberlappung der Hoehenintervalle.
Das ersetzt einen 66-MB-WASM-CAD-Kernel durch closed-form Arithmetik in reinem
Rust, ohne zusaetzliches Laufzeitgewicht ueber render3d hinaus.
SectionOutput-Format
Modul: render3d::section. Alle Groessen in Metern.
pub struct SectionPlane { pub point: [f32; 3], pub normal: [f32; 3] }
pub struct SectionOutput {
pub cut_polygons: Vec<CutPolygon>, // JSON: "cutPolygons"
pub visible_edges: Vec<SectionEdge>, // JSON: "visibleEdges"
pub hidden_edges: Vec<SectionEdge>, // JSON: "hiddenEdges"
}
pub struct CutPolygon { pub component: ComponentRef, pub color: Rgb, pub pts: Vec<[f32; 2]> }
pub struct SectionEdge { pub component: ComponentRef, pub a: [f32; 2], pub b: [f32; 2] }
pub struct ComponentRef { pub kind: ComponentKind /* Wall | Slab */, pub index: usize }
Koordinatensystem der Ausgabe (u, v):
- Ursprung:
SectionPlane::point, projiziert. u(horizontal): Strecke entlang der Schnittebene, senkrecht zur Blickrichtung, berechnet alsnormalize(cross(normal, world_up))— dieselbe rechtshaendige Konvention wiemath::look_atsright-Vektor. Bei den vier Standard-Konstruktoren (looking_plus_x/minus_x/plus_y/minus_y) istudirekt die jeweils andere Grundriss-Achse.v(vertikal, "Hoehe"):v = world.y, ABSOLUT. Diese Codebasis ist durchgaengig Y-up (types.rs/mesh.rs/math.rs: „world.y = Hoehe");vfolgt bewusst dieser etablierten Konvention statt einer wortwoertlichen „world.z"-Lesart, um modulübergreifend konsistent zu bleiben.- Nur vertikale Schnittebenen (Normale ohne Hoehen-Komponente) sind unterstuetzt — Grundriss-/Horizontalschnitte bleiben Sache der bestehenden 2D-Plan-Pipeline.
cut_polygons sind bei diesem Modell immer Rechtecke (siehe oben), aber als
generischer Punktering abgelegt — kompatibel zu render2d::types::FillPolygon
(pts: Vec<Point>), dem vorgesehenen Zielformat fuer die spaetere 1:1-
Uebersetzung in die Plan-/Schnitt-Ansicht.
Bekannte Luecken
- Keine Wandknoten-Verschneidung (T-/X-Stoesse). Wie in
mesh.rs(M1-Stand) werden Waende als eigenstaendige, stumpf abgeschlossene Quader behandelt, die sich an Ecken UEBERLAPPEN statt sich zu vereinen (kein Miter-Join). Der Schnitt-Extraktor erbt das: an einem L-/T-Knoten kann eine Wand als „in die andere eingebettet" verdeckt erscheinen (im Testmodulsection::testsbewusst als reales, erwartetes Verhalten dokumentiert und geprueft — kein Bug dieses Moduls, sondern ein Artefakt der fehlenden Verschneidungslogik weiter oben in der Pipeline). - Keine Oeffnungs-Aussparungen.
WallInput/SlabInputkennen (noch) keine Tueren/Fenster; der Schnitt schneidet daher immer die volle Wandflaeche. Sobald Oeffnungen im Modell ankommen, musswall_prism/die Cut-Polygon- Bildung sie als Aussparungen (Lochpolygone bzw. mehrere Teil-Rechtecke pro Hoehenband) beruecksichtigen. - Keine echte Component-/Material-Id.
WallInput/SlabInputhaben aktuell keine eigene Id;ComponentRefreferenziert daher nur(Art, Index im Eingabe-Array)+ die rohe Albedo-Farbe als Material-Platzhalter. Sobald ein echtes Ressourcen-/Material-System existiert, sollteComponentRefauf eine stabile Id umgestellt werden (Indizes sind nicht stabil ueber Modell-Edits). - Verdeckungstest nutzt Bounding-Boxen, nicht die exakte Fussabdruckform. Fuer Wand-Baender und (i. d. R. konvexe) Deckenumrisse ist das exakt; bei stark konkaven oder diagonalen Grundrissen kann es zu Ueberverdeckung fuehren (ein Prisma blockiert dann auch Bereiche seiner eigenen „Nischen").
- Kein generisches HLR. Der Ansatz funktioniert NUR, weil alle Bauteile Prismen mit konstantem Querschnitt sind. Fuer echte gekrümmte oder nicht- prismatische Geometrie (Bogenwaende, Freiformdaecher, …) waere er nicht anwendbar — dafuer bliebe der OCCT-Weg (oder eine eigene, generischere HLR-Implementierung) die Referenz.
- Keine robuste Sonderfallbehandlung fuer Vertices exakt auf der Schnittlinie (Toleranz-basiert, kein Tie-Breaking/Pertubation) — die Testszenarien vermeiden diesen Fall bewusst.
Vergleich zum OCCT-WASM-Spike
OCCT-WASM (docs/welle-c-hlr-spike) |
Dieser Ansatz (render3d::section) |
|
|---|---|---|
| Verfahren | Generisches HLR (HLRAppli_ReflectLines) |
Analytische Prismen-Projektion |
| Anwendbarkeit | Beliebige BREP-Geometrie | Nur Prismen (konstanter Querschnitt über Höhe) |
| Zusaetzliches Gewicht | ~62,8 MB WASM (~19,6 MB gzip), separater Lazy-Chunk | Keins — reines Rust in render3d, kein weiteres WASM-Asset |
| Modul-Init | ~450 ms (Browser) / ~680 ms (Node) | Kein Initialisierungsschritt (kein Fremd-Modul zu laden) |
| Rechenzeit (L-Wand + Platte) | ~21 ms (reiner HLR-Lauf, gemessen im Browser) | Nicht separat gemessen (kein Millisekunden-Timer im Test); die Operationen sind reine Vektor-/Intervall-Arithmetik über wenige Kanten (O(Anzahl-Prismen × Kanten-pro-Prisma) mit kleinen Konstanten) und liegen der Groessenordnung nach klar unter 1 ms fuer Szenen dieser Groesse — eine belastbare Messung steht noch aus |
| Sichtbarkeit (verdeckte Kanten) | Exakt (echter HLR-Solver) | Naeherung über Bounding-Boxen im Grundriss + Hoehenintervall-Ueberlappung; exakt fuer achsparallele/konvexe Fussabdruecke |
| Reifegrad | Isolierter Spike, nicht verdrahtet | Isolierter Spike (dieses Modul), nicht in render2d/die Plan-Ansicht verdrahtet |
Fazit: Fuer den ueberwiegenden Regelfall dieses Projekts (Waende, Decken —
alles Prismen) ist die analytische Loesung der pragmatischere Weg: kein
zusaetzliches WASM-Gewicht, keine Fremd-Bibliothek, headless testbar wie der
Rest von render3d. Der OCCT-Weg bleibt die Referenz, falls/sobald echte
generische Volumenkoerper (Booleans, gekrümmte Flaechen) ins Modell kommen.