Resources Numerical accuracy Calculation policy

Cabinet shop drawings as drawing objects

Turns the cabinet plan, elevations, sections, schedule, cut list and nested sheets into lines, polylines, texts, hatches and dimensions of the open drawing (CabinetCraft add-on).

How the precision is kept

Every coordinate is rounded to 4 decimals by r4: once in the job's unit, again after scaling to the drawing's unit, and again when a sheet is moved to its place. The rounding is a fixed number of decimals of whatever unit the drawing uses, so its size in millimeters depends on that unit. Dimensions are added as real dimension objects on the rounded points with no text override.

Open item. Do not round after scaling to the drawing's unit, or round to a number of significant digits, so a drawing in meters is not limited to 0.1 mm.

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/cabinetcraft/lib/cadents.js CadCraft 0.8.2 64-bit 6 calculations Reviewed

Tests None found by the review

Rounding to 4 decimals

64-bit

Rounds a coordinate to 4 decimals.

r4(v) = round(v × 1e4) ÷ 1e4

Applied to every coordinate, text height and dimension scale this file produces. The rounding is absolute: 1e-4 of the unit in use.

  • addons/cabinetcraft/lib/cadents.js
  • line 21
  • CadCraft 0.8.2
const r4 = (v) => Math.round(v * 1e4) / 1e4;

Drawing item to drawing object

64-bit

A line, outline or text of a shop drawing as a CadCraft object.

x, y, text height → r4; text rotation = degrees × π ÷ 180

Coordinates are rounded to 4 decimals of the job's unit (mm or in) here. A filled outline also becomes a hatch with the same rounded points.

  • addons/cabinetcraft/lib/cadents.js
  • lines 24 to 39
  • CadCraft 0.8.2
/** One drawing-list entity → the CadCraft entities it becomes (a fill adds a hatch under the outline). */
export function toCad(e, { layer = null } = {}) {
  const out = [];
  if (e.dimPart) return out;   // dimensions are real dimension entities (below), not the lines and text that draw them in the SVG
  const L = (def) => layer || def;
  if (e.type === 'line') out.push({ type: 'line', layer: L(e.dash ? 'CC-HIDDEN' : e.heavy ? 'CC-ROOM' : e.thin ? 'CC-SHEET' : 'CC-BASE'), x1: r4(e.x1), y1: r4(e.y1), x2: r4(e.x2), y2: r4(e.y2) });
  else if (e.type === 'poly') {
    const pts = e.pts.map((p) => ({ x: r4(p.x), y: r4(p.y) }));
    const counter = e.color === '#8a6d3b';
    const lyr = L(counter ? 'CC-COUNTER' : e.dash ? 'CC-HIDDEN' : e.heavy ? 'CC-ROOM' : e.thin ? 'CC-SHEET' : 'CC-BASE');
    if (e.closed && e.fill && e.fill !== 'none' && pts.length >= 3) out.push({ type: 'hatch', layer: 'CC-FILL', loops: [pts.flatMap((p) => [p.x, p.y])], solid: true, color: e.fill });
    if (e.closed && counter && pts.length >= 3) out.push({ type: 'hatch', layer: 'CC-COUNTER', loops: [pts.flatMap((p) => [p.x, p.y])], solid: false, pattern: 'ANSI31', pscale: 1, pangle: 0 });
    out.push({ type: 'poly', layer: lyr, pts, closed: !!e.closed });
  } else if (e.type === 'text') out.push({ type: 'text', layer: layer || 'CC-TEXT', x: r4(e.x), y: r4(e.y), h: r4(e.h), rot: rad(e.rot || 0), s: String(e.s), ha: e.ha || 'center', va: e.va || 'middle' });
  return out;
}

Dimensions

64-bit

The linear dimensions of a shop drawing as dimension objects.

p₁, p₂ → r4; line position = p + offset → r4; dimension scale = max(0.01, text height ÷ 2.5) → r4

The dimension is given its two rounded points and an empty text, which leaves its value to be measured between those points.

  • addons/cabinetcraft/lib/cadents.js
  • lines 41 to 52
  • CadCraft 0.8.2
/** The dimension parts of a drawing list as real linear dimensions (once each). */
export function dimsOf(ents) {
  const seen = new Set(), out = [];
  for (const e of ents) {
    const d = e.dimPart;
    if (!d || seen.has(d)) continue;
    seen.add(d);
    if (d.vertical) out.push({ type: 'dim', kind: 'linear', layer: 'CC-DIM', p1: { x: r4(d.x1), y: r4(d.y1) }, p2: { x: r4(d.x2), y: r4(d.y2) }, loc: { x: r4(d.x1 + d.off), y: r4((d.y1 + d.y2) / 2) }, rot: Math.PI / 2, text: '', st: { scale: r4(Math.max(0.01, d.th / 2.5)) } });
    else out.push({ type: 'dim', kind: 'linear', layer: 'CC-DIM', p1: { x: r4(d.x1), y: r4(d.y1) }, p2: { x: r4(d.x2), y: r4(d.y2) }, loc: { x: r4((d.x1 + d.x2) / 2), y: r4(d.y1 + d.off) }, rot: 0, text: '', st: { scale: r4(Math.max(0.01, d.th / 2.5)) } });
  }
  return out;
}

Scaling to the drawing's unit

64-bit

Every coordinate, text height and dimension scale multiplied by the drawing units per job unit.

v → r4(v × k)

Each value is multiplied by k and rounded to 4 decimals of the drawing's unit. With a millimeter job in a meter drawing k is 0.001 and the result is rounded to 0.0001 m, which is 0.1 mm.

  • addons/cabinetcraft/lib/cadents.js
  • lines 68 to 83
  • CadCraft 0.8.2
/** Everything in the result multiplied by k (drawing units per millimetre-or-inch of the job): coordinates, text heights, the dimensions' text size. */
export function scaleEnts(ents, k) {
  const sc = (v) => r4(v * k);
  const P = (p) => ({ ...p, x: sc(p.x), y: sc(p.y) });
  return ents.map((e) => {
    switch (e.type) {
      case 'line': return { ...e, x1: sc(e.x1), y1: sc(e.y1), x2: sc(e.x2), y2: sc(e.y2) };
      case 'poly': return { ...e, pts: e.pts.map(P) };
      case 'text': return { ...e, x: sc(e.x), y: sc(e.y), h: sc(e.h) };
      case 'insert': return { ...e, x: sc(e.x), y: sc(e.y) };
      case 'hatch': return { ...e, loops: e.loops.map((l) => l.map(sc)), ...(e.pscale ? { pscale: e.pscale * k } : {}) };
      case 'dim': return { ...e, p1: P(e.p1), p2: P(e.p2), loc: P(e.loc), st: { ...(e.st || {}), scale: r4(((e.st && e.st.scale) || 1) * k) } };
      default: return e;
    }
  });
}

Scaling all sheets

64-bit

All blocks and sheets scaled to the drawing's unit.

k = 1 → unchanged; else every block and sheet through scaleEnts, sheet w and h × k

When the job's unit and the drawing's unit agree (k exactly 1) nothing is rescaled or rounded again. Sheet widths and heights are multiplied without rounding.

  • addons/cabinetcraft/lib/cadents.js
  • lines 84 to 87
  • CadCraft 0.8.2
export function scaleSheets(res, k) {
  if (k === 1) return res;
  return { ...res, blocks: res.blocks.map((b) => ({ ...b, entities: scaleEnts(b.entities, k) })), sheets: res.sheets.map((s) => ({ ...s, w: s.w * k, h: s.h * k, entities: scaleEnts(s.entities, k) })) };
}

Moving a sheet into place

64-bit

The objects of a sheet moved by an offset.

x → r4(x + dx); y → r4(y + dy)

One addition per coordinate, rounded to 4 decimals again. The offset itself is not rounded first, so two objects that shared a point still share it after the move.

  • addons/cabinetcraft/lib/cadents.js
  • lines 54 to 66
  • CadCraft 0.8.2
export function place(ents, dx, dy) {
  const mv = (p) => ({ ...p, x: r4(p.x + dx), y: r4(p.y + dy) });
  return ents.map((e) => {
    switch (e.type) {
      case 'line': return { ...e, x1: r4(e.x1 + dx), y1: r4(e.y1 + dy), x2: r4(e.x2 + dx), y2: r4(e.y2 + dy) };
      case 'poly': return { ...e, pts: e.pts.map(mv) };
      case 'text': case 'insert': case 'point': return mv(e);
      case 'hatch': return { ...e, loops: e.loops.map((l) => l.map((v, i) => r4(v + (i % 2 ? dy : dx)))) };
      case 'dim': return { ...e, p1: mv(e.p1), p2: mv(e.p2), loc: mv(e.loc) };
      default: return e;
    }
  });
}

In detail

Method
Copy each drawing-list item to a drawing object; multiply by the unit factor; translate.
Number types
64-bit numbers, rounded to 4 decimals.
Tolerances
r4 = round(v × 1e4) ÷ 1e4, absolute in the current unit.
Limits
In a drawing whose unit is the meter, 4 decimals is 0.1 mm; in feet about 0.03 mm; in inches 0.0025 mm; in millimeters 0.0001 mm.

Approach: 64-bit, stated limit

The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.

Every policy that takes this approach