Resources Numerical accuracy Calculation policy

Cabinets along a wall line

Places cabinets one after another along a wall line picked in the plan, finds which cabinets belong to a front view, and prints areas and lengths of the cut list (Cabinet add-on).

How the precision is kept

Cabinet sizes are kept in rule units (millimeters or inches) and the drawing may use another unit. A typed width is multiplied by the number of rule units per drawing unit, positions are added up in rule units, and each position is multiplied by the reciprocal factor to place the cabinet. All of it is 64-bit arithmetic.

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.

addons/cabinet/main.js CadCraft 0.8.2 64-bit 6 calculations Reviewed

Tests None found by the review

Rule units per drawing unit

64-bit

The factor between the drawing's unit and the cabinet rules' unit, and its reciprocal.

per = meters per drawing unit ÷ (0.0254 or 0.001); k = 1 ÷ per

per comes from core.js as one division of two decimal constants. k is its reciprocal, so per × k is not always exactly 1.

  • addons/cabinet/main.js
  • line 145
  • CadCraft 0.8.2
const doc = c.doc, u = ruleUnitOf(doc), per = perUnit(doc, u), k = 1 / per;

Placing a cabinet on the run

64-bit

The insertion point and rotation of a new cabinet, and where the next one starts.

w = typed × per; x = runₓ + cos(ang)·pos·k; y = runᵧ + sin(ang)·pos·k; next pos = pos + w

Positions add up in rule units, one addition per cabinet, and each is converted to drawing units once when the cabinet is placed, so the conversion error does not build up along the run. The warning for running past the wall uses 1e-6 rule units, absolute.

  • addons/cabinet/main.js
  • lines 193 to 202
  • CadCraft 0.8.2
const w = Number(r) * per;
if (!(w > 0)) continue;
const cab = cleanCabinet({ type, w, h: S.h, d: S.d, no: nextNo(doc, type) }, R);
const bad = problems(cab, R);
if (bad.some((p) => p.code === 'too-narrow' || p.code === 'no-size')) { c.print(t('prob.' + bad[0].code, fmtVars(bad[0].vars, u))); continue; }
if (pos + w > runLen + 1e-6) c.print(t('warn.past', { len: fmtLen(runLen, u) }));
const data = { u, k, cab, rules: ruleDiff(R) };
let e;
doc.change('CABINET', () => {
  e = doc.add({ ...api.objects.create('cab', data, { layer: LAYER_OF[type] }), x: run.x + Math.cos(run.ang) * pos * k, y: run.y + Math.sin(run.ang) * pos * k, rot: run.ang });

Cabinets of a front view

64-bit

Which cabinets stand on a wall line and how far along it, for the front view.

on the run when |sin(rot − ang)| ≤ 1e-6, cos(rot − ang) ≥ 0 and |offset| ≤ 0.5 × depth × k; x = s ÷ k − smallest x, rounded to 6 decimals

The distance along the run is a dot product with the run's direction, divided by k. Positions are measured from the first cabinet and rounded to 6 decimals of the rule unit before they are stored with the front view.

  • addons/cabinet/main.js
  • lines 110 to 123
  • CadCraft 0.8.2
// ---------------------------------------------------------------------------------------------- the front view of a wall line
function elevItems(doc, run) {
  const items = [];
  for (const { e, d } of readCabs(doc)) {
    const rot = e.rot || 0;
    if (Math.abs(Math.sin(rot - run.ang)) > 1e-6 || Math.cos(rot - run.ang) < 0 || (e.sx ?? 1) < 0 || (e.sy ?? 1) < 0) continue;
    const a = along(run, { x: e.x, y: e.y });
    if (Math.abs(a.off) > 0.5 * d.cab.d * d.k) continue;
    items.push({ u: d.u, k: d.k, cab: d.cab, rules: d.rules, x: a.s / d.k });
  }
  const min = items.length ? Math.min(...items.map((i) => i.x)) : 0;
  for (const i of items) i.x = Math.round((i.x - min) * 1e6) / 1e6;
  return items.sort((a, b) => a.x - b.x || a.cab.elev - b.cab.elev);
}

Area as text

64-bit

The area of a material group on the command line.

in² ÷ 144 = ft²; mm² ÷ 1e6 = m²; 3 decimals

144 and 1e6 are exact factors. The text has at most 3 decimals with trailing zeros removed; the value itself is not changed.

  • addons/cabinet/main.js
  • line 369
  • CadCraft 0.8.2
const fmtArea = (a, u) => (u === 'in' ? fmtLen(a / 144, 'in') + ' ' + t('unit.sqft') : fmtLen(a / 1e6, 'in') + ' ' + t('unit.m2'));

Edge banding length as text

64-bit

The length of edge banding on the command line.

in ÷ 12 = ft; mm ÷ 1000 = m; 3 decimals

12 and 1000 are exact factors. The text has at most 3 decimals with trailing zeros removed.

  • addons/cabinet/main.js
  • line 370
  • CadCraft 0.8.2
const fmtRun = (v, u) => (u === 'in' ? fmtLen(v / 12, 'in') + ' ' + t('unit.ft') : fmtLen(v / 1000, 'in') + ' ' + t('unit.m'));

Sheet use in percent

64-bit

The share of each material's sheets covered by parts, as printed after nesting.

percent = round(efficiency × 100)

Rounded to a whole percent for the printed line only; the efficiency itself comes from the nesting job.

  • addons/cabinet/main.js
  • line 363
  • CadCraft 0.8.2
for (const m of N.job.efficiency) c.print('  ' + t('nest.mat', { mat: m.material, sheets: m.sheets, pct: Math.round(m.efficiency * 100) }));

In detail

Method
Position along the run = sum of the widths before it; point = run start + direction × position × k.
Number types
64-bit numbers.
Tolerances
A cabinet belongs to a run when |sin(angle difference)| ≤ 1e-6 and it lies within half its depth of the line. A run is past its end when position + width > length + 1e-6. Positions in a front view are rounded to 6 decimals.
Limits
k is formed as 1 ÷ per and multiplied in, so a width typed in drawing units and converted back can differ from the typed value in the last bit.

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