Resources Numerical accuracy Calculation policy

Equipment list from drawing tags

Reads the equipment schedule hidden in a foodservice drawing's item tags: one row per item, its quantity and the sheets that show it.

How the precision is kept

Quantities are the numbers typed in the tags, added in 64-bit. Which sheet shows a tag is decided by turning the tag's insertion point into each viewport's own axes and comparing it with the viewport's half width and half height, with no tolerance.

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.

dwg-equipment.js BimCraft 0.8.1 64-bit 3 calculations Reviewed

Tests bin/test-bimcraft.mjs

Viewport windows on the model

64-bit

For each sheet viewport, the half width and half height of the model area it shows.

k = h ÷ viewHeight; half width = w ÷ 2 ÷ k; half height = h ÷ 2 ÷ k

The scale is the viewport's paper height over the model height it shows; a viewport whose scale is not positive is skipped. The cosine and sine of the negative twist are kept for the inside test.

  • dwg-equipment.js
  • lines 38 to 41
  • BimCraft 0.8.1
const k = v.h / v.viewHeight;
if (!(k > 0)) continue;
const hw = v.w / 2 / k, hh = v.h / 2 / k, c = Math.cos(-v.twist), sn = Math.sin(-v.twist);
windows.push({ key: s.key, name: s.name, vx: v.vx, vy: v.vy, hw, hh, c, sn });

Sheets that show a point

64-bit

Which sheets show a given model point.

u = dx·cos − dy·sin, v = dx·sin + dy·cos; inside when |u| ≤ half width and |v| ≤ half height

The offset from the view point is turned into the viewport's axes and compared with the half sizes by exact comparison. A tag exactly on a viewport's edge counts as shown.

  • dwg-equipment.js
  • lines 44 to 52
  • BimCraft 0.8.1
const sheetsAt = (x, y) => {
  const out = [];
  for (const w of windows) {
    const dx = x - w.vx, dy = y - w.vy;
    const u = dx * w.c - dy * w.sn, v = dx * w.sn + dy * w.c;   // into the viewport's own axes
    if (Math.abs(u) <= w.hw && Math.abs(v) <= w.hh && !out.includes(w.key)) out.push(w.key);
  }
  return out;
};

Quantity of a row

64-bit

The scheduled quantity of an item tagged in several places.

qty = Σ tag quantities

Each tag's quantity is read with Number() and the values are added in order. The sum is written with String() and no rounding. If any tag's quantity is empty or not a number, the parts are listed instead of summed.

  • dwg-equipment.js
  • lines 83 to 84
  • BimCraft 0.8.1
const nums = r.qtys.map(Number);
r.qty = r.qtys.length === 1 ? r.qtys[0] : nums.every((n, i) => r.qtys[i] !== '' && Number.isFinite(n)) ? String(nums.reduce((x, y) => x + y, 0)) : r.qtys.filter(Boolean).join(' + ');

In detail

Method
A row's quantity is the sum of its tags' quantities when every one is a number; otherwise the parts are listed joined by plus signs. A tag is on a sheet when its insertion point falls inside one of the sheet's viewport windows.
Number types
64-bit numbers parsed from attribute text.
Limits
The total is written with String() and no rounding, so tag quantities with decimal fractions can show a binary rounding tail (0.1 + 0.2 gives 0.30000000000000004).

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