Resources Numerical accuracy Calculation policy

As-built points compared with the drawing

Brings the drawing's design points and surveyed as-built points to the same units, compares them against a tolerance, and marks and reports the differences.

How the precision is kept

The drawing's points are multiplied by one unit factor (millimeters per drawing unit ÷ 1000 for meters, ÷ 304.8 for feet) and compared in the file's units by layout/layout-points.js comparePoints; as-built points are divided by the same factor to be drawn. Positions stay in 64-bit. The distances written on the labels and in the summary line are rounded with toFixed.

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.

asbuilt.js CadCraft 0.8.2 64-bit 3 calculations Reviewed

Tests bin/test-layout.mjs

Unit factor and tolerance

64-bit

The factor between drawing units and the file's units, and the tolerance the comparison uses.

factor = mm per unit ÷ 1000 (meters), ÷ 304.8 (feet), or 1; default tol = 10 ÷ mm per unit

The factor comes from ptexport.js UNIT_FACTOR: one division by 1000 or by 304.8, both exact definitions. The default tolerance is 10 mm in drawing units, or 0.01 when the drawing's unit is not known; a typed value of zero or less falls back to the default.

  • asbuilt.js
  • lines 35 to 42
  • CadCraft 0.8.2
const per = mmPerDrawingUnit(doc.meta.lunits, doc.meta.units);
const un = kw(await c.keyword(t(per ? 'cmd.exportpoints.units' : 'cmd.exportpoints.units.none'), { options: [opt('D', 'Drawing'), ...(per ? [opt('M', 'Metres'), opt('F', 'Feet')] : [])], default: c.engine.abUnits || 'D' }), 'D');
const factor = UNIT_FACTOR(per, un === 'M' ? 'metres' : un === 'F' ? 'feet' : 'drawing') ?? 1;
const u = activeUcs(doc);
const inUcs = u ? kw(await c.keyword(t('cmd.exportpoints.ucs'), { options: [opt('W', 'World'), opt('U', 'Ucs')], default: 'W' }), 'W') === 'U' : false;
const tolDefault = c.engine.abTol ?? (per ? 10 / per : 0.01);
const tolIn = await c.distance(t('fieldpts.cad.tol'), { default: tolDefault });
const tol = typeof tolIn === 'number' && tolIn > 0 ? tolIn : tolDefault;

Comparison and conversion back to the drawing

64-bit

Compares the two point lists in the file's units and brings as-built points back into drawing coordinates.

compare with tol × factor; drawn point = file point ÷ factor

The tolerance is scaled into the file's units with one multiplication before comparePoints is called. The summary line prints the largest horizontal distance as (maxH ÷ factor).toFixed(3). A point is brought back with one division per coordinate and, in a user coordinate system, ucs.js toWorld; a design point therefore passes × factor and then ÷ factor, which need not return the identical 64-bit number.

  • asbuilt.js
  • lines 49 to 55
  • CadCraft 0.8.2
const design = collectPoints(doc, picked.length ? new Set(picked) : new Set(), { ucs: inUcs ? u : null, factor, start: c.engine.abStart });
const cmp = comparePoints(design, parsed.points, { tol: tol * factor, match: match === 'E' ? 'nearest' : 'number' });
const s = cmp.summary;
c.print(t('fieldpts.read.done', { n: parsed.points.length, file: file.name, format: parsed.format, bad: parsed.badCount }));
c.print(t('fieldpts.cad.summary', { matched: s.matched, ok: s.ok, out: s.out, missing: s.missing, extra: s.extra, max: (s.maxH / factor).toFixed(3) }));
// back into the drawing: file units → drawing units → world
const back = (p) => { const q = { x: p.x / factor, y: p.y / factor }; return inUcs ? ucsToWorld(u, q) : q; };

Marks and labels in the drawing

64-bit

A point at each as-built shot, a line from the design point when it is out of tolerance, and a label with the distance.

label = (dh ÷ factor).toFixed(min(4, max(0, ⌈−log₁₀ tol⌉))); text height = max(1.5 × tol, 0.5 × current text height)

The point and the line are stored at full 64-bit precision. The label is text: the distance is divided by the factor and rounded with toFixed to 0 to 4 decimals depending on the tolerance, so the label shows fewer digits than the stored geometry holds.

  • asbuilt.js
  • lines 58 to 68
  • CadCraft 0.8.2
const h = Math.max(tol * 1.5, (doc.current.textHeight || 2.5) * 0.5);
doc.change('ASBUILT', () => {
  if (!doc.layers.has(AS_BUILT_LAYER)) doc.addLayer({ name: AS_BUILT_LAYER, color: 3, on: true, frozen: false, locked: false, plot: true });
  for (const r of cmp.rows) {
    if (!r.asBuilt) continue;
    const b = back(r.asBuilt);
    const z = Number.isFinite(r.asBuilt.z) ? r.asBuilt.z / factor : 0;
    doc.add({ type: 'point', layer: AS_BUILT_LAYER, color: r.status === 'out' ? 1 : null, x: b.x, y: b.y, z });
    if (r.status === 'out' && r.design) { const d = back(r.design); doc.add({ type: 'line', layer: AS_BUILT_LAYER, color: 1, x1: d.x, y1: d.y, x2: b.x, y2: b.y }); }
    const label = r.status === 'extra' ? (r.built + '  ?') : (r.n + '  ' + (r.dh / factor).toFixed(Math.max(0, Math.min(4, Math.ceil(-Math.log10(tol))))));
    doc.add({ type: 'text', layer: AS_BUILT_LAYER, color: r.status === 'out' ? 1 : null, x: b.x + h * 0.6, y: b.y + h * 0.6, h, rot: 0, s: label, ha: 'left', va: 'baseline', wf: 1 });

In detail

Method
Match by point number or by nearest point, then horizontal distance against the tolerance (the comparison itself is in layout/layout-points.js).
Number types
64-bit numbers for coordinates and distances; label and summary text is rounded.
Tolerances
The tolerance is typed in drawing units. Its default is 10 mm expressed in drawing units (10 ÷ millimeters per unit), or 0.01 when the drawing has no known unit. It is multiplied by the unit factor before the comparison.
Limits
Label text keeps 0 to 4 decimals, chosen from the tolerance as ⌈−log₁₀ tol⌉. The summary's largest distance keeps 3 decimals. The CSV report is written by layout-points.js and is not reviewed here.

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