Resources Numerical accuracy Calculation policy

Automatic plan dimensions

Chooses the points an automatic row of dimensions measures between: the building's overall size and the stops along each outside edge.

How the precision is kept

Plan millimeters in 64-bit. Wall reference points come from wall-dimensions.js; this file picks which of them to dimension, using absolute tolerances in millimeters. Two saved values are rounded: the station along a wall to six decimals and the dimension line's offset to 0.1 mm.

Open item. Save each reference's station along its wall without rounding it to six decimals.

Calculations under this policy

6 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.

autodim.js BimCraft 0.8.1 64-bit 6 calculations Reviewed

Tests bin/test-autodim.mjs, tools/bimcraft-test/r47-test.mjs

Plan extents and edge tolerance

64-bit

The outside box of the level's walls and how close to it a wall must lie to count as an outside edge.

T = 1.2 × max(150 mm, thickest wall)

The extents are the minimum and maximum of the walls' outside-face end points, in 64-bit. The edge tolerance is absolute, in millimeters, and grows with the thickest wall.

  • autodim.js
  • lines 38 to 40
  • BimCraft 0.8.1
const minX = Math.min(...ends.map((e) => e.p[0])), maxX = Math.max(...ends.map((e) => e.p[0]));
const minY = Math.min(...ends.map((e) => e.p[1])), maxY = Math.max(...ends.map((e) => e.p[1]));
const T = tol ?? Math.max(150, ...straight.map((w) => w.t || 0)) * 1.2;

Dimension line offset

64-bit

How far the dimension line sits from the two points it measures.

offset = round((target − a)·n × 10) ÷ 10, n = (−dy, dx) ÷ |b − a|

The offset is rounded to 0.1 mm before it is saved. It places the line; it is not the measured length. The division by the segment's length is safe because add refuses segments under 20 mm first.

  • autodim.js
  • lines 41 to 44
  • BimCraft 0.8.1
const offFor = (a, b, target) => {   // wall-dimensions.js: n = (-dy, dx) / length of the measured segment a→b; the line sits at a + n * offset
  const v = Math.hypot(b[0] - a[0], b[1] - a[1]), n = [-(b[1] - a[1]) / v, (b[0] - a[0]) / v];
  return Math.round(((target[0] - a[0]) * n[0] + (target[1] - a[1]) * n[1]) * 10) / 10;
};

Reference station on a wall

64-bit

The saved position of a dimension's end along its wall, 0 at one end and 1 at the other.

station = round(station × 10⁶) ÷ 10⁶

The station is rounded to six decimals before it is saved. On a 10 m wall one unit of the sixth decimal is 0.01 mm, so the saved point of an opening edge can be up to 0.005 mm from the edge.

  • autodim.js
  • line 45
  • BimCraft 0.8.1
const ref = (w, reference, station) => ({ wall: w.guid, reference, station: Math.round(station * 1e6) / 1e6 });

Is this dimension already there

64-bit

Compares two references so the same dimension is not made twice.

Two references match when the wall, the reference and the station rounded to four decimals agree. Used only for this comparison; nothing rounded here is saved.

  • autodim.js
  • line 24
  • BimCraft 0.8.1
const key = (r) => r.wall + '|' + r.reference + '|' + Math.round(r.station * 1e4);

Measured segment along an axis

64-bit

Makes one dimension between two points, measured along X or along Y.

The measured segment is made square to the axis by taking one coordinate from the first point. Segments shorter than 20 mm are not dimensioned.

  • autodim.js
  • lines 46 to 53
  • BimCraft 0.8.1
const add = (kind, side, r0, r1, axis, a, end, target) => {
  const b = axis === 'x' ? [end[0], a[1]] : [a[0], end[1]];
  if (Math.hypot(b[0] - a[0], b[1] - a[1]) < 20) return false;
  const spec = { kind, side, refs: [r0, r1], axis, offset: offFor(a, b, target), view, level };
  if (existing.some((d) => same(d, spec) && d.axis === axis) || specs.some((d) => same(d, spec) && d.axis === axis)) return 'dup';
  specs.push(spec);
  return true;
};

Stops along an outside edge

64-bit

The wall ends, opening edges and meeting walls that a row of dimensions runs between.

opening stations = offset ÷ L and (offset + width) ÷ L

A wall is on an edge when both outside-face ends are within T of it, within T ÷ 2 of each other across, and more than 50 mm apart along. Stops closer than 2 mm along the edge are merged, keeping the first in priority order. L is the wall's stored length, or the distance between its ends.

  • autodim.js
  • lines 77 to 93
  • BimCraft 0.8.1
const onEdge = (w) => { const pa = pt(w, REF, 0), pb = pt(w, REF, 1); return pa && pb && Math.abs(pa[cross] - sd.edge) <= T && Math.abs(pb[cross] - sd.edge) <= T && Math.abs(pa[cross] - pb[cross]) <= T / 2 && Math.abs(pa[along] - pb[along]) > 50; };
const edgeWalls = straight.filter(onEdge);
if (!edgeWalls.length) continue;
const stops = [];   // { r (ref), p (point), prio }
const push = (w, reference, station, prio) => { const p = pt(w, reference, station); if (p) stops.push({ r: ref(w, reference, station), p, prio }); };
for (const w of edgeWalls) {
  push(w, REF, 0, 0); push(w, REF, 1, 0);
  if (withOpenings) for (const o of opensOf.get(w.guid) || []) { const L = w.len || Math.hypot(w.b[0] - w.a[0], w.b[1] - w.a[1]); if (L > 0) { push(w, REF, o.offset / L, 1); push(w, REF, (o.offset + o.width) / L, 1); } }
}
// walls that meet this edge: their centre line
for (const w of straight) {
  if (edgeWalls.includes(w)) continue;
  for (const s of [0, 1]) { const q = pt(w, 'center', s); if (q && Math.abs(q[cross] - sd.edge) <= T && Math.abs(pt(w, 'center', 1 - s)[cross] - sd.edge) > 2 * T) push(w, 'center', s, 2); }
}
stops.sort((x, y) => x.p[along] - y.p[along] || x.prio - y.prio);
const keep = [];
for (const s of stops) { if (keep.length && Math.abs(s.p[along] - keep[keep.length - 1].p[along]) < 2) continue; keep.push(s); }

In detail

Method
Extents from the walls' outside-face end points; walls lying on an extent become edge walls; their ends, opening edges and meeting walls' center lines are sorted along the edge and dimensioned between neighbors.
Number types
64-bit numbers.
Tolerances
Edge tolerance T = 1.2 × max(150 mm, thickest wall). Walls shorter than 1 mm ignored; curved when |bulge| > 1e-9. Stops closer than 2 mm merged; segments under 20 mm not dimensioned. Extremes compared with 1e-6 mm. Duplicate test on stations rounded to four decimals.
Limits
Curved walls and walls not square to the plan's axes are left out of the rows. The saved station is rounded to six decimals of the wall's length.

Approach: 64-bit, direct

Every value is a 64-bit number from input to result. Formulas are closed form or a direct solve, and every comparison uses a stated tolerance.

Every policy that takes this approach