Resources Numerical accuracy Calculation policy

CabinetCraft room picking and dry-run units

Snaps picked room corners to a grid, decides which way round the picked outline runs, and converts sheet sizes between the job's units and a G-code program's units for the dry run.

How the precision is kept

Picked corners are rounded to a 50 mm or 2 in grid, so the stored outline lies on whole grid values. The dry run converts the job's sheet size and thickness to the program's units through millimeters with the factor 25.4 and its reciprocal. Numbers handed to labels and the maker review are rounded to 2 decimals.

Open item. Skip the unit conversion when the program and the job use the same unit, so the factor is exactly 1.

Calculations under this policy

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

addons/cabinetcraft/main.js CadCraft 0.8.2 64-bit 4 calculations Reviewed

Tests None found by the review

Picked room corner

64-bit

A corner of the room outline picked on the plan, snapped to the grid.

p = round(x ÷ g) × g; g = 50 (mm job) or 2 (inch job)

The corner is rounded to the grid, so its coordinates are whole multiples of 50 or 2, which 64-bit numbers hold exactly. Unless free picking is on, the smaller of the x and y moves from the last corner is set to zero so walls run along x or y. An arc is refused when its sweep is under 0.5 or over 170 in size.

  • addons/cabinetcraft/main.js
  • lines 121 to 136
  • CadCraft 0.8.2
pickPoint(x, y) {
  const g = S.project.unit === 'in' ? 2 : 50;
  let px = Math.round(x / g) * g, py = Math.round(y / g) * g;
  const last = S.pick[S.pick.length - 1];
  if (S.pickArc && last) {   // an arc is three points: where it starts (the last corner), a point on it, where it ends
    if (!S.pickMid) { S.pickMid = [px, py]; render(); return; }
    const a = arcFromThree(last, S.pickMid, [px, py]);
    S.pickMid = null;
    if (!a || Math.abs(a.sweep) < 0.5 || Math.abs(a.sweep) > 170) { say2(t('room.arc.bad')); return; }
    S.pickArcs = [...S.pickArcs, { i: S.pick.length - 1, sweep: a.sweep }];
    S.pick = [...S.pick, [px, py]]; render(); return;
  }
  if (last && !S.pickAny) { if (Math.abs(px - last[0]) >= Math.abs(py - last[1])) py = last[1]; else px = last[0]; if (px === last[0] && py === last[1]) return; }
  else if (last && px === last[0] && py === last[1]) return;
  S.pick = [...S.pick, [px, py]]; render();
},

Direction of the picked outline

64-bit

Whether the corners were picked clockwise, which decides the sign of each arc's sweep.

Σ (xᵢ × yᵢ₊₁ − xᵢ₊₁ × yᵢ) < 0 means clockwise

The shoelace sum is used only for its sign. The corners are grid values, so every product is of whole numbers.

  • addons/cabinetcraft/main.js
  • lines 147 to 148
  • CadCraft 0.8.2
const cw = pts.reduce((s, p, i) => { const q = pts[(i + 1) % pts.length]; return s + (p[0] * q[1] - q[0] * p[1]); }, 0) < 0;
const arcs = S.pickArcs.map((a) => ({ i: a.i, sweep: cw ? -a.sweep : a.sweep }));

Sheet size in the program's units

64-bit

The sheet size, thickness and rapid rate the dry run checks a G-code program against.

k = (1 ÷ 25.4 or 1) × (25.4 or 1); sheet = job sheet × k; rapid (inch program) = rapid ÷ 25.4

One factor converts the job's sheet and thickness to the program's units. With an inch job and an inch program it is (1 ÷ 25.4) × 25.4, which is 0.9999999999999999 in 64-bit, so the sheet handed to the dry run is smaller than the job's by about one part in 10¹⁶.

  • addons/cabinetcraft/main.js
  • lines 160 to 164
  • CadCraft 0.8.2
const toMm = unit === 'in' ? 25.4 : 1;
S.dry = (S.files || []).map((f) => {
  const mat = S.nest && S.nest.mats[f.group];
  const pu = /\bG20\b/.test(f.text) ? 'in' : 'mm', k = (pu === 'in' ? 1 / 25.4 : 1) * toMm;   // the program's units; the sheet and thickness are the job's
  const r = dryRunGcode(f.text, { sheet: mat ? { w: mat.sheet.w * k, h: mat.sheet.h * k } : null, thickness: (f.thickness || 0) * k, unit: pu, rapid: rapid && pu === 'in' ? rapid / 25.4 : rapid });

Numbers on labels and the maker review

64-bit

Writes a number with at most 2 decimals.

text = round(v × 100) ÷ 100

Math.round(v × 100) ÷ 100, then String. This helper is handed to the label sheet, the maker review and the host adapter; it changes only the text, not the job's values.

  • addons/cabinetcraft/main.js
  • line 78
  • CadCraft 0.8.2
const fmt = (v) => String(Math.round(v * 100) / 100);

In detail

Method
Grid snap: round(x ÷ g) × g. Outline direction: the sign of the shoelace sum. Unit factor: (1 ÷ 25.4 for an inch program, else 1) × (25.4 for an inch job, else 1).
Number types
64-bit numbers.
Limits
For an inch job with an inch program the unit factor is (1 ÷ 25.4) × 25.4, which is 0.9999999999999999 in 64-bit, not 1.

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