Resources Numerical accuracy Calculation policy

Project: stand-in ground, volumes and saved points

Holds the project and the results derived from it: a flat stand-in ground for a road with no survey, cut and fill inside the daylight lines, and the points written to the project file.

How the precision is kept

Surfaces, profiles, corridors and volumes are built by other modules and cached here by a text key of their inputs. The project file is written through JSON, which keeps every digit of a 64-bit number. The stand-in elevation is rounded to 0.01 and its result is marked with a warning.

Calculations under this policy

3 calculations 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.

project.js CivilCraft 0.8.1 64-bit 3 calculations Reviewed

Tests bin/test-civilcraft.mjs

Stand-in ground for a road with no survey

64-bit

The elevation and extent of the flat ground a corridor is drawn on when the project has no surface.

z = mean of the PVI elevations, rounded to 0.01; margin = (60 m or 200 ft) + 6 × (z_max − z_min)

The mean is a sum in order divided by the count, then rounded with Math.round(× 100) ÷ 100. Without a design profile the elevation is 0. The flat ground is nine points on the alignment's bounding box widened by the margin.

  • project.js
  • lines 380 to 388
  • CivilCraft 0.8.1
if (prof.ok && (a.pvis || []).length >= 2) z = Math.round((a.pvis.reduce((v, q) => v + q.z, 0) / a.pvis.length) * 100) / 100;
else { basis = 'zero'; z = 0; prof = buildProfile([{ sta: al.start, z: 0 }, { sta: al.end, z: 0 }]); }
// flat ground under the alignment, wide enough for its daylight (the profile's rise and fall at the flattest slope)
const pl = al.polyline(Math.max(al.length / 200, 1));
const zs = basis === 'profile' ? a.pvis.map((q) => q.z) : [0], dz = Math.max(...zs) - Math.min(...zs);
const pad = (m ? 60 : 200) + 6 * dz;
const x0 = Math.min(...pl.map((q) => q.x)) - pad, x1 = Math.max(...pl.map((q) => q.x)) + pad, y0 = Math.min(...pl.map((q) => q.y)) - pad, y1 = Math.max(...pl.map((q) => q.y)) + pad;
const pts = []; for (const x of [x0, (x0 + x1) / 2, x1]) for (const y of [y0, (y0 + y1) / 2, y1]) pts.push({ x, y, z });
const flat = buildSurface({ points: pts }).surface;

Cut and fill inside the daylight lines

64-bit

The total cut and fill and the figures per graded item.

Calls gridVolume once for all regions with the given cell size, then once per item with the cell size the total used, so the item figures and the total are on the same grid.

  • project.js
  • lines 429 to 440
  • CivilCraft 0.8.1
/** Cut and fill (grid method) inside every daylight line, in total and per item. */
volumes(cell) {
  const g = this.graded(), eg = this.eg().surface;
  if (!g.surface || !eg) return null;
  const regions = g.regions.filter(Boolean);
  if (!regions.length) return null;
  return this.memo('vol', this.surfaceDeps() + '|' + this.gradeDeps() + '|' + cell, () => {
    const total = gridVolume(eg, g.surface, { region: regions, cell });
    total.items = g.items.filter((it) => it.region).map((it) => ({ id: it.id, name: it.name, ...gridVolume(eg, g.surface, { region: it.region, cell: total.cell }) }));
    return total;
  });
}

Points in the project file

64-bit

Writes each survey point to the .civilcraft.json file.

Each point is written as [number, x, y, z, description] and serialized by JSON, which prints the shortest text that reads back to the same 64-bit number. No rounding.

  • project.js
  • line 454
  • CivilCraft 0.8.1
points: this.points.map((p) => (p.blk ? [p.n, p.x, p.y, p.z, p.d, p.blk] : [p.n, p.x, p.y, p.z, p.d])),   // 0.5 WL.19: + the block it came from

In detail

Method
Each derived result is memoized on a key made of JSON text of its inputs. Volumes use gridVolume between the existing and the graded surface.
Number types
64-bit numbers; JSON text in the project file.
Limits
The stand-in ground is flat and made up; the code comment says no volumes, sections or graded surface come from it. Volumes carry the accuracy of the grid method and its cell size.

Approach: 64-bit, stated limit

The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.

Every policy that takes this approach