Dach: Grundriss-Masse (Breite/Tiefe) im Panel editierbar

Bisher liess sich der Dach-Grundriss nach dem Platzieren nicht mehr in der
Grösse ändern. RoofSection bekommt Breite/Tiefe-Felder, die das Umriss-
Rechteck neu bilden (untere/linke Ecke bleibt fix). RoofInfo trägt
width/depth/minX/minY. tsc + vitest grün.
This commit is contained in:
2026-07-10 00:37:32 +02:00
parent 64f61797d8
commit 826685ceaf
4 changed files with 40 additions and 0 deletions
+2
View File
@@ -300,6 +300,8 @@ export const de = {
"objinfo.roof.ridgeAxis.y": "entlang Y", "objinfo.roof.ridgeAxis.y": "entlang Y",
"objinfo.roof.pitch": "Neigung (°)", "objinfo.roof.pitch": "Neigung (°)",
"objinfo.roof.pitchUpper": "Obere Neigung (°)", "objinfo.roof.pitchUpper": "Obere Neigung (°)",
"objinfo.roof.width": "Breite (m)",
"objinfo.roof.depth": "Tiefe (m)",
"objinfo.roof.overhang": "Überstand (m)", "objinfo.roof.overhang": "Überstand (m)",
"objinfo.roof.thickness": "Dachdicke (m)", "objinfo.roof.thickness": "Dachdicke (m)",
"objinfo.roof.baseElevation": "Traufhöhe (m)", "objinfo.roof.baseElevation": "Traufhöhe (m)",
+2
View File
@@ -299,6 +299,8 @@ export const en: Record<TranslationKey, string> = {
"objinfo.roof.ridgeAxis.y": "along Y", "objinfo.roof.ridgeAxis.y": "along Y",
"objinfo.roof.pitch": "Pitch (°)", "objinfo.roof.pitch": "Pitch (°)",
"objinfo.roof.pitchUpper": "Upper pitch (°)", "objinfo.roof.pitchUpper": "Upper pitch (°)",
"objinfo.roof.width": "Width (m)",
"objinfo.roof.depth": "Depth (m)",
"objinfo.roof.overhang": "Overhang (m)", "objinfo.roof.overhang": "Overhang (m)",
"objinfo.roof.thickness": "Roof thickness (m)", "objinfo.roof.thickness": "Roof thickness (m)",
"objinfo.roof.baseElevation": "Eaves height (m)", "objinfo.roof.baseElevation": "Eaves height (m)",
+25
View File
@@ -434,6 +434,16 @@ export function ColumnSection({
// ── Treppen-Attribut-Abschnitt ─────────────────────────────────────────────── // ── Treppen-Attribut-Abschnitt ───────────────────────────────────────────────
// Grundform (gerade/L/Wendel), Laufbreite, Stufenanzahl, Steighöhe (+ abgeleitete // Grundform (gerade/L/Wendel), Laufbreite, Stufenanzahl, Steighöhe (+ abgeleitete
// Steigungshöhe/Auftrittstiefe), Laufrichtung; Referenzgeschoss + UK/OK read-only. // Steigungshöhe/Auftrittstiefe), Laufrichtung; Referenzgeschoss + UK/OK read-only.
/** Rechteck-Umriss (CCW) aus unterer/linker Ecke + Breite/Tiefe (für Dach-Resize). */
function rectOutline(x0: number, y0: number, w: number, d: number) {
return [
{ x: x0, y: y0 },
{ x: x0 + w, y: y0 },
{ x: x0 + w, y: y0 + d },
{ x: x0, y: y0 + d },
];
}
/** Dach-Abschnitt: Form, Neigung(en), Überstand, Firstrichtung, Dicke. */ /** Dach-Abschnitt: Form, Neigung(en), Überstand, Firstrichtung, Dicke. */
export function RoofSection({ export function RoofSection({
roof, roof,
@@ -514,6 +524,21 @@ export function RoofSection({
host.onSetRoofPatch({ pitchUpperDeg: Math.max(0, Math.min(85, v)) }), host.onSetRoofPatch({ pitchUpperDeg: Math.max(0, Math.min(85, v)) }),
)} )}
{/* Grundriss-Masse (Breite/Tiefe): das Umriss-Rechteck neu bilden, die
untere/linke Ecke (minX/minY) bleibt fix. */}
{numField("objinfo.roof.width", roof.width, 0.1, (v) => {
const w = Math.max(0.2, v);
host.onSetRoofPatch({
outline: rectOutline(roof.minX, roof.minY, w, roof.depth),
});
})}
{numField("objinfo.roof.depth", roof.depth, 0.1, (v) => {
const d = Math.max(0.2, v);
host.onSetRoofPatch({
outline: rectOutline(roof.minX, roof.minY, roof.width, d),
});
})}
{/* Überstand + Dicke (Meter). */} {/* Überstand + Dicke (Meter). */}
{numField("objinfo.roof.overhang", roof.overhang, 0.05, (v) => {numField("objinfo.roof.overhang", roof.overhang, 0.05, (v) =>
host.onSetRoofPatch({ overhang: Math.max(0, v) }), host.onSetRoofPatch({ overhang: Math.max(0, v) }),
+11
View File
@@ -92,6 +92,13 @@ export interface RoofInfo {
ridgeHeight: number; ridgeHeight: number;
/** Grundfläche des Umriss-Rechtecks (m², ohne Überstand). */ /** Grundfläche des Umriss-Rechtecks (m², ohne Überstand). */
footprintArea: number; footprintArea: number;
/** Breite (X-Ausdehnung) des Umriss-Rechtecks (Meter). */
width: number;
/** Tiefe (Y-Ausdehnung) des Umriss-Rechtecks (Meter). */
depth: number;
/** Untere/linke Ecke der Bounding-Box (fix beim Breite/Tiefe-Resize). */
minX: number;
minY: number;
} }
/** /**
@@ -623,6 +630,10 @@ function roofSelection(project: Project, roof: Roof): Selection {
baseElevation: eavesZ, baseElevation: eavesZ,
ridgeHeight: g.ridgeHeight, ridgeHeight: g.ridgeHeight,
footprintArea, footprintArea,
width: Math.abs(bb.x1 - bb.x0),
depth: Math.abs(bb.y1 - bb.y0),
minX: bb.x0,
minY: bb.y0,
}; };
return { return {
kind: "roof", kind: "roof",