Fenster-Grundriss: Rahmen-/Stulp-Blöcke über volle Rahmentiefe, plus Laibungs-Blöcke an den Enden

Die Stulp-Marken an Flügelstössen waren als kleines, von der Rahmentiefe
unabhängiges Quadrat gezeichnet statt als echter Profilquerschnitt über die
ganze Rahmentiefe (aussen bis innen). Zusätzlich fehlten die entsprechenden
Blendrahmen-Querschnittsblöcke an den beiden Laibungs-Enden komplett — jetzt
zeigt jedes Fenster dort einen Block, unabhängig von der Flügelanzahl.
This commit is contained in:
2026-07-12 18:07:09 +02:00
parent e65a6b7de1
commit 3d66dc8967
2 changed files with 36 additions and 25 deletions
+21 -16
View File
@@ -410,33 +410,38 @@ export function windowSymbol(
const fein = detail === "fein"; const fein = detail === "fein";
const axisWidth = Math.hypot(jambEnd.x - jambStart.x, jambEnd.y - jambStart.y); const axisWidth = Math.hypot(jambEnd.x - jambStart.x, jambEnd.y - jambStart.y);
const axisDir = normalize(sub(jambEnd, jambStart));
const segs = sashSegments(spec.sashes, axisWidth); const segs = sashSegments(spec.sashes, axisWidth);
// Öffenbarer Flügel sitzt `reveal` tiefer im Blendrahmen (nur „fein"). // Öffenbarer Flügel sitzt `reveal` tiefer im Blendrahmen (nur „fein").
const reveal = fein ? Math.min(bandDepth * 0.3, fw * 0.7) : 0; const reveal = fein ? Math.min(bandDepth * 0.3, fw * 0.7) : 0;
// Halbe Kantenlänge eines Stulp-Quadrats (SIA-Marke), an die Rahmenbreite gekoppelt. // Profil-Block über die VOLLE Rahmentiefe (aussen bis innen), Breite `2·halfU`
const markHalf = Math.min(fw * 0.6, bandDepth * 0.4); // entlang der Achse, zentriert bei `uCenter` (Achsabstand ab jambStart) — der
// Rahmenquerschnitt, wie er im Grundriss-Schnitt sichtbar ist (Nutzer:
// „Rahmen aussen als zwei Flächen gleichbreit wie das Fenster [tief]").
const frameBlock = (uCenter: number, halfU: number): Vec2[] => {
const a = along(jambStart, jambEnd, uCenter - halfU);
const b = along(jambStart, jambEnd, uCenter + halfU);
return [
add(a, scale(n, frameOuterN)),
add(b, scale(n, frameOuterN)),
add(b, scale(n, frameInnerN)),
add(a, scale(n, frameInnerN)),
];
};
// Laibungs-Pfosten an beiden Enden (Blendrahmen-Querschnitt an der Wand-
// öffnung) — EIN Block je Seite, unabhängig vom Detailgrad.
meetingMarks.push(frameBlock(fw / 2, fw / 2), frameBlock(axisWidth - fw / 2, fw / 2));
// Flügel-Trennlinien (Mittelpfosten) an den inneren Segmentgrenzen + // Flügel-Trennlinien (Mittelpfosten) an den inneren Segmentgrenzen +
// Stulp-Quadrate: mittel 1, fein 2 (die beiden zusammenstossenden Profile). // Stulp-Block: mittel 1, fein 2 (die beiden zusammenstossenden Profile)
// je über die volle Rahmentiefe.
for (let i = 0; i < segs.length - 1; i++) { for (let i = 0; i < segs.length - 1; i++) {
const uPos = segs[i].to; const uPos = segs[i].to;
const onAxis = along(jambStart, jambEnd, uPos); const onAxis = along(jambStart, jambEnd, uPos);
mullionLines.push([add(onAxis, scale(n, frameOuterN)), add(onAxis, scale(n, frameInnerN))]); mullionLines.push([add(onAxis, scale(n, frameOuterN)), add(onAxis, scale(n, frameInnerN))]);
const center = add(onAxis, scale(n, gMidBase));
const square = (offU: number): Vec2[] => {
const c = add(center, scale(axisDir, offU));
return [
add(add(c, scale(axisDir, -markHalf)), scale(n, -markHalf)),
add(add(c, scale(axisDir, markHalf)), scale(n, -markHalf)),
add(add(c, scale(axisDir, markHalf)), scale(n, markHalf)),
add(add(c, scale(axisDir, -markHalf)), scale(n, markHalf)),
];
};
if (fein) { if (fein) {
meetingMarks.push(square(-markHalf), square(markHalf)); meetingMarks.push(frameBlock(uPos - fw / 2, fw / 2), frameBlock(uPos + fw / 2, fw / 2));
} else { } else {
meetingMarks.push(square(0)); meetingMarks.push(frameBlock(uPos, fw / 2));
} }
} }
+15 -9
View File
@@ -214,31 +214,37 @@ describe("generatePlan — Stulp-/Flügelstoss-Marken (SIA fig. 37/38, window-st
], ],
}; };
it("mittel: EIN Stulp-Quadrat (4 Linien) je Flügel-Junction", () => { // Jeder Block ist ein Rechteck über die VOLLE Rahmentiefe (4 Linien) je EIN
// Block an JEDEM Laibungs-Ende (Blendrahmen-Querschnitt, immer vorhanden)
// plus die Flügelstoss-Blöcke an inneren Junctions (mittel 1, fein 2).
it("mittel: 2 Laibungs-Blöcke (Enden) + EIN Stulp-Block je Flügel-Junction", () => {
const p = project({ ...baseWindow, typeId: "wt1" }, [twoSashType]); const p = project({ ...baseWindow, typeId: "wt1" }, [twoSashType]);
expect(stulpLineCount(p, "mittel")).toBe(4); // 2 Laibungsenden + 1 Junction = 3 Blöcke × 4 Linien.
expect(stulpLineCount(p, "mittel")).toBe(12);
}); });
it("fein: ZWEI Stulp-Quadrate (8 Linien) je Flügel-Junction", () => { it("fein: 2 Laibungs-Blöcke (Enden) + ZWEI Stulp-Blöcke je Flügel-Junction", () => {
const p = project({ ...baseWindow, typeId: "wt1" }, [twoSashType]); const p = project({ ...baseWindow, typeId: "wt1" }, [twoSashType]);
expect(stulpLineCount(p, "fein")).toBe(8); // 2 Laibungsenden + 2 Junction-Blöcke = 4 Blöcke × 4 Linien.
expect(stulpLineCount(p, "fein")).toBe(16);
}); });
it("grob: KEINE Stulp-Marken", () => { it("grob: KEINE Rahmen-Blöcke", () => {
const p = project({ ...baseWindow, typeId: "wt1" }, [twoSashType]); const p = project({ ...baseWindow, typeId: "wt1" }, [twoSashType]);
expect(stulpLineCount(p, "grob")).toBe(0); expect(stulpLineCount(p, "grob")).toBe(0);
}); });
it("Alt-Fall (kein typeId, nur wingCount) erzeugt KEINE Stulp-Marken — keine echte Flügeltabelle", () => { it("Alt-Fall (kein typeId, nur wingCount) erzeugt KEINE Rahmen-Blöcke — keine echte Flügeltabelle", () => {
const p = project({ ...baseWindow, wingCount: 3 }); const p = project({ ...baseWindow, wingCount: 3 });
expect(stulpLineCount(p, "mittel")).toBe(0); expect(stulpLineCount(p, "mittel")).toBe(0);
expect(stulpLineCount(p, "fein")).toBe(0); expect(stulpLineCount(p, "fein")).toBe(0);
}); });
it("einflügliges Fenster (keine Junction) erzeugt KEINE Stulp-Marken", () => { it("einflügliges Fenster (keine Junction) zeigt trotzdem die 2 Laibungs-Blöcke an den Enden", () => {
const p = project({ ...baseWindow, typeId: "wt1" }, [baseWindowType]); const p = project({ ...baseWindow, typeId: "wt1" }, [baseWindowType]);
expect(stulpLineCount(p, "mittel")).toBe(0); expect(stulpLineCount(p, "mittel")).toBe(8);
expect(stulpLineCount(p, "fein")).toBe(0); expect(stulpLineCount(p, "fein")).toBe(8);
}); });
}); });