Dach: Auswahl-Hervorhebung auch im 3D (Draht-Umriss der Dachflächen)
selectionHighlightLines bekommt roofIds und emittiert die Kanten aller Dachflächen + Giebel (roofGeometry, Modell→World) als Akzent-Draht — ein selektiertes Dach leuchtet jetzt im wgpu-Viewport wie Wand/Decke. App reicht selectedRoofIds durch. +1 Test. tsc + vitest grün.
This commit is contained in:
+4
-1
@@ -5984,7 +5984,8 @@ function Content({
|
||||
selectedWallIds.length === 0 &&
|
||||
selectedCeilingIds.length === 0 &&
|
||||
selectedOpeningIds.length === 0 &&
|
||||
selectedStairIds.length === 0
|
||||
selectedStairIds.length === 0 &&
|
||||
selectedRoofIds.length === 0
|
||||
? null
|
||||
: selectionHighlightLines(
|
||||
project,
|
||||
@@ -5993,6 +5994,7 @@ function Content({
|
||||
HIGHLIGHT_RGB,
|
||||
selectedOpeningIds,
|
||||
selectedStairIds,
|
||||
selectedRoofIds,
|
||||
),
|
||||
[
|
||||
project,
|
||||
@@ -6000,6 +6002,7 @@ function Content({
|
||||
selectedCeilingIds,
|
||||
selectedOpeningIds,
|
||||
selectedStairIds,
|
||||
selectedRoofIds,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -27,6 +27,15 @@ describe("selectionHighlightLines", () => {
|
||||
expect(lines.length).toBe(0);
|
||||
});
|
||||
|
||||
it("ein Dach -> Draht-Kanten der Dachflächen/Giebel (nicht leer, mit Farbe)", () => {
|
||||
// sampleProject enthält das Demo-Satteldach RF1.
|
||||
const lines = selectionHighlightLines(sampleProject, [], [], RGB, [], [], ["RF1"]);
|
||||
expect(lines.length).toBeGreaterThan(0);
|
||||
// Farbe in jedem Vertex (erstes Vertex: [px,py,pz,r,g,b]).
|
||||
expect(lines[3]).toBeCloseTo(RGB[0], 6);
|
||||
expect(lines[5]).toBeCloseTo(RGB[2], 6);
|
||||
});
|
||||
|
||||
it("eine Wand ohne Öffnungen -> je Materiallage ein Quader, Kern-Band unter der Decke gespalten (5·12 Kanten)", () => {
|
||||
// W2 (EG, Ost) trägt keine Tür/kein Fenster im Sample-Projekt (nur W1/W3
|
||||
// haben Öffnungen, s. sampleProject.ts) -> ein Achsen-Teilquader. Wandtyp
|
||||
|
||||
+22
-1
@@ -2254,12 +2254,14 @@ export function selectionHighlightLines(
|
||||
rgb: RRgb,
|
||||
openingIds: string[] = [],
|
||||
stairIds: string[] = [],
|
||||
roofIds: string[] = [],
|
||||
): Float32Array {
|
||||
if (
|
||||
wallIds.length === 0 &&
|
||||
ceilingIds.length === 0 &&
|
||||
openingIds.length === 0 &&
|
||||
stairIds.length === 0
|
||||
stairIds.length === 0 &&
|
||||
roofIds.length === 0
|
||||
) {
|
||||
return new Float32Array(0);
|
||||
}
|
||||
@@ -2268,6 +2270,7 @@ export function selectionHighlightLines(
|
||||
const ceilingSet = new Set(ceilingIds);
|
||||
const openingSet = new Set(openingIds);
|
||||
const stairSet = new Set(stairIds);
|
||||
const roofSet = new Set(roofIds);
|
||||
const out: number[] = [];
|
||||
const pushEdge = (a: RVec3, b: RVec3) => {
|
||||
out.push(a[0], a[1], a[2], rgb[0], rgb[1], rgb[2]);
|
||||
@@ -2332,5 +2335,23 @@ export function selectionHighlightLines(
|
||||
for (const o of openings) if (openingSet.has(o.openingId)) boxEdges(o);
|
||||
for (const s of slabs) if (ceilingSet.has(s.ceilingId)) prismEdges(s.outline, s.zBottom, s.zTop);
|
||||
for (const st of stairs) if (stairSet.has(st.stairId)) prismEdges(st.outline, st.zBottom, st.zTop);
|
||||
// Dach: die Kanten aller Dachflächen + Giebel als Draht-Umriss (roofGeometry
|
||||
// liefert 3D-Polygone in MODELL-Koordinaten [x, y, z=Höhe]; world = [x, z, y]).
|
||||
if (roofSet.size > 0) {
|
||||
for (const roof of project.roofs ?? []) {
|
||||
if (!roofSet.has(roof.id)) continue;
|
||||
const g = roofGeometry(roof, roofBaseElevation(project, roof));
|
||||
const polyEdges = (pts: readonly (readonly [number, number, number])[]) => {
|
||||
const m = pts.length;
|
||||
for (let i = 0, j = m - 1; i < m; j = i++) {
|
||||
const a = pts[j];
|
||||
const b = pts[i];
|
||||
pushEdge([a[0], a[2], a[1]], [b[0], b[2], b[1]]);
|
||||
}
|
||||
};
|
||||
for (const pl of g.planes) polyEdges(pl.pts);
|
||||
for (const gab of g.gables) polyEdges(gab);
|
||||
}
|
||||
}
|
||||
return new Float32Array(out);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user