Fenster: Farbe/Strichstärke je Linien-Kategorie im Attribute-Panel einstellbar
Neue per-Öffnung-Übersteuerung (Opening.frameLine/sashLine/sillLineStyle,
je {color?, weight?}) für Blendrahmen+Stulp-/Laibungsblöcke, Flügelrahmen/
Sprossen und die Auf-/Untersicht-Sims-Andeutung separat. Fehlt eine
Übersteuerung, gilt weiterhin der bisherige Default (Opening.color/Haarlinie).
UI: drei neue Zeilen (Farbfeld + Strichstärke) im Objekt-Info-Panel bei
selektiertem Fenster.
This commit is contained in:
@@ -3364,6 +3364,15 @@ export default function App() {
|
|||||||
onSetOpeningLintelLines: (lintelLines) => {
|
onSetOpeningLintelLines: (lintelLines) => {
|
||||||
if (selection?.kind === "opening") updateOpening(selection.id, { lintelLines });
|
if (selection?.kind === "opening") updateOpening(selection.id, { lintelLines });
|
||||||
},
|
},
|
||||||
|
onSetOpeningFrameLine: (v) => {
|
||||||
|
if (selection?.kind === "opening") updateOpening(selection.id, { frameLine: v });
|
||||||
|
},
|
||||||
|
onSetOpeningSashLine: (v) => {
|
||||||
|
if (selection?.kind === "opening") updateOpening(selection.id, { sashLine: v });
|
||||||
|
},
|
||||||
|
onSetOpeningSillLineStyle: (v) => {
|
||||||
|
if (selection?.kind === "opening") updateOpening(selection.id, { sillLineStyle: v });
|
||||||
|
},
|
||||||
// Typ-Zuweisung (Bibliothek): Tür-/Fenstertyp per typeId; leerer String löst
|
// Typ-Zuweisung (Bibliothek): Tür-/Fenstertyp per typeId; leerer String löst
|
||||||
// die Zuweisung wieder (Inline-Verhalten).
|
// die Zuweisung wieder (Inline-Verhalten).
|
||||||
onSetOpeningType: (typeId) => {
|
onSetOpeningType: (typeId) => {
|
||||||
|
|||||||
@@ -481,6 +481,10 @@ export const de = {
|
|||||||
"objinfo.opening.lintelLines.innen": "Innen",
|
"objinfo.opening.lintelLines.innen": "Innen",
|
||||||
"objinfo.opening.lintelLines.aussen": "Außen",
|
"objinfo.opening.lintelLines.aussen": "Außen",
|
||||||
"objinfo.opening.lintelLines.beide": "Beide",
|
"objinfo.opening.lintelLines.beide": "Beide",
|
||||||
|
"objinfo.opening.frameLine": "Rahmen",
|
||||||
|
"objinfo.opening.sashLine": "Fenster (Flügel/Sprossen)",
|
||||||
|
"objinfo.opening.sillLine": "Sims",
|
||||||
|
"objinfo.lineWeight": "Strichstärke (mm)",
|
||||||
// ── Treppen-Attribute (Object-Info-Panel) ───────────────────────────────
|
// ── Treppen-Attribute (Object-Info-Panel) ───────────────────────────────
|
||||||
"objinfo.stair.section": "Treppe",
|
"objinfo.stair.section": "Treppe",
|
||||||
"objinfo.stair.shape": "Grundform",
|
"objinfo.stair.shape": "Grundform",
|
||||||
|
|||||||
@@ -480,6 +480,10 @@ export const en: Record<TranslationKey, string> = {
|
|||||||
"objinfo.opening.lintelLines.innen": "Inside",
|
"objinfo.opening.lintelLines.innen": "Inside",
|
||||||
"objinfo.opening.lintelLines.aussen": "Outside",
|
"objinfo.opening.lintelLines.aussen": "Outside",
|
||||||
"objinfo.opening.lintelLines.beide": "Both",
|
"objinfo.opening.lintelLines.beide": "Both",
|
||||||
|
"objinfo.opening.frameLine": "Frame",
|
||||||
|
"objinfo.opening.sashLine": "Window (sash/muntins)",
|
||||||
|
"objinfo.opening.sillLine": "Sill",
|
||||||
|
"objinfo.lineWeight": "Line weight (mm)",
|
||||||
"objinfo.stair.section": "Stair",
|
"objinfo.stair.section": "Stair",
|
||||||
"objinfo.stair.shape": "Shape",
|
"objinfo.stair.shape": "Shape",
|
||||||
"objinfo.stair.shape.straight": "Straight",
|
"objinfo.stair.shape.straight": "Straight",
|
||||||
|
|||||||
@@ -1218,6 +1218,31 @@ export interface Opening {
|
|||||||
* Kategorie-Farbe.
|
* Kategorie-Farbe.
|
||||||
*/
|
*/
|
||||||
color?: string;
|
color?: string;
|
||||||
|
/**
|
||||||
|
* Nur Fenster, Grundriss: Übersteuerung von Farbe/Strichstärke des
|
||||||
|
* Blendrahmens + Stulp-/Laibungsblöcke ({@link LineStyleOverride}).
|
||||||
|
* `undefined` ⇒ {@link Opening.color}, sonst Kategorie-Farbe/Haarlinie.
|
||||||
|
*/
|
||||||
|
frameLine?: LineStyleOverride;
|
||||||
|
/**
|
||||||
|
* Nur Fenster, Grundriss: Übersteuerung von Farbe/Strichstärke des
|
||||||
|
* Flügelrahmens/der Sprossen (window-sash/window-mullion).
|
||||||
|
*/
|
||||||
|
sashLine?: LineStyleOverride;
|
||||||
|
/**
|
||||||
|
* Nur Fenster, Grundriss: Übersteuerung von Farbe/Strichstärke der Auf-/
|
||||||
|
* Untersicht-Andeutung ({@link WindowType.sillLine}); nur wirksam, wenn der
|
||||||
|
* Fenstertyp dort eine Sims-Linie aktiviert hat.
|
||||||
|
*/
|
||||||
|
sillLineStyle?: LineStyleOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Optionale Farb-/Strichstärke-Übersteuerung einer Linien-Kategorie im Grundriss. */
|
||||||
|
export interface LineStyleOverride {
|
||||||
|
/** Strichfarbe (Hex); fehlt ⇒ System-Default. */
|
||||||
|
color?: string;
|
||||||
|
/** Strichstärke in mm Papier; fehlt ⇒ System-Default (Haarlinie). */
|
||||||
|
weight?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,6 +15,11 @@
|
|||||||
// Texte über t(...).
|
// Texte über t(...).
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
// Anzeige-Fallbacks für die Öffnungs-Linien-Übersteuerung (LineStyleRow) —
|
||||||
|
// dieselben Werte wie POCHE_STROKE/SYMBOL_HAIRLINE_MM in plan/generatePlan.ts
|
||||||
|
// (reine UI-Default-Anzeige, kein Re-Export nötig).
|
||||||
|
const OPENING_LINE_DEFAULT_COLOR = "#1a1a1a";
|
||||||
|
const OPENING_LINE_DEFAULT_WEIGHT = 0.02;
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
import type { TranslationKey } from "../i18n";
|
import type { TranslationKey } from "../i18n";
|
||||||
import { flattenCategories, formatM } from "../model/types";
|
import { flattenCategories, formatM } from "../model/types";
|
||||||
@@ -30,6 +35,7 @@ import type {
|
|||||||
} from "../model/types";
|
} from "../model/types";
|
||||||
import { SIA_CATEGORIES, siaLabelFull } from "../geometry/roomArea";
|
import { SIA_CATEGORIES, siaLabelFull } from "../geometry/roomArea";
|
||||||
import { Dropdown } from "../ui/Dropdown";
|
import { Dropdown } from "../ui/Dropdown";
|
||||||
|
import { ColorHexField } from "../ui/ColorHexField";
|
||||||
import { usePanelHost } from "./host";
|
import { usePanelHost } from "./host";
|
||||||
import type {
|
import type {
|
||||||
CeilingInfo,
|
CeilingInfo,
|
||||||
@@ -986,6 +992,30 @@ export function OpeningSection({
|
|||||||
min={1}
|
min={1}
|
||||||
onCommit={(v) => host.onSetOpeningWingCount(Math.max(1, Math.min(4, Math.round(v))))}
|
onCommit={(v) => host.onSetOpeningWingCount(Math.max(1, Math.min(4, Math.round(v))))}
|
||||||
/>
|
/>
|
||||||
|
{/* Grundriss-Linien je Kategorie: Rahmen (Blendrahmen+Stulp), Fenster
|
||||||
|
(Flügelrahmen/Sprossen), Sims (Auf-/Untersicht, nur wenn der
|
||||||
|
Fenstertyp sie aktiviert hat — s. WindowType.sillLine). */}
|
||||||
|
<LineStyleRow
|
||||||
|
label={t("objinfo.opening.frameLine")}
|
||||||
|
value={opening.frameLine}
|
||||||
|
fallbackColor={OPENING_LINE_DEFAULT_COLOR}
|
||||||
|
fallbackWeight={OPENING_LINE_DEFAULT_WEIGHT}
|
||||||
|
onChange={host.onSetOpeningFrameLine}
|
||||||
|
/>
|
||||||
|
<LineStyleRow
|
||||||
|
label={t("objinfo.opening.sashLine")}
|
||||||
|
value={opening.sashLine}
|
||||||
|
fallbackColor={OPENING_LINE_DEFAULT_COLOR}
|
||||||
|
fallbackWeight={OPENING_LINE_DEFAULT_WEIGHT}
|
||||||
|
onChange={host.onSetOpeningSashLine}
|
||||||
|
/>
|
||||||
|
<LineStyleRow
|
||||||
|
label={t("objinfo.opening.sillLine")}
|
||||||
|
value={opening.sillLineStyle}
|
||||||
|
fallbackColor={OPENING_LINE_DEFAULT_COLOR}
|
||||||
|
fallbackWeight={OPENING_LINE_DEFAULT_WEIGHT}
|
||||||
|
onChange={host.onSetOpeningSillLineStyle}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -1528,11 +1558,15 @@ function DimensionField({
|
|||||||
value,
|
value,
|
||||||
onCommit,
|
onCommit,
|
||||||
min = 0,
|
min = 0,
|
||||||
|
unit = "m",
|
||||||
|
step = 0.01,
|
||||||
}: {
|
}: {
|
||||||
label: string;
|
label: string;
|
||||||
value: number;
|
value: number;
|
||||||
onCommit: (v: number) => void;
|
onCommit: (v: number) => void;
|
||||||
min?: number;
|
min?: number;
|
||||||
|
unit?: string;
|
||||||
|
step?: number;
|
||||||
}) {
|
}) {
|
||||||
// Entwurf als String, damit Zwischenzustände (leer, „1.") tippbar sind.
|
// Entwurf als String, damit Zwischenzustände (leer, „1.") tippbar sind.
|
||||||
// `null` = kein aktiver Entwurf → zeige den Host-Wert.
|
// `null` = kein aktiver Entwurf → zeige den Host-Wert.
|
||||||
@@ -1553,7 +1587,7 @@ function DimensionField({
|
|||||||
<input
|
<input
|
||||||
className="objinfo-input"
|
className="objinfo-input"
|
||||||
type="number"
|
type="number"
|
||||||
step={0.01}
|
step={step}
|
||||||
min={isFinite(min) ? min : undefined}
|
min={isFinite(min) ? min : undefined}
|
||||||
value={shown}
|
value={shown}
|
||||||
onChange={(e) => setDraft(e.target.value)}
|
onChange={(e) => setDraft(e.target.value)}
|
||||||
@@ -1568,11 +1602,51 @@ function DimensionField({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span className="objinfo-unit">m</span>
|
<span className="objinfo-unit">{unit}</span>
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Farbe + Strichstärke (mm) einer Linien-Kategorie, mit "System"-Fallback-
|
||||||
|
* Anzeige (Override `undefined` ⇒ zeigt `fallbackColor`/`fallbackWeight`,
|
||||||
|
* Ändern setzt sofort einen expliziten Override). */
|
||||||
|
function LineStyleRow({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
fallbackColor,
|
||||||
|
fallbackWeight,
|
||||||
|
onChange,
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
value: { color?: string; weight?: number } | undefined;
|
||||||
|
fallbackColor: string;
|
||||||
|
fallbackWeight: number;
|
||||||
|
onChange: (v: { color?: string; weight?: number } | undefined) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="objinfo-field">
|
||||||
|
<span className="objinfo-flabel">{label}</span>
|
||||||
|
<ColorHexField
|
||||||
|
value={value?.color ?? fallbackColor}
|
||||||
|
onChange={(color) => onChange({ ...value, color })}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
className="objinfo-input objinfo-input-narrow"
|
||||||
|
type="number"
|
||||||
|
step={0.01}
|
||||||
|
min={0}
|
||||||
|
value={(value?.weight ?? fallbackWeight).toFixed(2)}
|
||||||
|
onChange={(e) => {
|
||||||
|
const w = Number(e.target.value);
|
||||||
|
if (isFinite(w) && w >= 0) onChange({ ...value, weight: w });
|
||||||
|
}}
|
||||||
|
title={t("objinfo.lineWeight")}
|
||||||
|
/>
|
||||||
|
<span className="objinfo-unit">mm</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Dreh-Feld (Delta-Winkel in Grad) ─────────────────────────────────────────
|
// ── Dreh-Feld (Delta-Winkel in Grad) ─────────────────────────────────────────
|
||||||
// Anders als DimensionField zeigt dieses Feld KEINEN persistenten Host-Wert —
|
// Anders als DimensionField zeigt dieses Feld KEINEN persistenten Host-Wert —
|
||||||
// eine „aktuelle Rotation" gibt es für die Selektion generell nicht (Wand ist
|
// eine „aktuelle Rotation" gibt es für die Selektion generell nicht (Wand ist
|
||||||
|
|||||||
@@ -311,6 +311,12 @@ export interface PanelHostValue {
|
|||||||
onSetOpeningDoorType: (doorType: "normal" | "wandoeffnung") => void;
|
onSetOpeningDoorType: (doorType: "normal" | "wandoeffnung") => void;
|
||||||
/** Setzt die Sturzlinien-Darstellung der Tür. */
|
/** Setzt die Sturzlinien-Darstellung der Tür. */
|
||||||
onSetOpeningLintelLines: (lintelLines: "keine" | "innen" | "aussen" | "beide") => void;
|
onSetOpeningLintelLines: (lintelLines: "keine" | "innen" | "aussen" | "beide") => void;
|
||||||
|
/** Übersteuert Farbe/Strichstärke des Blendrahmens + Stulp-/Laibungsblöcke. */
|
||||||
|
onSetOpeningFrameLine: (v: { color?: string; weight?: number } | undefined) => void;
|
||||||
|
/** Übersteuert Farbe/Strichstärke von Flügelrahmen/Sprossen. */
|
||||||
|
onSetOpeningSashLine: (v: { color?: string; weight?: number } | undefined) => void;
|
||||||
|
/** Übersteuert Farbe/Strichstärke der Auf-/Untersicht-Andeutung (Sims). */
|
||||||
|
onSetOpeningSillLineStyle: (v: { color?: string; weight?: number } | undefined) => void;
|
||||||
/** Weist der Öffnung einen Tür-/Fenstertyp (Bibliothek) zu; "" löst die Zuweisung. */
|
/** Weist der Öffnung einen Tür-/Fenstertyp (Bibliothek) zu; "" löst die Zuweisung. */
|
||||||
onSetOpeningType: (typeId: string) => void;
|
onSetOpeningType: (typeId: string) => void;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2270,36 +2270,47 @@ function addOpeningSymbol(
|
|||||||
out.push({ kind: "line", a: g[0], b: g[1], cls: "window-glass", weightMm: SYMBOL_HAIRLINE_MM, greyed, openingId: o.id });
|
out.push({ kind: "line", a: g[0], b: g[1], cls: "window-glass", weightMm: SYMBOL_HAIRLINE_MM, greyed, openingId: o.id });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Linien-Kategorien einzeln übersteuerbar (Nutzer-Wunsch): Rahmen (Blend-
|
||||||
|
// rahmen-Kontur + Stulp-/Laibungsblöcke), Fenster (Flügelrahmen/Sprossen),
|
||||||
|
// Sims (Auf-/Untersicht-Andeutung, s. u.). `undefined` ⇒ bisheriges
|
||||||
|
// Verhalten (strokeColor/SYMBOL_HAIRLINE_MM).
|
||||||
|
const frameColor = o.frameLine?.color ?? strokeColor;
|
||||||
|
const frameWeight = o.frameLine?.weight ?? lwMm;
|
||||||
|
const frameHairline = o.frameLine?.weight ?? SYMBOL_HAIRLINE_MM;
|
||||||
|
const sashColor = o.sashLine?.color ?? strokeColor;
|
||||||
|
const sashWeight = o.sashLine?.weight ?? SYMBOL_HAIRLINE_MM;
|
||||||
|
|
||||||
// Blendrahmen-Rechteck (mittel + fein).
|
// Blendrahmen-Rechteck (mittel + fein).
|
||||||
out.push({
|
out.push({
|
||||||
kind: "polygon",
|
kind: "polygon",
|
||||||
pts: sym.frame,
|
pts: sym.frame,
|
||||||
fill: "none",
|
fill: "none",
|
||||||
stroke: strokeColor,
|
stroke: frameColor,
|
||||||
strokeWidthMm: lwMm,
|
strokeWidthMm: frameWeight,
|
||||||
hatch: NO_HATCH,
|
hatch: NO_HATCH,
|
||||||
greyed,
|
greyed,
|
||||||
openingId: o.id,
|
openingId: o.id,
|
||||||
});
|
});
|
||||||
// Pfosten-/Flügel-Trennlinien.
|
// Pfosten-/Flügel-Trennlinien (Alt-Pfad ohne Typ — zählt als "Fenster").
|
||||||
for (const [a, b] of sym.mullionLines) {
|
for (const [a, b] of sym.mullionLines) {
|
||||||
out.push({ kind: "line", a, b, cls: "window-mullion", weightMm: SYMBOL_HAIRLINE_MM, color: strokeColor, greyed, openingId: o.id });
|
out.push({ kind: "line", a, b, cls: "window-mullion", weightMm: sashWeight, color: sashColor, greyed, openingId: o.id });
|
||||||
}
|
}
|
||||||
// fein: Flügelrahmen (Flügelkontur) je öffenbarem Flügel — Schachtelung
|
// fein: Flügelrahmen (Flügelkontur) je öffenbarem Flügel — Schachtelung
|
||||||
// Blendrahmen → Flügelrahmen → Glas (Feindetail, hebt fein klar von mittel ab).
|
// Blendrahmen → Flügelrahmen → Glas (Feindetail, hebt fein klar von mittel ab).
|
||||||
if (detail === "fein") {
|
if (detail === "fein") {
|
||||||
for (const pts of sym.sashFrames) {
|
for (const pts of sym.sashFrames) {
|
||||||
for (let i = 0; i < pts.length; i++) {
|
for (let i = 0; i < pts.length; i++) {
|
||||||
out.push({ kind: "line", a: pts[i], b: pts[(i + 1) % pts.length], cls: "window-sash", weightMm: SYMBOL_HAIRLINE_MM, color: strokeColor, greyed, openingId: o.id });
|
out.push({ kind: "line", a: pts[i], b: pts[(i + 1) % pts.length], cls: "window-sash", weightMm: sashWeight, color: sashColor, greyed, openingId: o.id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Stulp-Mittelquadrat je Flügel-Junction (SIA-Signatur): mittel = EIN Quadrat,
|
// Stulp-Mittelquadrat je Flügel-Junction (SIA-Signatur): mittel = EIN Quadrat,
|
||||||
// fein = ZWEI anliegende Rechtecke (die beiden Stulp-Stäbe der Flügel) —
|
// fein = ZWEI anliegende Rechtecke (die beiden Stulp-Stäbe der Flügel) —
|
||||||
// bereits tiefenkorrekt (inset-/insetFace-bewusst) in windowSymbol berechnet.
|
// bereits tiefenkorrekt (inset-/insetFace-bewusst) in windowSymbol berechnet.
|
||||||
|
// Zählt als "Rahmen" (Laibungs-/Stossblock des Blendrahmens).
|
||||||
for (const mark of sym.meetingMarks) {
|
for (const mark of sym.meetingMarks) {
|
||||||
for (let i = 0; i < mark.length; i++) {
|
for (let i = 0; i < mark.length; i++) {
|
||||||
out.push({ kind: "line", a: mark[i], b: mark[(i + 1) % mark.length], cls: "window-stulp", weightMm: SYMBOL_HAIRLINE_MM, color: strokeColor, greyed, openingId: o.id });
|
out.push({ kind: "line", a: mark[i], b: mark[(i + 1) % mark.length], cls: "window-stulp", weightMm: frameHairline, color: frameColor, greyed, openingId: o.id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Glaslinien (Anzahl je Detailgrad/Verglasung, s. glassCount).
|
// Glaslinien (Anzahl je Detailgrad/Verglasung, s. glassCount).
|
||||||
@@ -2347,11 +2358,13 @@ function addOpeningSymbol(
|
|||||||
if (detail !== "grob" && wt?.sillLine) {
|
if (detail !== "grob" && wt?.sillLine) {
|
||||||
const { faces, view } = wt.sillLine;
|
const { faces, view } = wt.sillLine;
|
||||||
const dash = view === "unter" ? OVERHEAD_DASH : [0.04, 0.08];
|
const dash = view === "unter" ? OVERHEAD_DASH : [0.04, 0.08];
|
||||||
|
const sillColor = o.sillLineStyle?.color ?? strokeColor;
|
||||||
|
const sillWeight = o.sillLineStyle?.weight ?? SYMBOL_HAIRLINE_MM;
|
||||||
if (faces === "aussen" || faces === "beide") {
|
if (faces === "aussen" || faces === "beide") {
|
||||||
out.push({ kind: "line", a: sym.frame[0], b: sym.frame[1], cls: "window-sill", weightMm: SYMBOL_HAIRLINE_MM, dash, color: strokeColor, greyed, openingId: o.id });
|
out.push({ kind: "line", a: sym.frame[0], b: sym.frame[1], cls: "window-sill", weightMm: sillWeight, dash, color: sillColor, greyed, openingId: o.id });
|
||||||
}
|
}
|
||||||
if (faces === "innen" || faces === "beide") {
|
if (faces === "innen" || faces === "beide") {
|
||||||
out.push({ kind: "line", a: sym.frame[3], b: sym.frame[2], cls: "window-sill", weightMm: SYMBOL_HAIRLINE_MM, dash, color: strokeColor, greyed, openingId: o.id });
|
out.push({ kind: "line", a: sym.frame[3], b: sym.frame[2], cls: "window-sill", weightMm: sillWeight, dash, color: sillColor, greyed, openingId: o.id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Rollladen-/Sonnenschutzkasten (P0-Minimalfassung, reine 2D-Kontur): ein
|
// Rollladen-/Sonnenschutzkasten (P0-Minimalfassung, reine 2D-Kontur): ein
|
||||||
|
|||||||
@@ -324,6 +324,61 @@ describe("generatePlan — Auf-/Untersicht-Andeutung (WindowType.sillLine)", ()
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("generatePlan — Linien-Übersteuerung je Kategorie (Opening.frameLine/sashLine/sillLineStyle)", () => {
|
||||||
|
const twoSashType: WindowType = {
|
||||||
|
...baseWindowType,
|
||||||
|
sashes: [
|
||||||
|
{ kind: "fluegel", autoWidth: true, opening: "dreh", hingeSide: "left" },
|
||||||
|
{ kind: "fluegel", autoWidth: true, opening: "dreh", hingeSide: "right" },
|
||||||
|
],
|
||||||
|
sillLine: { faces: "aussen", view: "auf" },
|
||||||
|
};
|
||||||
|
|
||||||
|
it("ohne Übersteuerung: Stulp-/Sash-/Sims-Linien nutzen den Default (Opening.color bzw. Haarlinie)", () => {
|
||||||
|
const p = project({ ...baseWindow, typeId: "wt1" }, [twoSashType]);
|
||||||
|
const stulp = linesOfClass(p, "window-stulp", "mittel");
|
||||||
|
expect(stulp.length).toBeGreaterThan(0);
|
||||||
|
for (const l of stulp) expect(l.kind === "line" && l.weightMm).toBeCloseTo(0.02, 6);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("frameLine übersteuert Farbe+Stärke der Stulp-/Laibungsblöcke (window-stulp)", () => {
|
||||||
|
const p = project(
|
||||||
|
{ ...baseWindow, typeId: "wt1", frameLine: { color: "#ff0000", weight: 0.5 } },
|
||||||
|
[twoSashType],
|
||||||
|
);
|
||||||
|
const stulp = linesOfClass(p, "window-stulp", "mittel");
|
||||||
|
expect(stulp.length).toBeGreaterThan(0);
|
||||||
|
for (const l of stulp) {
|
||||||
|
expect(l.kind === "line" && l.color).toBe("#ff0000");
|
||||||
|
expect(l.kind === "line" && l.weightMm).toBeCloseTo(0.5, 6);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sashLine übersteuert Farbe+Stärke des Flügelrahmens (window-sash, fein)", () => {
|
||||||
|
const p = project(
|
||||||
|
{ ...baseWindow, typeId: "wt1", sashLine: { color: "#00ff00", weight: 0.3 } },
|
||||||
|
[twoSashType],
|
||||||
|
);
|
||||||
|
const sash = linesOfClass(p, "window-sash", "fein");
|
||||||
|
expect(sash.length).toBeGreaterThan(0);
|
||||||
|
for (const l of sash) {
|
||||||
|
expect(l.kind === "line" && l.color).toBe("#00ff00");
|
||||||
|
expect(l.kind === "line" && l.weightMm).toBeCloseTo(0.3, 6);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sillLineStyle übersteuert Farbe+Stärke der Auf-/Untersicht-Linie (window-sill)", () => {
|
||||||
|
const p = project(
|
||||||
|
{ ...baseWindow, typeId: "wt1", sillLineStyle: { color: "#0000ff", weight: 0.4 } },
|
||||||
|
[twoSashType],
|
||||||
|
);
|
||||||
|
const sill = linesOfClass(p, "window-sill", "mittel");
|
||||||
|
expect(sill.length).toBe(1);
|
||||||
|
expect(sill[0].kind === "line" && sill[0].color).toBe("#0000ff");
|
||||||
|
expect(sill[0].kind === "line" && sill[0].weightMm).toBeCloseTo(0.4, 6);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("generatePlan — Rollladenkasten shading (Item 3)", () => {
|
describe("generatePlan — Rollladenkasten shading (Item 3)", () => {
|
||||||
const shadingLineCount = (p: Project) => linesOfClass(p, "window-shading").length;
|
const shadingLineCount = (p: Project) => linesOfClass(p, "window-shading").length;
|
||||||
|
|
||||||
|
|||||||
@@ -233,6 +233,10 @@ export interface OpeningInfo {
|
|||||||
/** Aufgelöste absolute UK/OK (Meter). */
|
/** Aufgelöste absolute UK/OK (Meter). */
|
||||||
zBottom: number;
|
zBottom: number;
|
||||||
zTop: number;
|
zTop: number;
|
||||||
|
/** Nur Fenster: Grundriss-Linien-Übersteuerungen je Kategorie. */
|
||||||
|
frameLine?: { color?: string; weight?: number };
|
||||||
|
sashLine?: { color?: string; weight?: number };
|
||||||
|
sillLineStyle?: { color?: string; weight?: number };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -723,6 +727,9 @@ function openingSelection(project: Project, o: Opening): Selection {
|
|||||||
typeId: o.typeId,
|
typeId: o.typeId,
|
||||||
zBottom: ext.zBottom,
|
zBottom: ext.zBottom,
|
||||||
zTop: ext.zTop,
|
zTop: ext.zTop,
|
||||||
|
frameLine: o.frameLine,
|
||||||
|
sashLine: o.sashLine,
|
||||||
|
sillLineStyle: o.sillLineStyle,
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
kind: "opening",
|
kind: "opening",
|
||||||
|
|||||||
@@ -4267,6 +4267,11 @@ body {
|
|||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
.objinfo-input-narrow {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 48px;
|
||||||
|
min-width: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Element-Abschnitte IM Attribute-Panel dem .attr-Grid-Look angleichen ──────
|
/* ── Element-Abschnitte IM Attribute-Panel dem .attr-Grid-Look angleichen ──────
|
||||||
Die aus ObjectInfo verschobenen Sektionen (Wand/Decke/Öffnung/Treppe/Raum)
|
Die aus ObjectInfo verschobenen Sektionen (Wand/Decke/Öffnung/Treppe/Raum)
|
||||||
|
|||||||
Reference in New Issue
Block a user