Fenster: echte Schachtelung Blendrahmen → Flügelrahmen → Glas (2D+3D)

Öffenbare vs. feste Flügel sind jetzt unterscheidbar, und die Einbaulage
(Schichteinzug) wirkt auch im 2D-Grundriss.

2D (windowSymbol/generatePlan):
- Der reiche Pfad (typisiertes Fenster) zeichnet den Blendrahmen an der REALEN
  Einbaulage (insetFace/insetFromFace, vorher ignoriert), je Flügel einen
  Flügelrahmen (window-sash) nur wenn ÖFFENBAR, und das Glas darin. Feste
  Flügel: Glas direkt im Blendrahmen.
- Die alte Diagonale quer über die Box (sah aus wie durchgestrichen) entfernt —
  Öffenbarkeit wird jetzt über den Flügelrahmen ausgedrückt.
- Alt-Pfad (kein Typ) byte-identisch → kernel2d-Parität unberührt.

3D (frameMeshesForOpening/resolveOpeningFrame):
- Je öffenbarem Flügel ein Flügelrahmen-Ring (4 Riegel) im Blendrahmen (fein).
- Flügeltabelle konsistent aus explizitem sashes bzw. effektivem wingCount
  (Instanz-Override wirkt jetzt auch auf Flügelrahmen); wingCount daraus abgeleitet.

Tests angepasst/ergänzt (fest vs. öffenbar, Zählungen). 663/663 grün.
This commit is contained in:
2026-07-10 01:47:27 +02:00
parent d131683304
commit 9a38636bf2
5 changed files with 332 additions and 77 deletions
+15 -4
View File
@@ -142,7 +142,10 @@ describe("generatePlan — Flügeleinteilung aus sashes (Item 1)", () => {
a.forEach((v, i) => expect(v).toBeCloseTo(b[i], 9));
});
it("Flügel mit opening !== 'fest' erzeugt eine Öffnungsandeutung (window-opening); 'fest' keine", () => {
it("öffenbarer Flügel bekommt einen Flügelrahmen (window-sash, 4 Kanten); 'fest' keinen", () => {
// Ein öffenbarer + ein fester Flügel: genau EIN Flügelrahmen-Rechteck = 4
// Kanten-Linien (der feste Flügel bekommt keinen; Glas sitzt direkt im
// Blendrahmen). So liest man fest vs. öffenbar direkt im Grundriss.
const wt: WindowType = {
...baseWindowType,
sashes: [
@@ -151,12 +154,20 @@ describe("generatePlan — Flügeleinteilung aus sashes (Item 1)", () => {
],
};
const p = project({ ...baseWindow, typeId: "wt1" }, [wt]);
expect(linesOfClass(p, "window-opening").length).toBe(1);
expect(linesOfClass(p, "window-sash").length).toBe(4);
// Nur feste Flügel -> gar kein Flügelrahmen.
const wtFixed: WindowType = {
...baseWindowType,
sashes: [{ kind: "fluegel", autoWidth: true, opening: "fest" }],
};
const pFixed = project({ ...baseWindow, typeId: "wt1" }, [wtFixed]);
expect(linesOfClass(pFixed, "window-sash").length).toBe(0);
});
it("Alt-Fall (kein typeId) erzeugt KEINE Öffnungsandeutung", () => {
it("Alt-Fall (kein typeId) erzeugt KEINEN Flügelrahmen", () => {
const p = project({ ...baseWindow });
expect(linesOfClass(p, "window-opening").length).toBe(0);
expect(linesOfClass(p, "window-sash").length).toBe(0);
});
});