Schnittlinien-Werkzeug: Befehl sectionline/viewline setzt linePoints

Zwei Klicks (Start -> Ende) legen die Grundriss-Schnitt-/Ansichtslinie einer
DrawingLevel fest. Ziel: genau eine Platzhalter-Ebene ohne Linie wird belegt,
sonst neue Ebene (Schnitt B/C ...). Live-Vorschau mit Richtungspfeil, Art
(Schnitt/Ansicht) als Inline-Option umschaltbar. Registry-Aliase schnittlinie/
ansichtslinie, Ribbon-Gruppe 'Schnitte' im BIM-Tab, i18n de/en, Datenpfad-Tests.
This commit is contained in:
2026-07-11 00:12:08 +02:00
parent 0e02c2b20f
commit 340f950f9c
7 changed files with 345 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
// Schnittlinien-Befehl: der reine Datenpfad (commitLine/nextLevelName) — setzt
// die Grundriss-Schnittlinie auf die richtige Ziel-Ebene bzw. legt eine neue an.
import { describe, it, expect } from "vitest";
import { _test } from "./sectionline";
import type { DrawingLevel, Project } from "../../model/types";
const { commitLine, nextLevelName } = _test;
function projectWith(levels: DrawingLevel[]): Project {
return {
id: "p",
name: "T",
layers: [],
drawingLevels: levels,
walls: [],
drawings2d: [],
} as unknown as Project;
}
const a = { x: 0, y: 0 };
const b = { x: 5, y: 0 };
describe("sectionline — commitLine", () => {
it("belegt die EINE Platzhalter-Schnittebene ohne Linie", () => {
const p = projectWith([
{ id: "eg", name: "EG", kind: "floor", visible: true, locked: false },
{ id: "s1", name: "Schnitt A", kind: "section", visible: true, locked: false },
]);
const out = commitLine(p, a, b, "section");
const s = out.drawingLevels.find((z) => z.id === "s1")!;
expect(s.linePoints).toEqual([a, b]);
expect(s.directionSign).toBe(1);
// Keine neue Ebene angelegt.
expect(out.drawingLevels).toHaveLength(2);
});
it("legt eine NEUE Schnittebene an, wenn keine Platzhalter-Ebene existiert", () => {
const p = projectWith([
{ id: "eg", name: "EG", kind: "floor", visible: true, locked: false },
{
id: "s1",
name: "Schnitt A",
kind: "section",
visible: true,
locked: false,
linePoints: [{ x: 1, y: 1 }, { x: 2, y: 2 }],
},
]);
const out = commitLine(p, a, b, "section");
expect(out.drawingLevels).toHaveLength(3);
const created = out.drawingLevels[out.drawingLevels.length - 1];
expect(created.kind).toBe("section");
expect(created.linePoints).toEqual([a, b]);
// Zweite Ebene → Buchstabe B.
expect(created.name).toContain("B");
});
it("legt bei ZWEI Platzhaltern (mehrdeutig) eine neue Ebene an", () => {
const p = projectWith([
{ id: "s1", name: "Schnitt A", kind: "section", visible: true, locked: false },
{ id: "s2", name: "Schnitt B", kind: "section", visible: true, locked: false },
]);
const out = commitLine(p, a, b, "section");
expect(out.drawingLevels).toHaveLength(3);
// Die bestehenden Platzhalter bleiben unangetastet.
expect(out.drawingLevels[0].linePoints).toBeUndefined();
expect(out.drawingLevels[1].linePoints).toBeUndefined();
});
it("verwirft entartete (zu kurze) Linien", () => {
const p = projectWith([
{ id: "s1", name: "Schnitt A", kind: "section", visible: true, locked: false },
]);
const out = commitLine(p, a, { x: 0.02, y: 0 }, "section");
expect(out).toBe(p);
});
it("trennt Schnitt- und Ansichts-Ebenen (kind)", () => {
const p = projectWith([
{ id: "s1", name: "Schnitt A", kind: "section", visible: true, locked: false },
]);
// Ansichtslinie darf die Schnitt-Platzhalter-Ebene NICHT belegen.
const out = commitLine(p, a, b, "elevation");
expect(out.drawingLevels).toHaveLength(2);
expect(out.drawingLevels[0].linePoints).toBeUndefined();
expect(out.drawingLevels[1].kind).toBe("elevation");
});
});
describe("sectionline — nextLevelName", () => {
it("zählt Buchstaben je Art hoch (A, B, C …)", () => {
const p0 = projectWith([]);
expect(nextLevelName(p0, "section")).toContain("A");
const p1 = projectWith([
{ id: "s1", name: "Schnitt A", kind: "section", visible: true, locked: false },
]);
expect(nextLevelName(p1, "section")).toContain("B");
});
});