Dach: getrennter Überstand Traufe/Ortgang (statt ringsum)
Bisher ein einziger overhang ringsum (Designdoc-Prio #2). Neu Roof.overhangGable für den Ortgang (Giebelseite, entlang First); overhang gilt für die Traufe (senkrecht zum First). Fehlt overhangGable, gilt ringsum overhang (rückwärts- kompatibel). Geometrie mappt die Überstände je nach ridgeAxis auf die Outline- Achsen. Panel: zweites Feld 'Überstand Ortgang' (ausser flach/zelt). +3 Tests. 672/672 grün.
This commit is contained in:
@@ -154,4 +154,30 @@ describe("roofGeometry — Überstand", () => {
|
||||
const bb = roofBBox(g.eaves);
|
||||
expect(bb).toEqual({ x0: -0.5, y0: -0.5, x1: 6.5, y1: 4.5 });
|
||||
});
|
||||
|
||||
it("getrennter Traufe/Ortgang-Überstand: First entlang X -> Ortgang weitet X, Traufe Y", () => {
|
||||
// ridgeAxis "x": First entlang X -> Ortgang (Giebel) an den X-Enden,
|
||||
// Traufe an den Y-Seiten. overhang(Traufe)=0.3, overhangGable(Ortgang)=0.8.
|
||||
const g = roofGeometry(
|
||||
roof({ shape: "sattel", ridgeAxis: "x", overhang: 0.3, overhangGable: 0.8 }),
|
||||
E,
|
||||
);
|
||||
const bb = roofBBox(g.eaves);
|
||||
expect(bb).toEqual({ x0: -0.8, y0: -0.3, x1: 6.8, y1: 4.3 });
|
||||
});
|
||||
|
||||
it("getrennter Überstand: First entlang Y -> Ortgang weitet Y, Traufe X", () => {
|
||||
const g = roofGeometry(
|
||||
roof({ shape: "sattel", ridgeAxis: "y", overhang: 0.3, overhangGable: 0.8 }),
|
||||
E,
|
||||
);
|
||||
const bb = roofBBox(g.eaves);
|
||||
expect(bb).toEqual({ x0: -0.3, y0: -0.8, x1: 6.3, y1: 4.8 });
|
||||
});
|
||||
|
||||
it("overhangGable fehlt -> ringsum gleich overhang (rückwärtskompatibel)", () => {
|
||||
const g = roofGeometry(roof({ shape: "sattel", overhang: 0.4 }), E);
|
||||
const bb = roofBBox(g.eaves);
|
||||
expect(bb).toEqual({ x0: -0.4, y0: -0.4, x1: 6.4, y1: 4.4 });
|
||||
});
|
||||
});
|
||||
|
||||
+10
-5
@@ -336,11 +336,16 @@ const swapLine = (l: [Vec2, Vec2]): [Vec2, Vec2] => [swap2(l[0]), swap2(l[1])];
|
||||
*/
|
||||
export function roofGeometry(roof: Roof, eavesZ: number): RoofGeometry {
|
||||
const bb = roofBBox(roof.outline);
|
||||
const o = Math.max(0, roof.overhang);
|
||||
let x0 = bb.x0 - o;
|
||||
let y0 = bb.y0 - o;
|
||||
let x1 = bb.x1 + o;
|
||||
let y1 = bb.y1 + o;
|
||||
const oe = Math.max(0, roof.overhang); // Traufüberstand (senkrecht zum First)
|
||||
const og = Math.max(0, roof.overhangGable ?? roof.overhang); // Ortgang (entlang First)
|
||||
// Der First liegt entlang der `ridgeAxis`-Achse: dort wirkt der Ortgang-, quer
|
||||
// dazu der Traufüberstand. In OUTLINE-Koordinaten je nach Firstrichtung mappen.
|
||||
const ox = roof.ridgeAxis === "x" ? og : oe;
|
||||
const oy = roof.ridgeAxis === "x" ? oe : og;
|
||||
let x0 = bb.x0 - ox;
|
||||
let y0 = bb.y0 - oy;
|
||||
let x1 = bb.x1 + ox;
|
||||
let y1 = bb.y1 + oy;
|
||||
const flip = roof.ridgeAxis === "y";
|
||||
if (flip) {
|
||||
[x0, y0, x1, y1] = [y0, x0, y1, x1];
|
||||
|
||||
Reference in New Issue
Block a user