Fenster-Grundriss: keine separate Trennlinie mehr neben dem Rahmenblock am Flügelstoss
Der Rahmenblock (voller Profilquerschnitt) und eine dünne window-mullion- Linie lagen an derselben Stelle übereinander — überflüssig, der Block markiert den Stoss bereits vollständig. Nur noch für Alt-Fenster ohne Typ (kein Block verfügbar) bleibt die Linie bestehen.
This commit is contained in:
@@ -433,11 +433,11 @@ export function windowSymbol(
|
|||||||
|
|
||||||
// Flügel-Trennlinien (Mittelpfosten) an den inneren Segmentgrenzen +
|
// Flügel-Trennlinien (Mittelpfosten) an den inneren Segmentgrenzen +
|
||||||
// Stulp-Block: mittel 1, fein 2 (die beiden zusammenstossenden Profile) —
|
// Stulp-Block: mittel 1, fein 2 (die beiden zusammenstossenden Profile) —
|
||||||
// je über die volle Rahmentiefe.
|
// je über die volle Rahmentiefe. KEINE zusätzliche dünne Trennlinie mehr
|
||||||
|
// daneben (Nutzer-Feedback: „keine vertikale Trennlinie, sondern ein
|
||||||
|
// Rechteck") — der Block selbst markiert den Stoss.
|
||||||
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);
|
|
||||||
mullionLines.push([add(onAxis, scale(n, frameOuterN)), add(onAxis, scale(n, frameInnerN))]);
|
|
||||||
if (fein) {
|
if (fein) {
|
||||||
meetingMarks.push(frameBlock(uPos - fw / 2, fw / 2), frameBlock(uPos + fw / 2, fw / 2));
|
meetingMarks.push(frameBlock(uPos - fw / 2, fw / 2), frameBlock(uPos + fw / 2, fw / 2));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -98,15 +98,30 @@ function linesOfClass(p: Project, cls: string, detail: "grob" | "mittel" | "fein
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Mittelpunkt (x) jedes Rahmenblocks (4 Linien = ein Rechteck, s. windowSymbol
|
||||||
|
* meetingMarks) unter den `window-stulp`-Primitiven, sortiert. */
|
||||||
|
function stulpBlockCenters(p: Project, detail: "grob" | "mittel" | "fein" = "mittel"): number[] {
|
||||||
|
const lines = linesOfClass(p, "window-stulp", detail);
|
||||||
|
const centers: number[] = [];
|
||||||
|
for (let i = 0; i < lines.length; i += 4) {
|
||||||
|
const group = lines.slice(i, i + 4);
|
||||||
|
const xs = group.flatMap((pr) => (pr.kind === "line" ? [pr.a.x, pr.b.x] : []));
|
||||||
|
centers.push((Math.min(...xs) + Math.max(...xs)) / 2);
|
||||||
|
}
|
||||||
|
return centers.sort((a, b) => a - b);
|
||||||
|
}
|
||||||
|
|
||||||
describe("generatePlan — Flügeleinteilung aus sashes (Item 1)", () => {
|
describe("generatePlan — Flügeleinteilung aus sashes (Item 1)", () => {
|
||||||
it("Alt-Fall (kein typeId/sashes, nur wingCount=3) erzeugt genau 2 Pfostenlinien — Regression", () => {
|
it("Alt-Fall (kein typeId/sashes, nur wingCount=3) erzeugt genau 2 Pfostenlinien — Regression", () => {
|
||||||
const p = project({ ...baseWindow, wingCount: 3 });
|
const p = project({ ...baseWindow, wingCount: 3 });
|
||||||
expect(linesOfClass(p, "window-mullion").length).toBe(2);
|
expect(linesOfClass(p, "window-mullion").length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("WindowType MIT sashes (3 feste Flügelbreiten 0.4 m) erzeugt Pfostenlinien exakt an den Flügelgrenzen", () => {
|
it("WindowType MIT sashes (3 feste Flügelbreiten 0.4 m) erzeugt Rahmenblöcke (keine Linie mehr) exakt an den Flügelgrenzen", () => {
|
||||||
// Öffnung 1.2 m breit, jambStart bei x=1.0 (position 1.0) -> jambEnd x=2.2.
|
// Öffnung 1.2 m breit, jambStart bei x=1.0 (position 1.0) -> jambEnd x=2.2.
|
||||||
// 3 Flügel à 0.4 m (autoWidth:false) -> Grenzen bei x=1.4 und x=1.8.
|
// 3 Flügel à 0.4 m (autoWidth:false) -> Stoss-Blöcke bei x=1.4 und x=1.8.
|
||||||
|
// KEINE separate window-mullion-Linie mehr (Nutzer-Feedback: nur der Block
|
||||||
|
// markiert den Stoss, keine zusätzliche dünne Trennlinie daneben).
|
||||||
const wt: WindowType = {
|
const wt: WindowType = {
|
||||||
...baseWindowType,
|
...baseWindowType,
|
||||||
sashes: [
|
sashes: [
|
||||||
@@ -116,28 +131,26 @@ describe("generatePlan — Flügeleinteilung aus sashes (Item 1)", () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
const p = project({ ...baseWindow, typeId: "wt1" }, [wt]);
|
const p = project({ ...baseWindow, typeId: "wt1" }, [wt]);
|
||||||
const mullions = linesOfClass(p, "window-mullion");
|
expect(linesOfClass(p, "window-mullion").length).toBe(0);
|
||||||
expect(mullions.length).toBe(2);
|
// 2 Laibungs-Blöcke (Enden, nahe x=1.0/2.2) + 2 Flügelstoss-Blöcke (1.4/1.8).
|
||||||
const xs = mullions
|
const junctionCenters = stulpBlockCenters(p, "mittel").filter((x) => x > 1.2 && x < 2.0);
|
||||||
.map((pr) => (pr.kind === "line" ? pr.a.x : NaN))
|
expect(junctionCenters.length).toBe(2);
|
||||||
.sort((a, b) => a - b);
|
expect(junctionCenters[0]).toBeCloseTo(1.4, 6);
|
||||||
expect(xs[0]).toBeCloseTo(1.4, 6);
|
expect(junctionCenters[1]).toBeCloseTo(1.8, 6);
|
||||||
expect(xs[1]).toBeCloseTo(1.8, 6);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("WindowType MIT sashes, aber alle autoWidth (kein fixes width/pfosten) -> identische Grenzen wie die alte wingCount-Gleichverteilung", () => {
|
it("WindowType MIT sashes, aber alle autoWidth (kein fixes width/pfosten) -> Rahmenblöcke an denselben Positionen wie die alte wingCount-Gleichverteilung", () => {
|
||||||
// 3 gleichmässige Flügel über sashesOfWindowType (kein `sashes` am Typ,
|
// 3 gleichmässige Flügel über sashesOfWindowType (kein `sashes` am Typ,
|
||||||
// nur `wingCount: 3`) müssen exakt dieselben Pfosten liefern wie der
|
// nur `wingCount: 3`) müssen an denselben Achspositionen einen Stoss haben
|
||||||
// Alt-Fall ohne Typ (Regressionssicherheit der Ableitung).
|
// wie der Alt-Fall ohne Typ (Regressionssicherheit der Ableitung) — der
|
||||||
|
// Alt-Fall zeigt sie weiterhin als Linie, der typisierte Pfad als Block.
|
||||||
const wt: WindowType = { ...baseWindowType, wingCount: 3 };
|
const wt: WindowType = { ...baseWindowType, wingCount: 3 };
|
||||||
const withType = project({ ...baseWindow, typeId: "wt1" }, [wt]);
|
const withType = project({ ...baseWindow, typeId: "wt1" }, [wt]);
|
||||||
const withoutType = project({ ...baseWindow, wingCount: 3 });
|
const withoutType = project({ ...baseWindow, wingCount: 3 });
|
||||||
const linesOf = (p: Project) =>
|
const a = stulpBlockCenters(withType, "mittel").filter((x) => x > 1.2 && x < 2.0);
|
||||||
linesOfClass(p, "window-mullion")
|
const b = linesOfClass(withoutType, "window-mullion")
|
||||||
.map((pr) => (pr.kind === "line" ? pr.a.x : NaN))
|
.map((pr) => (pr.kind === "line" ? pr.a.x : NaN))
|
||||||
.sort((a, b) => a - b);
|
.sort((x, y) => x - y);
|
||||||
const a = linesOf(withType);
|
|
||||||
const b = linesOf(withoutType);
|
|
||||||
expect(a.length).toBe(b.length);
|
expect(a.length).toBe(b.length);
|
||||||
a.forEach((v, i) => expect(v).toBeCloseTo(b[i], 9));
|
a.forEach((v, i) => expect(v).toBeCloseTo(b[i], 9));
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user