3D: mehrschichtige Wände zeigen ihren Schichtaufbau
Statt eines Vollkörpers in der repräsentativen Farbe wird jede Materiallage der Wand als eigener extrudierter Teilquader in ihrer Component-Farbe emittiert (quer zur Wanddicke gestapelt, zentriert um die Achse). Gilt auch für die Öffnungs-Teilquader (Pfeiler/Brüstung/ Sturz). Jede Schicht-Box trägt die wallId der Ursprungswand → Klick- Auswahl + Highlight umfassen weiter die ganze Wand.
This commit is contained in:
+45
-11
@@ -24,12 +24,14 @@ describe("selectionHighlightLines", () => {
|
|||||||
expect(lines.length).toBe(0);
|
expect(lines.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("eine Wand ohne Öffnungen -> genau 12 Kanten (ein Quader)", () => {
|
it("eine Wand ohne Öffnungen -> je Materiallage ein Quader (4·12 Kanten)", () => {
|
||||||
// W2 (EG, Ost) trägt keine Tür/kein Fenster im Sample-Projekt (nur W1/W3
|
// W2 (EG, Ost) trägt keine Tür/kein Fenster im Sample-Projekt (nur W1/W3
|
||||||
// haben Öffnungen, s. sampleProject.ts) -> ein einziger Teilquader, also
|
// haben Öffnungen, s. sampleProject.ts) -> ein Achsen-Teilquader. Wandtyp
|
||||||
// exakt 12 Kanten.
|
// "aw" hat 4 Schichten (render-ext/insulation/brick/render-int), die
|
||||||
|
// TS-seitig je als eigene Box gestapelt werden (Option B) -> 4 Quader =
|
||||||
|
// 4·12 Kanten. (Früher: 1 Vollkörper = 12 Kanten.)
|
||||||
const lines = selectionHighlightLines(sampleProject, ["W2"], [], RGB);
|
const lines = selectionHighlightLines(sampleProject, ["W2"], [], RGB);
|
||||||
expect(lines.length).toBe(12 * VERTICES_PER_EDGE * FLOATS_PER_VERTEX);
|
expect(lines.length).toBe(4 * 12 * VERTICES_PER_EDGE * FLOATS_PER_VERTEX);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("eine Wand mit Farbwerten in jedem Vertex", () => {
|
it("eine Wand mit Farbwerten in jedem Vertex", () => {
|
||||||
@@ -70,16 +72,48 @@ describe("selectionHighlightLines", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("Bauteil-/Materialfarbe statt Einheits-Grau (Wände + Decken)", () => {
|
describe("Bauteil-/Materialfarbe statt Einheits-Grau (Wände + Decken)", () => {
|
||||||
it("Wand -> Farbe der dicksten Schicht (aw: insulation 0.16 m, #ffffff)", () => {
|
it("Wand -> je Materiallage eine Box in ihrer Component-Farbe (Option B)", () => {
|
||||||
// Wandtyp "aw" (s. sampleProject): render-ext 0.02, insulation 0.16,
|
// Wandtyp "aw" (s. sampleProject) hat 4 Schichten mit eigenen Farben:
|
||||||
// brick 0.15, render-int 0.015 -> dickste Schicht = insulation (#ffffff).
|
// render-ext 0.02 #d8d2c7, insulation 0.16 #ffffff,
|
||||||
|
// brick 0.15 #8c5544, render-int 0.015 #efece6 (Σ = 0.345 m).
|
||||||
|
// W2 ist öffnungslos -> genau ein Achsen-Teilquader, also 4 Schicht-Boxen.
|
||||||
const walls = projectToWalls3d(sampleProject);
|
const walls = projectToWalls3d(sampleProject);
|
||||||
const w2 = walls.filter((w) => w.wallId === "W2");
|
const w2 = walls.filter((w) => w.wallId === "W2");
|
||||||
expect(w2.length).toBeGreaterThan(0);
|
expect(w2.length).toBe(4);
|
||||||
|
|
||||||
|
// Alle Schicht-Boxen tragen die gemeinsame wallId (Klick selektiert ganze Wand)
|
||||||
|
// und sind Vollkörper (layers leer -> render3d zeichnet in `color`).
|
||||||
for (const seg of w2) {
|
for (const seg of w2) {
|
||||||
expect(seg.color[0]).toBeCloseTo(1, 6);
|
expect(seg.wallId).toBe("W2");
|
||||||
expect(seg.color[1]).toBeCloseTo(1, 6);
|
expect(seg.layers.length).toBe(0);
|
||||||
expect(seg.color[2]).toBeCloseTo(1, 6);
|
}
|
||||||
|
|
||||||
|
// Die vier Materialfarben kommen genau einmal vor.
|
||||||
|
const hex = (c: [number, number, number]) =>
|
||||||
|
c.map((v) => Math.round(v * 255).toString(16).padStart(2, "0")).join("");
|
||||||
|
const colors = w2.map((s) => hex(s.color)).sort();
|
||||||
|
expect(colors).toEqual(["8c5544", "d8d2c7", "efece6", "ffffff"]);
|
||||||
|
|
||||||
|
// Die Schichtdicken summieren zur Gesamt-Wanddicke (keine Lücken/Overlaps).
|
||||||
|
const totalT = w2.reduce((s, seg) => s + seg.thickness, 0);
|
||||||
|
expect(totalT).toBeCloseTo(0.345, 6);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Schicht-Offsets kacheln die Wanddicke lückenlos um die Achse", () => {
|
||||||
|
// W2-Achse (5,0)->(5,4): u=(0,1), Normale n=(1,0) -> der Schicht-Versatz
|
||||||
|
// wirkt rein auf x (Box-Start.x = 5 + offset). Sortiert man die Boxen nach
|
||||||
|
// Versatz, müssen sich benachbarte Flächen exakt berühren und der Stapel
|
||||||
|
// symmetrisch um die Achse liegen: min = -T/2, max = +T/2.
|
||||||
|
const w2 = projectToWalls3d(sampleProject).filter((w) => w.wallId === "W2");
|
||||||
|
const bands = w2
|
||||||
|
.map((s) => ({ offset: s.start[0] - 5, t: s.thickness }))
|
||||||
|
.sort((a, b) => a.offset - b.offset);
|
||||||
|
const T = bands.reduce((s, b) => s + b.t, 0);
|
||||||
|
expect(bands[0].offset - bands[0].t / 2).toBeCloseTo(-T / 2, 6);
|
||||||
|
expect(bands[bands.length - 1].offset + bands[bands.length - 1].t / 2).toBeCloseTo(T / 2, 6);
|
||||||
|
for (let i = 1; i < bands.length; i++) {
|
||||||
|
// Oberkante der Vorlage == Unterkante der nächsten (keine Lücke/Overlap).
|
||||||
|
expect(bands[i - 1].offset + bands[i - 1].t / 2).toBeCloseTo(bands[i].offset - bands[i].t / 2, 6);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+103
-45
@@ -18,13 +18,19 @@
|
|||||||
// Polygon-Platten (SlabInput) mitgegeben — render3d trianguliert den Umriss und
|
// Polygon-Platten (SlabInput) mitgegeben — render3d trianguliert den Umriss und
|
||||||
// zieht ihn über die Deckendicke hoch.
|
// zieht ihn über die Deckendicke hoch.
|
||||||
//
|
//
|
||||||
// SCHICHTEN (Putz/Dämmung/Mauerwerk/…): zusätzlich zur Gesamtdicke wird der
|
// SCHICHTEN (Putz/Dämmung/Mauerwerk/…): der aufgelöste Schichtaufbau des
|
||||||
// aufgelöste Schichtaufbau des WallType mitgegeben (`layers`) — je Schicht
|
// WallType wird HIER (TS-seitig) in echte 3D-Substanz zerlegt — statt EINES
|
||||||
// Dicke + 3D-Farbe des zugehörigen Bauteil-Materials (Component). render3d
|
// Vollkörpers in der repräsentativen Farbe emittiert jede Achsen-Teilquader-
|
||||||
// extrudiert daraus je Schicht ein eigenes Band quer zur Wanddicke (siehe
|
// Position je Materiallage eine EIGENE Box, quer zur Wanddicke entlang der
|
||||||
// render3d::mesh); die Eck-Gehrung (Wandknoten-Verschneidung) berechnet
|
// Wand-Normalen gestapelt und in der Materialfarbe ihres Components eingefärbt
|
||||||
// render3d selbständig aus der Wandkonnektivität, braucht also keine
|
// (Option B). Schicht i belegt entlang der Normalen das Intervall
|
||||||
// zusätzlichen Felder von hier.
|
// [−T/2 + Σ_{k<i} t_k, −T/2 + Σ_{k≤i} t_k], T = Σ t_k (Summe der Lagen),
|
||||||
|
// zentriert um die Wandachse. Alle Schicht-Boxen einer Wand tragen dieselbe
|
||||||
|
// `wallId` (Klick/Highlight selektieren die GANZE Wand). Jede Box ist ein
|
||||||
|
// Vollkörper (`layers: []`), den render3d in ihrer `color` zeichnet — die
|
||||||
|
// Schicht-Aufteilung passiert also komplett hier, render3d bleibt unverändert.
|
||||||
|
// Ohne auflösbaren WallType/ohne Schichten: EIN Vollkörper über die volle
|
||||||
|
// Dicke im neutralen Grundton (heutiges Fallback-Verhalten).
|
||||||
|
|
||||||
import type { Project, Wall, Layer } from "../model/types";
|
import type { Project, Wall, Layer } from "../model/types";
|
||||||
import {
|
import {
|
||||||
@@ -42,7 +48,12 @@ export type RRgb = [number, number, number];
|
|||||||
/** Weltpunkt (x, elevation, y) — nur intern für Highlight-Kantengeometrie. */
|
/** Weltpunkt (x, elevation, y) — nur intern für Highlight-Kantengeometrie. */
|
||||||
type RVec3 = [number, number, number];
|
type RVec3 = [number, number, number];
|
||||||
|
|
||||||
/** Eine aufgelöste Wandschicht: Dicke + 3D-Albedo-Farbe (aus dem Component). */
|
/**
|
||||||
|
* Eine aufgelöste Wandschicht: Dicke + 3D-Albedo-Farbe (aus dem Component).
|
||||||
|
* Wird seit der TS-seitigen Schicht-Zerlegung (Option B, siehe Moduldoc) NICHT
|
||||||
|
* mehr an render3d durchgereicht — jede Schicht ist eine eigene Voll-Box; das
|
||||||
|
* `RWall.layers`-Feld bleibt für Serde-Kompatibilität, aber stets leer.
|
||||||
|
*/
|
||||||
export interface RLayer {
|
export interface RLayer {
|
||||||
thickness: number;
|
thickness: number;
|
||||||
color: RRgb;
|
color: RRgb;
|
||||||
@@ -55,7 +66,11 @@ export interface RWall {
|
|||||||
height: number;
|
height: number;
|
||||||
baseElevation: number;
|
baseElevation: number;
|
||||||
color: RRgb;
|
color: RRgb;
|
||||||
/** Aufgelöster Schichtaufbau (leer = kein WallType auflösbar, siehe emitWall). */
|
/**
|
||||||
|
* Immer leer: die Schichten werden TS-seitig in eigene Voll-Boxen zerlegt
|
||||||
|
* (Option B, siehe Moduldoc). Feld bleibt nur zur Serde-Kompatibilität mit
|
||||||
|
* render3d::WallInput (leer ⇒ Vollkörper-Extrusion in `color`).
|
||||||
|
*/
|
||||||
layers: RLayer[];
|
layers: RLayer[];
|
||||||
/**
|
/**
|
||||||
* Id der Ursprungs-Wand (`project.walls[].id`). Alle Öffnungs-Teilquader einer
|
* Id der Ursprungs-Wand (`project.walls[].id`). Alle Öffnungs-Teilquader einer
|
||||||
@@ -146,10 +161,57 @@ function dominantLayerColor(layers: Layer[], project: Project, fallback: RRgb):
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hängt einen Wand-Teilquader an: das Achsenstück [from..to] (Meter ab
|
* Eine quer zur Wanddicke gestapelte Materiallage als 3D-Band: eigene Dicke,
|
||||||
* Wand-Startpunkt) über den Höhenbereich [zBottom..zTop]. Entartete Stücke
|
* Materialfarbe und Mitten-Versatz `offset` (Meter, entlang der Wand-Normalen,
|
||||||
* (Länge ≤ 0 oder Höhe ≤ 0) werden übersprungen — so überleben Öffnungen dicht
|
* relativ zur Wandachse). Jede solche Lage wird pro Achsen-Teilquader zu einer
|
||||||
* an den Wandenden ohne Nullquader.
|
* eigenen Voll-Box (siehe {@link emitWall}/{@link pushSegment}).
|
||||||
|
*/
|
||||||
|
interface WallBand {
|
||||||
|
thickness: number;
|
||||||
|
color: RRgb;
|
||||||
|
offset: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Löst den Schichtstapel EINER Wand auf: je Materiallage ein {@link WallBand}
|
||||||
|
* mit ihrer Dicke, Component-Farbe und dem Mitten-Versatz entlang der Normalen.
|
||||||
|
* Die Versätze zentrieren den Stapel um die Wandachse; als Gesamtdicke T dient
|
||||||
|
* die SUMME der tatsächlichen Lagen-Dicken (nicht `wallTypeThickness`, falls es
|
||||||
|
* abweicht) — so schließen die Bänder lückenlos aneinander an. Kein auflösbarer
|
||||||
|
* WallType / keine Lagen ⇒ EIN Vollkörper-Band über die volle Dicke im
|
||||||
|
* neutralen Grundton (heutiges Fallback-Verhalten).
|
||||||
|
*/
|
||||||
|
function resolveWallBands(project: Project, wall: Wall): WallBand[] {
|
||||||
|
try {
|
||||||
|
const wt = getWallType(project, wall);
|
||||||
|
if (wt.layers.length > 0) {
|
||||||
|
// Gesamtdicke = Summe der Lagen (konsistent mit den Offsets); wenn diese
|
||||||
|
// von wallTypeThickness abwiche, gewinnt die Lagen-Summe (keine Lücken).
|
||||||
|
const total = wt.layers.reduce((s, l) => s + l.thickness, 0);
|
||||||
|
const bands: WallBand[] = [];
|
||||||
|
let prefix = 0;
|
||||||
|
for (const l of wt.layers) {
|
||||||
|
const color = hexToRgb(getComponent(project, l.componentId).color);
|
||||||
|
bands.push({ thickness: l.thickness, color, offset: -total / 2 + prefix + l.thickness / 2 });
|
||||||
|
prefix += l.thickness;
|
||||||
|
}
|
||||||
|
return bands;
|
||||||
|
}
|
||||||
|
// WallType ohne Schichten: EIN Vollkörper über die Typ-Gesamtdicke.
|
||||||
|
return [{ thickness: wallTypeThickness(wt), color: WALL_RGB, offset: 0 }];
|
||||||
|
} catch {
|
||||||
|
// Kein auflösbarer WallType: EIN Vollkörper mit Default-Dicke/Grundton.
|
||||||
|
return [{ thickness: 0.2, color: WALL_RGB, offset: 0 }];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hängt eine Wand-Schicht-Box an: das Achsenstück [from..to] (Meter ab
|
||||||
|
* Wand-Startpunkt) über den Höhenbereich [zBottom..zTop], quer um `normalOffset`
|
||||||
|
* Meter entlang der Wand-Normalen versetzt (Schichtmitte relativ zur Achse) und
|
||||||
|
* mit Schicht-`thickness`/`color`. Entartete Stücke (Länge ≤ 0 oder Höhe ≤ 0)
|
||||||
|
* werden übersprungen — so überleben Öffnungen dicht an den Wandenden ohne
|
||||||
|
* Nullquader.
|
||||||
*/
|
*/
|
||||||
function pushSegment(
|
function pushSegment(
|
||||||
out: RWall[],
|
out: RWall[],
|
||||||
@@ -159,9 +221,9 @@ function pushSegment(
|
|||||||
zBottom: number,
|
zBottom: number,
|
||||||
zTop: number,
|
zTop: number,
|
||||||
thickness: number,
|
thickness: number,
|
||||||
layers: RLayer[],
|
normalOffset: number,
|
||||||
wallId: string,
|
|
||||||
color: RRgb,
|
color: RRgb,
|
||||||
|
wallId: string,
|
||||||
): void {
|
): void {
|
||||||
if (to - from <= EPS) return;
|
if (to - from <= EPS) return;
|
||||||
if (zTop - zBottom <= EPS) return;
|
if (zTop - zBottom <= EPS) return;
|
||||||
@@ -171,8 +233,14 @@ function pushSegment(
|
|||||||
if (len < 1e-9) return;
|
if (len < 1e-9) return;
|
||||||
const ux = dx / len;
|
const ux = dx / len;
|
||||||
const uy = dy / len;
|
const uy = dy / len;
|
||||||
const p1: RVec2 = [wall.start.x + ux * from, wall.start.y + uy * from];
|
// Grundriss-Normale (identisch zur Dicken-Achse in raycast3d /
|
||||||
const p2: RVec2 = [wall.start.x + ux * to, wall.start.y + uy * to];
|
// selectionHighlightLines: n = (uy, −ux)). Der Schicht-Versatz verschiebt
|
||||||
|
// Start/Ende der Box quer zur Wand, sodass render3d/raycast die Box um ihre
|
||||||
|
// eigene (versetzte) Achse zentriert aufbaut.
|
||||||
|
const ox = uy * normalOffset;
|
||||||
|
const oy = -ux * normalOffset;
|
||||||
|
const p1: RVec2 = [wall.start.x + ux * from + ox, wall.start.y + uy * from + oy];
|
||||||
|
const p2: RVec2 = [wall.start.x + ux * to + ox, wall.start.y + uy * to + oy];
|
||||||
out.push({
|
out.push({
|
||||||
start: p1,
|
start: p1,
|
||||||
end: p2,
|
end: p2,
|
||||||
@@ -180,38 +248,27 @@ function pushSegment(
|
|||||||
height: zTop - zBottom,
|
height: zTop - zBottom,
|
||||||
baseElevation: zBottom,
|
baseElevation: zBottom,
|
||||||
color,
|
color,
|
||||||
layers,
|
layers: [],
|
||||||
wallId,
|
wallId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Emittiert die Teilquader EINER Wand (mit oder ohne Öffnungen). */
|
/** Emittiert die Teilquader EINER Wand (mit oder ohne Öffnungen). */
|
||||||
function emitWall(out: RWall[], project: Project, wall: Wall): void {
|
function emitWall(out: RWall[], project: Project, wall: Wall): void {
|
||||||
let thickness = 0.2;
|
const bands = resolveWallBands(project, wall);
|
||||||
// Aufgelöster Schichtaufbau (Dicke + 3D-Farbe je Schicht des WallType) —
|
|
||||||
// leer, wenn kein WallType auflösbar ist (render3d extrudiert dann wie
|
|
||||||
// bisher einen Vollkörper aus `thickness`/`color`, siehe RWall-Moduldoc).
|
|
||||||
let layers: RLayer[] = [];
|
|
||||||
// Repräsentative Vollkörper-Farbe = Farbe der dicksten Schicht (Option A,
|
|
||||||
// siehe Moduldoc); Fallback WALL_RGB, wenn kein WallType auflösbar ist.
|
|
||||||
let color: RRgb = WALL_RGB;
|
|
||||||
try {
|
|
||||||
const wt = getWallType(project, wall);
|
|
||||||
thickness = wallTypeThickness(wt);
|
|
||||||
layers = wt.layers.map((l) => ({
|
|
||||||
thickness: l.thickness,
|
|
||||||
color: hexToRgb(getComponent(project, l.componentId).color),
|
|
||||||
}));
|
|
||||||
color = dominantLayerColor(wt.layers, project, WALL_RGB);
|
|
||||||
} catch {
|
|
||||||
thickness = 0.2;
|
|
||||||
layers = [];
|
|
||||||
color = WALL_RGB;
|
|
||||||
}
|
|
||||||
const { zBottom, zTop } = wallVerticalExtent(project, wall);
|
const { zBottom, zTop } = wallVerticalExtent(project, wall);
|
||||||
const axisLen = Math.hypot(wall.end.x - wall.start.x, wall.end.y - wall.start.y);
|
const axisLen = Math.hypot(wall.end.x - wall.start.x, wall.end.y - wall.start.y);
|
||||||
if (axisLen < 1e-9 || zTop - zBottom <= EPS) return;
|
if (axisLen < 1e-9 || zTop - zBottom <= EPS) return;
|
||||||
|
|
||||||
|
// Ein Achsen-Teilquader × jede Materiallage = eine Box (Schichtstapel quer
|
||||||
|
// zur Wanddicke). Alle tragen die Wand-Id, sodass ein Klick auf irgendeine
|
||||||
|
// Schicht die GANZE Wand selektiert und das Highlight alle Bänder umrandet.
|
||||||
|
const emitSeg = (from: number, to: number, zb: number, zt: number): void => {
|
||||||
|
for (const b of bands) {
|
||||||
|
pushSegment(out, wall, from, to, zb, zt, b.thickness, b.offset, b.color, wall.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Aussparungen der Wand als vereinheitlichte Cutouts sammeln:
|
// Aussparungen der Wand als vereinheitlichte Cutouts sammeln:
|
||||||
// • Öffnungen (project.openings, Fenster mit Brüstung/Sturz),
|
// • Öffnungen (project.openings, Fenster mit Brüstung/Sturz),
|
||||||
// • Legacy-Türen (project.doors, sitzen am Boden, nur Sturz).
|
// • Legacy-Türen (project.doors, sitzen am Boden, nur Sturz).
|
||||||
@@ -234,9 +291,10 @@ function emitWall(out: RWall[], project: Project, wall: Wall): void {
|
|||||||
}
|
}
|
||||||
cutouts.sort((a, b) => a.from - b.from);
|
cutouts.sort((a, b) => a.from - b.from);
|
||||||
|
|
||||||
// Ohne Aussparungen: ein durchgehender Quader (wie bisher).
|
// Ohne Aussparungen: ein durchgehender Quader je Schicht (wie bisher, aber
|
||||||
|
// in Lagen aufgeteilt).
|
||||||
if (cutouts.length === 0) {
|
if (cutouts.length === 0) {
|
||||||
pushSegment(out, wall, 0, axisLen, zBottom, zTop, thickness, layers, wall.id, color);
|
emitSeg(0, axisLen, zBottom, zTop);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,23 +306,23 @@ function emitWall(out: RWall[], project: Project, wall: Wall): void {
|
|||||||
const segFrom = Math.max(cursor, from);
|
const segFrom = Math.max(cursor, from);
|
||||||
if (from > cursor) {
|
if (from > cursor) {
|
||||||
// Voller Wandpfeiler bis zur Aussparung.
|
// Voller Wandpfeiler bis zur Aussparung.
|
||||||
pushSegment(out, wall, cursor, from, zBottom, zTop, thickness, layers, wall.id, color);
|
emitSeg(cursor, from, zBottom, zTop);
|
||||||
}
|
}
|
||||||
if (to > segFrom) {
|
if (to > segFrom) {
|
||||||
// Brüstung unter der Öffnung (bei Türen entfällt sie, da oBottom == zBottom).
|
// Brüstung unter der Öffnung (bei Türen entfällt sie, da oBottom == zBottom).
|
||||||
if (oBottom > zBottom + EPS) {
|
if (oBottom > zBottom + EPS) {
|
||||||
pushSegment(out, wall, segFrom, to, zBottom, oBottom, thickness, layers, wall.id, color);
|
emitSeg(segFrom, to, zBottom, oBottom);
|
||||||
}
|
}
|
||||||
// Sturz über der Öffnung (bis zum Wandkopf).
|
// Sturz über der Öffnung (bis zum Wandkopf).
|
||||||
if (oTop < zTop - EPS) {
|
if (oTop < zTop - EPS) {
|
||||||
pushSegment(out, wall, segFrom, to, oTop, zTop, thickness, layers, wall.id, color);
|
emitSeg(segFrom, to, oTop, zTop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor = Math.max(cursor, to);
|
cursor = Math.max(cursor, to);
|
||||||
}
|
}
|
||||||
// Restlicher Wandpfeiler bis zum Achsenende.
|
// Restlicher Wandpfeiler bis zum Achsenende.
|
||||||
if (cursor < axisLen) {
|
if (cursor < axisLen) {
|
||||||
pushSegment(out, wall, cursor, axisLen, zBottom, zTop, thickness, layers, wall.id, color);
|
emitSeg(cursor, axisLen, zBottom, zTop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user