Akkumulierten grünen Arbeitsstand landen (Basis für Weiterarbeit)
Bündelt den über mehrere Sessions gewachsenen, uncommitteten Stand in
einem Basis-Commit, damit Folge-Features isoliert darauf aufsetzen.
Verifikation: tsc --noEmit sauber, vitest 600/600 grün.
Enthalten (Details in PENDENZEN.md ✅-Liste / HANDOVER.md):
- truck-Integration: Profil-Extrusion + Verjüngung + Boolean-CSG (csgrs),
Crate src-tauri/trucksolid, Werkzeug `extrude`, ExtrudedSolid-Modell.
- kernel2d-Port nach Rust/WASM (Phasen 1–5, Diff-Harness).
- render3d 3D-Live-Schnitt = 2D-Schnitt: geschichteter Bodenaufbau,
Prioritäts-Verschneidung (section_boolean.rs), einstellbare
Schichttrennlinien, per-Hatch-Strichstärke, relativeToWall-Orientierung.
- Interop-Export IFC4/STL/OBJ (Loch-Ausschnitt wallMeshCut), Schnellexport.
- Projektdatei .obp + OS-Lock (lock.rs, LockConflictDialog).
- Layout-Blätter (Modell/Editor/Panel/PDF), Ausschnitte, Override-Engine,
Tragwerk-Stützen (Column), BIM-Tree-Panel.
- Bauteil-Typsystem (Tür/Fenster/Treppe-Typen), Betontreppe mit schräger
Laufplatte, Text-/Textbox-Werkzeug, Mess-Werkzeug, 2D/3D-Griffe für
Öffnungen/Treppen, Snap-Symbol-Restyle.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
// Unit-Tests für die Wand-/Decken-Resolver (wallVerticalExtent /
|
||||
// ceilingVerticalExtent): reine Datenschicht, kein React/Store.
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { ceilingVerticalExtent } from "./wall";
|
||||
import type { Ceiling, Project } from "./types";
|
||||
|
||||
/** Minimalprojekt mit einem Geschoss (baseElevation 0, floorHeight 2.6) und
|
||||
* einem einschichtigen Wandtyp (0.2 m), den die Decke als Aufbau nutzt. */
|
||||
function makeProject(overrides?: Partial<Project>): Project {
|
||||
return {
|
||||
id: "t",
|
||||
name: "T",
|
||||
lineStyles: [],
|
||||
hatches: [],
|
||||
components: [{ id: "c", name: "C", color: "#ccc", hatchId: "none", joinPriority: 10 }],
|
||||
wallTypes: [
|
||||
{ id: "dt", name: "Decke", layers: [{ componentId: "c", thickness: 0.2 }] },
|
||||
],
|
||||
drawingLevels: [
|
||||
{
|
||||
id: "eg",
|
||||
name: "EG",
|
||||
kind: "floor",
|
||||
visible: true,
|
||||
locked: false,
|
||||
floorHeight: 2.6,
|
||||
cutHeight: 1.0,
|
||||
baseElevation: 0,
|
||||
},
|
||||
{
|
||||
id: "og",
|
||||
name: "OG",
|
||||
kind: "floor",
|
||||
visible: true,
|
||||
locked: false,
|
||||
floorHeight: 2.6,
|
||||
cutHeight: 1.0,
|
||||
baseElevation: 2.8,
|
||||
},
|
||||
],
|
||||
layers: [{ code: "30", name: "Decken", color: "#0a0a0a", lw: 0.5, visible: true, locked: false }],
|
||||
walls: [],
|
||||
doors: [],
|
||||
openings: [],
|
||||
ceilings: [],
|
||||
stairs: [],
|
||||
rooms: [],
|
||||
drawings2d: [],
|
||||
context: [],
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function makeCeiling(overrides?: Partial<Ceiling>): Ceiling {
|
||||
return {
|
||||
id: "cl1",
|
||||
type: "ceiling",
|
||||
floorId: "eg",
|
||||
categoryCode: "30",
|
||||
outline: [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 4, y: 0 },
|
||||
{ x: 4, y: 4 },
|
||||
{ x: 0, y: 4 },
|
||||
],
|
||||
wallTypeId: "dt",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("ceilingVerticalExtent", () => {
|
||||
it("ohne top/bottom: OK = Geschoss-Oberkante, UK = OK − Dicke (heutiges Verhalten)", () => {
|
||||
const project = makeProject();
|
||||
const ceiling = makeCeiling();
|
||||
const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
|
||||
expect(zTop).toBeCloseTo(2.6); // baseElevation(0) + floorHeight(2.6)
|
||||
expect(zBottom).toBeCloseTo(2.4); // zTop − thickness(0.2)
|
||||
});
|
||||
|
||||
it("mit top: custom übersteuert die Oberkante; UK bleibt OK − Dicke", () => {
|
||||
const project = makeProject();
|
||||
const ceiling = makeCeiling({ top: { mode: "custom", z: 3.0 } });
|
||||
const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
|
||||
expect(zTop).toBeCloseTo(3.0);
|
||||
expect(zBottom).toBeCloseTo(2.8);
|
||||
});
|
||||
|
||||
it("mit bottom: custom übersteuert die Unterkante — gewinnt über OK − Dicke", () => {
|
||||
const project = makeProject();
|
||||
const ceiling = makeCeiling({ bottom: { mode: "custom", z: 2.2 } });
|
||||
const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
|
||||
expect(zTop).toBeCloseTo(2.6); // OK unverändert (Geschoss-Default)
|
||||
expect(zBottom).toBeCloseTo(2.2); // UK-Override statt OK − Dicke (2.4)
|
||||
});
|
||||
|
||||
it("mit top UND bottom: beide Overrides wirken unabhängig (Dicke wird ignoriert)", () => {
|
||||
const project = makeProject();
|
||||
const ceiling = makeCeiling({
|
||||
top: { mode: "custom", z: 5.0 },
|
||||
bottom: { mode: "custom", z: 4.5 },
|
||||
});
|
||||
const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
|
||||
expect(zTop).toBeCloseTo(5.0);
|
||||
expect(zBottom).toBeCloseTo(4.5);
|
||||
});
|
||||
|
||||
it("bottom: floor bindet die Unterkante an ein Geschoss (+ optionalem offset)", () => {
|
||||
const project = makeProject();
|
||||
const ceiling = makeCeiling({ bottom: { mode: "floor", floorId: "og", offset: 0.1 } });
|
||||
const { zBottom, zTop } = ceilingVerticalExtent(project, ceiling);
|
||||
expect(zTop).toBeCloseTo(2.6);
|
||||
expect(zBottom).toBeCloseTo(2.9); // baseElevation(og)=2.8 + offset(0.1)
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user