Dach im 3D anwählbar: Ray-Dreieck-Pick über die Dachflächen

Der 3D-Pick kannte nur Wand/Decke/Öffnung/Treppe — Dächer waren im
wgpu-Viewport nicht anwählbar (Nutzer-Report). Neu: pickGeometry liefert je
Dach die Dachflächen + Giebel als World-Dreiecke (fan-trianguliert wie
emitRoofs); pickNearest testet sie über das bestehende doppelseitige
rayTriangle (präzise geneigte Flächen statt Bounding-Prisma — kein Klick-
Diebstahl vor der Fassade dahinter). App-Routing: kind 'roof' →
setSelectedRoofIds (exklusiv, wie Treppe/Öffnung); damit greifen Highlight
und die Dach-3D-Griffe (4ef40a0) jetzt auch per 3D-Klick. +1 Test. 690/690.
This commit is contained in:
2026-07-10 23:56:12 +02:00
parent c91b9ab1f2
commit 355c1d4dd1
5 changed files with 94 additions and 10 deletions
+14 -1
View File
@@ -8,7 +8,7 @@
import { describe, it, expect } from "vitest";
import type { Project, Roof } from "../model/types";
import { sampleProject } from "../model/sampleProject";
import { selectionHighlightLines, projectToWalls3d, projectToModel3d } from "./toWalls3d";
import { selectionHighlightLines, projectToWalls3d, projectToModel3d, pickGeometry } from "./toWalls3d";
import { resolveHatch } from "./generatePlan";
import { roofGeometry, roofBaseElevation } from "../geometry/roof";
@@ -1453,3 +1453,16 @@ describe("emitOpeningShading (Rollladen-/Sonnenschutzkasten als 3D-Box)", () =>
).toBe(0);
});
});
describe("pickGeometry — Dächer (Ray-Dreieck-Pick)", () => {
it("liefert je Dach World-Dreiecke (Flächen + Giebel), world=[x,Höhe,y]", () => {
const { roofs } = pickGeometry(sampleProject);
// sampleProject trägt das Demo-Satteldach RF1.
expect(roofs.length).toBe(1);
expect(roofs[0].roofId).toBe("RF1");
// Sattel: 2 Flächen (je 4 Ecken → 2 Dreiecke) + 2 Giebel (je 1 Dreieck) = 6.
expect(roofs[0].tris.length).toBe(6);
// Höhe liegt in der WORLD-Y-Komponente (Index 1) — alle über der Traufe > 0.
for (const tri of roofs[0].tris) for (const p of tri) expect(p[1]).toBeGreaterThan(0);
});
});