Ansicht: Kämpfer-/Sprossen-Zeilen (mullionRows) im Fenster
Die 2D-Ansicht teilte das Glasfeld nur vertikal (Flügel) und beim Oberlicht, ignorierte aber mullionRows — ein Fenster mit horizontaler Sprossenteilung sah in der Ansicht ungeteilt aus, im 3D dagegen geteilt. Jetzt splittet die Ansicht das Glasfeld je Flügel in mullionRows Zeilen mit Trennlinien, konsistent zum 3D.
This commit is contained in:
@@ -398,6 +398,52 @@ describe("toElevation — Öffnungen: Verdeckung + Reveal-Schatten", () => {
|
|||||||
expect(symCount("drehkipp")).toBe(4); // Dreh (2) + Kipp (2)
|
expect(symCount("drehkipp")).toBe(4); // Dreh (2) + Kipp (2)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Kämpfer-Zeilen (mullionRows): teilen das Glasfeld horizontal (Glas + Trennlinien)", () => {
|
||||||
|
const base = elevationProject({ overhang: false });
|
||||||
|
const mk = (mullionRows: number): Project =>
|
||||||
|
({
|
||||||
|
...base,
|
||||||
|
windowTypes: [
|
||||||
|
{
|
||||||
|
id: "wt",
|
||||||
|
name: "F",
|
||||||
|
kind: "fest",
|
||||||
|
wingCount: 1,
|
||||||
|
glazing: "einfach",
|
||||||
|
frameWidth: 0.06,
|
||||||
|
mullionRows,
|
||||||
|
defaultSillHeight: 0.9,
|
||||||
|
defaultWidth: 1,
|
||||||
|
defaultHeight: 1.2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
openings: [
|
||||||
|
{
|
||||||
|
id: "op",
|
||||||
|
type: "opening",
|
||||||
|
hostWallId: "NEAR",
|
||||||
|
categoryCode: "21",
|
||||||
|
kind: "window",
|
||||||
|
typeId: "wt",
|
||||||
|
position: 1.5,
|
||||||
|
width: 1,
|
||||||
|
height: 1.2,
|
||||||
|
sillHeight: 0.9,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}) as unknown as Project;
|
||||||
|
const glassCount = (rows: number): number => {
|
||||||
|
const p = mk(rows);
|
||||||
|
const plan = generateElevationPlan(p, p.drawingLevels[1])!;
|
||||||
|
// Glasflächen = weiss/blau gefüllte Polygone mit Kontur, keine Öffnung/Rahmen.
|
||||||
|
return plan.primitives.filter(
|
||||||
|
(pr) => pr.kind === "polygon" && pr.fill === "#9fc2d9",
|
||||||
|
).length;
|
||||||
|
};
|
||||||
|
expect(glassCount(1)).toBe(1); // fest, 1 Feld
|
||||||
|
expect(glassCount(3)).toBe(3); // in 3 Zeilen geteilt
|
||||||
|
});
|
||||||
|
|
||||||
it("Reveal-Schatten: shadows=true erzeugt Öffnungs-Schattenbänder, false keine", () => {
|
it("Reveal-Schatten: shadows=true erzeugt Öffnungs-Schattenbänder, false keine", () => {
|
||||||
const project = openingProject();
|
const project = openingProject();
|
||||||
const level = project.drawingLevels[1];
|
const level = project.drawingLevels[1];
|
||||||
|
|||||||
+13
-1
@@ -772,8 +772,20 @@ function collectOpenings(project: Project, frame: ElevationFrame): ProjectedOpen
|
|||||||
const gB = fa1 - gU;
|
const gB = fa1 - gU;
|
||||||
const gz0 = fz + gV;
|
const gz0 = fz + gV;
|
||||||
const gz1 = fieldTop - gV;
|
const gz1 = fieldTop - gV;
|
||||||
|
// Kämpfer-/Sprossen-Zeilen (mullionRows): das Glasfeld wird in `rows`
|
||||||
|
// horizontale Scheiben geteilt (analog zum 3D, s. toWalls3d), mit einer
|
||||||
|
// Trennlinie je Zeilengrenze über die Glasbreite. 1 = ungeteilt (bisher).
|
||||||
|
const rows = Math.max(1, Math.round(wt?.mullionRows ?? 1));
|
||||||
if (gB - gA > 1e-6 && gz1 - gz0 > 1e-6) {
|
if (gB - gA > 1e-6 && gz1 - gz0 > 1e-6) {
|
||||||
pr.glass.push(rect(pr.pts, gA, gB, gz0, gz1));
|
for (let r = 0; r < rows; r++) {
|
||||||
|
const rz0 = gz0 + ((gz1 - gz0) * r) / rows + (r > 0 ? gV / 2 : 0);
|
||||||
|
const rz1 = gz0 + ((gz1 - gz0) * (r + 1)) / rows - (r < rows - 1 ? gV / 2 : 0);
|
||||||
|
if (rz1 - rz0 > 1e-6) pr.glass.push(rect(pr.pts, gA, gB, rz0, rz1));
|
||||||
|
}
|
||||||
|
for (let r = 1; r < rows; r++) {
|
||||||
|
const rz = gz0 + ((gz1 - gz0) * r) / rows;
|
||||||
|
pr.divisions.push([quadAt(pr.pts, gA, rz), quadAt(pr.pts, gB, rz)]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Trennlinie zum nächsten Feld (ausser am Rand).
|
// Trennlinie zum nächsten Feld (ausser am Rand).
|
||||||
if (fa1 < 1 - fa - 1e-6) {
|
if (fa1 < 1 - fa - 1e-6) {
|
||||||
|
|||||||
Reference in New Issue
Block a user