model2geom = (model) => {
const { min, max } = Math;
const subzones = [];
const P = pt;
const L = ln;
const A = (...values) => values.filter((value) => value);
for (const [i, j, h, hw, he, hs, hn, hsw, hse, hnw, hne] of model) {
if (h > 0) {
const D = 0.5;
const origin = [i + D, j + D, 0];
const elements = [];
const SW = [-D, -D];
const SE = [D, -D];
const NE = [D, D];
const NW = [-D, D];
const [pSW, pSE, pNE, pNW] = [SW, SE, NE, NW].map((dir) => pt(...dir, h));
const sS = ln(pSW, pSE);
const sE = ln(pSE, pNE);
const sN = ln(pNE, pNW);
const sW = ln(pNW, pSW);
const roofNodes = [];
const roofSide = (dx, dy, h1, h2, h3) => {
const [p1, p2] = [P(dy, -dx, 0), P(-dy, dx, 0)];
const [t1, t2] = [P(0, 0, 0.4), P(-dx, -dy, 0.4)];
const elements = [];
if (h2 >= h) {
elements.push(
facet(
[p1, t1, t2],
A(h2 > h && [p1, t1], [t1, t2], h1 >= h && [t2, p1])
),
facet(
[p2, t2, t1],
A(h3 >= h && [p2, t2], [t2, t1], h2 > h && [t1, p2])
)
);
} else
elements.push(
facet(
[p1, p2, t2],
A([p1, p2], h > h3 && [p2, t2], h > h1 && [t2, p1])
)
);
return { origin: P(dx, dy, 0), elements };
};
roofNodes.push(roofSide(-D, 0, hn, hw, hs));
roofNodes.push(roofSide(0, -D, hw, hs, he));
roofNodes.push(roofSide(D, 0, hs, he, hn));
roofNodes.push(roofSide(0, D, he, hn, hw));
/*} else {
const topSegments = [];
if (h != hs) topSegments.push(sS);
if (h != he) topSegments.push(sE);
if (h != hn) topSegments.push(sN);
if (h != hw) topSegments.push(sW);
elements.push(facet([pSW, pSE, pNE, pNW], topSegments));
}*/
// side walls
const corner = (ci, cj, h1, h2, hd) => {
const vert = (h1, h2) => ln(pt(ci, cj, h1), pt(ci, cj, h2));
const segments = [];
if (h > h1 && h > h2) {
const [hmin, hmax] = [min(h1, h2), max(h1, h2)];
segments.push(vert(h, hmax));
if (hd > hmin && hmin != hmax)
segments.push(vert(min(hd, hmax), hmin));
return segments;
} else if (h < h1 && h < h2) {
if (h > hd) segments.push(vert(h, hd));
} else {
const hmin = min(h1, h2);
if (hd > hmin) segments.push(vert(min(hd, h), hmin));
}
return segments;
};
const ssw = corner(...SW, hw, hs, hsw);
const sse = corner(...SE, hs, he, hse);
const sne = corner(...NE, he, hn, hne);
const snw = corner(...NW, hn, hw, hnw);
if (h > hw) {
const quad = [pSW, pNW, pt(...NW, hw), pt(...SW, hw)];
const base = hw == 0 ? floor(SW, NW, 0, R(0.25)) : [];
elements.push(facet(quad, [sW, ...snw, ...ssw, ...base]));
}
if (h > he) {
const quad = [pNE, pSE, pt(...SE, he), pt(...NE, he)];
const base = he == 0 ? floor(NE, SE, 0, R(0.25)) : [];
elements.push(facet(quad, [sE, ...sne, ...sse, ...base]));
}
if (h > hs) {
const quad = [pSE, pSW, pt(...SW, hs), pt(...SE, hs)];
const base = hs == 0 ? floor(SE, SW, 0, R(0.25)) : [];
elements.push(facet(quad, [sS, ...ssw, ...sse, ...base]));
}
if (h > hn) {
const quad = [pNW, pNE, pt(...NE, hn), pt(...NW, hn)];
const base = hn == 0 ? floor(NW, NE, 0, R(0.25)) : [];
elements.push(facet(quad, [sN, ...snw, ...sne, ...base]));
}
subzones.push({
origin,
subzones: [
{ origin: [0, 0, 0], elements },
{ origin: [0, 0, h], subzones: roofNodes }
]
});
//subzones.push({ origin, elements });
}
}
return { origin: [0, 0, 0], subzones };
}