Resources Numerical accuracy Calculation policy

Building mass mesh for the 3D view

Builds the walls and roof of a building mass as a triangle mesh for drawing.

How the precision is kept

The mesh positions and normals are stored in 32-bit arrays and are used only to draw the mass; the only caller in the app is the 3D view (site3d.js). The areas, levels and volumes of a mass are worked out separately in 64-bit.

Calculations under this policy

1 calculation in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.

massing.js CivilCraft 0.8.1 32-bit, display only 1 calculation Reviewed

Tests bin/test-civilcraft-massing.mjs

Mass prism mesh

32-bit, display only

The triangles of the walls and roof of a mass.

Positions are pushed as absolute project coordinates and then copied into a Float32Array, before any shift to a local origin. The result goes to the 3D view only.

  • massing.js
  • lines 152 to 168
  • CivilCraft 0.8.1
/** The mass as a closed prism: walls from zBottom up to the roof (z0 + height) and the roof. Absolute project coordinates. */
export function massMesh(m, z0, zBottom = z0) {
  const P = signedArea(m.pts) < 0 ? m.pts.slice().reverse() : m.pts, n = P.length, top = z0 + massHeight(m), bot = Math.min(zBottom, z0);
  const pos = [], nor = [], ind = [];
  for (let i = 0; i < n; i++) {
    const a = P[i], b = P[(i + 1) % n], L = Math.hypot(b.x - a.x, b.y - a.y);
    if (L < 1e-12) continue;
    const nx = (b.y - a.y) / L, ny = -(b.x - a.x) / L, k = pos.length / 3;   // outward for a counter-clockwise outline
    pos.push(a.x, a.y, bot, b.x, b.y, bot, b.x, b.y, top, a.x, a.y, top);
    for (let q = 0; q < 4; q++) nor.push(nx, ny, 0);
    ind.push(k, k + 1, k + 2, k, k + 2, k + 3);
  }
  const k0 = pos.length / 3;
  for (const p of P) { pos.push(p.x, p.y, top); nor.push(0, 0, 1); }
  for (const i of triangulate(P)) ind.push(k0 + i);
  return { positions: new Float32Array(pos), normals: new Float32Array(nor), indices: new Uint32Array(ind) };
}

In detail

Method
One quad per wall with an outward normal; the roof from the footprint triangulation.
Number types
Float32Array positions and normals, Uint32Array indexes.
Tolerances
Walls shorter than 1e-12 are skipped.
Limits
The positions are absolute project coordinates in 32-bit, which are 0.25 to 0.5 units apart for coordinates of a few million, so a mass far from the origin can be drawn slightly off its footprint.

Approach: Display only

Computed to draw the screen, often in 32-bit on the graphics processor. No number a person reads, saves or exports comes from it.

Every policy that takes this approach