Schnitt/Ansicht Phase 2: Decken-Überkopf-Umriss als gestrichelte Haarlinie (über Schnittebene), mit Test
This commit is contained in:
+11
-10
@@ -98,6 +98,10 @@ const MONO_INK = "#111111";
|
|||||||
const LAYER_LINE_MM = 0.02;
|
const LAYER_LINE_MM = 0.02;
|
||||||
/** Haarlinie für Tür-/Fenstersymbole (Flügel, Bogen, Rahmen, Glas) in mm. */
|
/** Haarlinie für Tür-/Fenstersymbole (Flügel, Bogen, Rahmen, Glas) in mm. */
|
||||||
const SYMBOL_HAIRLINE_MM = 0.02;
|
const SYMBOL_HAIRLINE_MM = 0.02;
|
||||||
|
/** Strichmuster (mm Papier) für ÜBERKOPF-Ansichtslinien: Bauteile über der
|
||||||
|
* Grundriss-Schnittebene (Decken-/Slab-Überstände, Unterzüge) werden nach
|
||||||
|
* BIM-Konvention gestrichelt gezeichnet (Aufsicht auf ein Bauteil über einem). */
|
||||||
|
const OVERHEAD_DASH: number[] = [0.4, 0.25];
|
||||||
/** Stärke der Wand-Umrisslinie je Detailgrad, als Faktor auf die Ebenen-lw. */
|
/** Stärke der Wand-Umrisslinie je Detailgrad, als Faktor auf die Ebenen-lw. */
|
||||||
const OUTLINE_DETAIL_FACTOR: Record<DetailLevel, number> = {
|
const OUTLINE_DETAIL_FACTOR: Record<DetailLevel, number> = {
|
||||||
grob: 1.6, // dickere Sammellinie
|
grob: 1.6, // dickere Sammellinie
|
||||||
@@ -638,13 +642,9 @@ export function generatePlan(
|
|||||||
for (const ceiling of ceilings) {
|
for (const ceiling of ceilings) {
|
||||||
const greyed = categoryDisplay(ceiling.categoryCode).greyed;
|
const greyed = categoryDisplay(ceiling.categoryCode).greyed;
|
||||||
const category = catByCode.get(ceiling.categoryCode);
|
const category = catByCode.get(ceiling.categoryCode);
|
||||||
const lwMm = resolveStrokeWeight(
|
// Kein lwMm mehr: der Decken-Umriss ist eine feste Überkopf-Haarlinie
|
||||||
ceiling.strokeWeight,
|
// (gestrichelt), unabhängig von der Kategorie-Strichstärke.
|
||||||
ceiling.strokeWeightSource,
|
addCeilingPoche(primitives, project, ceiling, greyed, detail, category, wallFootprints);
|
||||||
category,
|
|
||||||
lwByCode.get(ceiling.categoryCode) ?? WALL_FALLBACK_MM,
|
|
||||||
);
|
|
||||||
addCeilingPoche(primitives, project, ceiling, greyed, detail, lwMm, category, wallFootprints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Räume (SIA-416-Flächen) dieses Geschosses: transluzente Farbfüllung + Stempel
|
// Räume (SIA-416-Flächen) dieses Geschosses: transluzente Farbfüllung + Stempel
|
||||||
@@ -1904,7 +1904,6 @@ function addCeilingPoche(
|
|||||||
ceiling: Ceiling,
|
ceiling: Ceiling,
|
||||||
greyed: boolean,
|
greyed: boolean,
|
||||||
detail: DetailLevel,
|
detail: DetailLevel,
|
||||||
lwMm: number,
|
|
||||||
category: LayerCategory | undefined,
|
category: LayerCategory | undefined,
|
||||||
wallFootprints: WallFootprint[],
|
wallFootprints: WallFootprint[],
|
||||||
): void {
|
): void {
|
||||||
@@ -1913,7 +1912,6 @@ function addCeilingPoche(
|
|||||||
const wt = getCeilingType(project, ceiling);
|
const wt = getCeilingType(project, ceiling);
|
||||||
const comp = wt.layers.length > 0 ? getComponent(project, wt.layers[0].componentId) : null;
|
const comp = wt.layers.length > 0 ? getComponent(project, wt.layers[0].componentId) : null;
|
||||||
const stroke = ceiling.color ?? POCHE_STROKE;
|
const stroke = ceiling.color ?? POCHE_STROKE;
|
||||||
const outlineMm = lwMm * OUTLINE_DETAIL_FACTOR[detail];
|
|
||||||
const ceilingId = ceiling.id;
|
const ceilingId = ceiling.id;
|
||||||
|
|
||||||
// Gefüllte Fläche mit der Ansichts-Schraffur: die Decke wird im Grundriss
|
// Gefüllte Fläche mit der Ansichts-Schraffur: die Decke wird im Grundriss
|
||||||
@@ -1974,7 +1972,10 @@ function addCeilingPoche(
|
|||||||
a: add(a, scale(d, t0)),
|
a: add(a, scale(d, t0)),
|
||||||
b: add(a, scale(d, t1)),
|
b: add(a, scale(d, t1)),
|
||||||
cls: "ceiling-outline",
|
cls: "ceiling-outline",
|
||||||
weightMm: outlineMm,
|
// Überkopf-Ansichtslinie (Decke liegt als Slab über der Schnittebene) →
|
||||||
|
// gestrichelte Haarlinie statt kräftiger Volllinie (BIM-Konvention).
|
||||||
|
weightMm: LAYER_LINE_MM * LAYER_DETAIL_FACTOR[detail],
|
||||||
|
dash: OVERHEAD_DASH,
|
||||||
color: stroke,
|
color: stroke,
|
||||||
greyed,
|
greyed,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -80,3 +80,56 @@ describe("generatePlan — Schnitt vs. Ansicht nach Schnitthöhe", () => {
|
|||||||
expect(low.some((pr) => pr.fill !== "none")).toBe(true);
|
expect(low.some((pr) => pr.fill !== "none")).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Decke über der Schnittebene → gestrichelte Überkopf-Umrisslinie ──────────
|
||||||
|
|
||||||
|
/** Minimalprojekt mit EINER Decke (Slab) ohne Wände → voller Umriss sichtbar. */
|
||||||
|
function ceilingProject(): Project {
|
||||||
|
return {
|
||||||
|
id: "t",
|
||||||
|
name: "T",
|
||||||
|
lineStyles: [{ id: "thin", name: "d", weight: 0.13, color: "#111", dash: null }],
|
||||||
|
hatches: [{ id: "none", name: "Ohne", pattern: "none", scale: 1, angle: 0, color: "#111" }],
|
||||||
|
components: [{ id: "a", name: "A", color: "#d8d2c7", hatchId: "none", joinPriority: 10 }],
|
||||||
|
wallTypes: [{ id: "aw", name: "AW", layers: [{ componentId: "a", thickness: 0.2 }] }],
|
||||||
|
drawingLevels: [
|
||||||
|
{ id: "eg", name: "EG", kind: "floor", visible: true, locked: false, floorHeight: 2.6, cutHeight: 1.0, baseElevation: 0 },
|
||||||
|
],
|
||||||
|
layers: [{ code: "30", name: "Decken", color: "#0a0a0a", lw: 0.5, visible: true, locked: false }],
|
||||||
|
walls: [],
|
||||||
|
doors: [],
|
||||||
|
openings: [],
|
||||||
|
ceilings: [
|
||||||
|
{
|
||||||
|
id: "C1",
|
||||||
|
type: "ceiling",
|
||||||
|
floorId: "eg",
|
||||||
|
categoryCode: "30",
|
||||||
|
outline: [
|
||||||
|
{ x: 0, y: 0 },
|
||||||
|
{ x: 2, y: 0 },
|
||||||
|
{ x: 2, y: 2 },
|
||||||
|
{ x: 0, y: 2 },
|
||||||
|
],
|
||||||
|
wallTypeId: "aw",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stairs: [],
|
||||||
|
rooms: [],
|
||||||
|
drawings2d: [],
|
||||||
|
context: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("generatePlan — Decke = gestrichelte Überkopf-Ansicht", () => {
|
||||||
|
it("zeichnet den freien Decken-Umriss gestrichelt (Überkopf-Konvention)", () => {
|
||||||
|
const plan = generatePlan(ceilingProject(), "eg", new Set(["30"]), undefined, "mittel");
|
||||||
|
const outlines = plan.primitives.filter(
|
||||||
|
(p): p is Extract<typeof p, { kind: "line" }> =>
|
||||||
|
p.kind === "line" && p.cls === "ceiling-outline",
|
||||||
|
);
|
||||||
|
expect(outlines.length).toBeGreaterThan(0);
|
||||||
|
// JEDE Decken-Umrisslinie ist gestrichelt (dash gesetzt, nicht null).
|
||||||
|
expect(outlines.every((p) => Array.isArray(p.dash) && p.dash.length >= 2)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user