Resources Numerical accuracy Calculation policy

Cabinet run layout and countertops

Places every cabinet, filler and end panel along its wall or island, works out how runs meet at corners, and sizes the countertops.

How the precision is kept

Positions along a run are running sums of cabinet widths in 64-bit numbers; each stored position is rounded to 6 decimals of the job unit (r6, core.js). Fits are decided with an absolute tolerance of 0.01 job units. On curved walls a filler width and a corner shift are found by bisection with a fixed number of halvings, and the room a curve takes at a corner uses the first term s² ÷ 2r. Footprint overlap is a separating-axis test with an absolute 1e-6 threshold.

Open item. Scale the 0.01 layout tolerance to the job unit, so an inch job does not use a tolerance 25.4 times larger than a millimeter job.

Calculations under this policy

19 calculations in 2 source files. 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/project.js CadCraft 0.8.2 64-bit 14 calculations Reviewed

Tests None found by the review

Island frames

64-bit

The origin and axes of each island's front row and back row.

u = (cos a, sin a), a = rot × π ÷ 180; back row origin = o + u × len

The cosine and sine are rounded to 6 decimals. cleanIslands in the same file only allows rot of 0, 90, 180 or 270, so the rounded axes are exactly 0 or ±1. The back row's origin is rounded to 6 decimals.

  • addons/cabinetcraft/lib/project.js
  • lines 171 to 189
  • CadCraft 0.8.2
/** The islands as runs of their own: the front row faces the island's left, a back row (if it has items) faces the other way from the far end. */
export function islandRuns(p) {
  const out = [];
  for (const isl of p.islands || []) {
    const a = (isl.rot * Math.PI) / 180;
    const u = { x: r6(Math.cos(a)), y: r6(Math.sin(a)) }, n = { x: r6(-u.y), y: r6(u.x) };
    const o = { x: isl.x, y: isl.y };
    const mk = (id, items, frame, attach, ep) => ({
      run: { id, name: isl.name, wall: null, island: isl.id, from: 0, to: isl.len, autoFiller: isl.autoFiller, endPanels: ep, base: items, upper: [], attach, seat: isl.seat, kind: isl.kind },
      wall: null, frame, len: isl.len, rows: {}, closedStart: attach.start, closedEnd: attach.end, island: isl,
    });
    out.push(mk(isl.id, isl.base, { o, u, n, ang: a }, isl.attach, isl.endPanels));
    if (isl.back.length) {
      const o2 = { x: r6(o.x + u.x * isl.len), y: r6(o.y + u.y * isl.len) };
      out.push(mk(isl.id + 'b', isl.back, { o: o2, u: { x: -u.x, y: -u.y }, n: { x: -n.x, y: -n.y }, ang: a + Math.PI }, { start: isl.attach.end, end: isl.attach.start }, { start: isl.endPanels.end, end: isl.endPanels.start }));
    }
  }
  return out;
}

Layout tolerance and largest automatic filler

64-bit

The two limits the layout compares against.

tol = 0.01; maxFiller = conv(75, unit)

tol is 0.01 in job units whatever the unit. conv (core.js) rounds 75 ÷ 25.4 to the nearest 1/16, so in an inch job the largest automatic filler is 2.9375 in, which is 74.6125 mm.

  • addons/cabinetcraft/lib/project.js
  • lines 210 to 211
  • CadCraft 0.8.2
const tol = 0.01;
const maxFiller = conv(75, unit);

End-face swing of a cabinet on a bay

64-bit

How far the end face of a straight cabinet on a curved bay swings toward the neighboring run.

tilt = d × sin(atan2(w ÷ 2, √(r² − w² ÷ 4)))

The expression equals d × w ÷ (2r); it is written with a square root, atan2 and sin, each of which rounds once. The square root's argument is kept at 0 or above, and a cabinet as wide as the arc's diameter returns 0.

  • addons/cabinetcraft/lib/project.js
  • lines 243 to 250
  • CadCraft 0.8.2
const arcTilt = (L, row, which) => {
  const g = L.wallInfo && L.wallInfo.arc;
  if (!g || !g.bay || L.island) return 0;
  const cells = L.rows[row].cells, c = which === 'start' ? cells[0] : cells[cells.length - 1];
  if (!c || (c.tpl && c.tpl.curved) || !(c.w < 2 * g.r)) return 0;
  const d = c.kind === 'cab' ? (depthOf ? depthOf(c) : c.cab.d) : L.rows[row].depth || 0;
  return d * Math.sin(Math.atan2(c.w / 2, Math.sqrt(Math.max(0, g.r * g.r - (c.w * c.w) / 4))));
};

Is a corner a right angle

64-bit

Decides whether a corner cabinet fits a room corner.

square when |turn − 90| < 0.01 degrees

A turn within 0.01 degrees of 90 is treated as exactly square. The turn itself was rounded to 6 decimals of a degree in room.js.

  • addons/cabinetcraft/lib/project.js
  • lines 256 to 262
  • CadCraft 0.8.2
const fits = (cell, tau, other, own) => {
  if (own.arc || (other && other.arc)) return 'arc';
  if (Math.abs(tau - 90) < 0.01) return null;
  if (cell.turn !== 'diag') return 'angle';
  const dg = diagAt(tau, cell.w, cell.cab.d);
  return dg.valid ? null : 'size';
};

Where the later run stops at a corner

64-bit

How far short of a room corner a run stops so it clears the run on the other wall.

stop = flat + tilt(A) + tilt(B) + flat² ÷ (2r); flat = other run's depth at 90°

On an arc wall the bend term q² ÷ 2r is the first term of the distance a circle leaves its tangent, not the exact value r − √(r² − q²). The sum is not rounded. A wedge is recorded when the corner is not square or the stop exceeds the depth by more than 1e-6.

  • addons/cabinetcraft/lib/project.js
  • lines 291 to 297
  • CadCraft 0.8.2
const later = ib > ia;
const dOther = later ? a.depth : b.depth;
const flat = square ? dOther : cornerBlock(tau, dOther);
const bend = (L, q) => (L.wallInfo.arc && !L.island ? (q * q) / (2 * L.wallInfo.arc.r) : 0);   // the curve leaves the tangent line by s^2 / 2r over a stretch s
const stop = flat + arcTilt(A, row, 'end') + arcTilt(B, row, 'start') + bend(A, flat);
if (later) b.blocked.start = Math.max(b.blocked.start, stop); else a.blocked.end = Math.max(a.blocked.end, stop);
if (!square || stop > dOther + 1e-6) {

Wedge filler triangle at an angled corner

64-bit

The three corners of the triangular void left where two runs meet at an angle that is not 90 degrees.

tri = [corner, corner ± u × leg1, corner + n × depth]

The legs and area come from wedgeCorner in angled.js. The triangle's points are the room corner plus a wall direction times a length; the directions are the wall frames' 6-decimal unit vectors. A wedge with a leg of 1 job unit or less is not recorded.

  • addons/cabinetcraft/lib/project.js
  • lines 300 to 309
  • CadCraft 0.8.2
const wc = wedgeCorner(tau, dOther);
if (wc && wc.leg1 > 1 && wc.leg2 > 1) {
  const Pc = A.wallInfo.b;
  const uA = A.wallInfo.t1, nA = { x: -uA.y, y: uA.x }, uB = B.wallInfo.t0, nB = { x: -uB.y, y: uB.x };
  const tri = later
    ? [[Pc.x, Pc.y], [Pc.x + uB.x * wc.leg1, Pc.y + uB.y * wc.leg1], [Pc.x + nA.x * dOther, Pc.y + nA.y * dOther]]
    : [[Pc.x, Pc.y], [Pc.x - uA.x * wc.leg1, Pc.y - uA.y * wc.leg1], [Pc.x + nB.x * dOther, Pc.y + nB.y * dOther]];
  const hostRun = later ? A : B;
  const hc = hostRun.rows[row].cells.filter((x) => x.kind === 'cab').pop();
  wedges.push({ row, from: A.run.id, to: B.run.id, tau: r6(tau), depth: dOther, leg1: wc.leg1, leg2: wc.leg2, area: wc.area, tri, hostCab: hc || null });

Automatic filler width

64-bit

The width of the filler that closes the gap between the last cabinet and the end of the span.

rest = end − start − used; filler = rest when tol < rest ≤ maxFiller

On a straight wall the filler is the remaining length, rounded to 6 decimals. On a curved wall, when that width does not fit, 30 halvings find the widest one that does; the result is the lower bound of the last interval. A width under 0.01 becomes no filler.

  • addons/cabinetcraft/lib/project.js
  • lines 336 to 351
  • CadCraft 0.8.2
let used = sumW(L, row, ordered) + (tail ? R.frontT : 0);
let rest = rw.end - rw.start - used;
if (cells.length && L.run.autoFiller && rest > tol && rest <= maxFiller) {
  let wf = rest;
  if (L.wallInfo && L.wallInfo.arc && !L.island) {   // on a curve a filler also adds the wedge on either side of it: take the widest one that still fits the span
    const span = rw.end - rw.start - (tail ? R.frontT : 0);
    const fits = (v) => sumW(L, row, [...ordered, { kind: 'filler', w: v, depth: 0 }]) <= span + tol;
    if (!fits(wf)) { let lo = 0, hi = wf; for (let k = 0; k < 30; k++) { const mid = (lo + hi) / 2; if (fits(mid)) lo = mid; else hi = mid; } wf = lo; }
  }
  if (wf < tol) wf = 0;
  const f = wf > 0 ? { kind: 'filler', w: r6(wf), auto: true, row, height: fillerHeight(ordered, R), depth: 0 } : null;
  if (!f) { /* no room for a filler on this curve */ } else {
  if (rw.cornerEnd) ordered.splice(ordered.length - 1, 0, f); else ordered.push(f);   // beside a corner cabinet the filler goes before it
  used += f.w; rest = r6(rest - f.w);
  }
}

Position of each cell along its run

64-bit

The distance from the start of the wall to each cabinet, filler and end panel.

xᵢ₊₁ = xᵢ + wᵢ; stored xᵢ rounded to 6 decimals

The running sum x is kept unrounded and each stored position is a rounded copy, so the rounding does not build up along the run. A corner cabinet at the end of a run is set at end − width.

  • addons/cabinetcraft/lib/project.js
  • lines 353 to 356
  • CadCraft 0.8.2
let x = rw.start;
for (const c of ordered) {
  if (c === rw.cornerEnd) x = Math.max(x, rw.end - c.w);   // the corner cabinet sits IN the corner, whatever is left over is before it
  c.x = r6(x); x += c.w;

First cabinet on a curve moved clear of the previous run

64-bit

On a curved wall that starts at a room corner, how far the first cabinet is moved along so it does not overlap the previous run's last cabinet.

bisection on [0, 600 mm], 40 halvings; clash when overlap > 1e-6

The search runs only when the cabinet clashes at 0 and is clear at conv(600), which is 23.625 in an inch job. After 40 halvings the interval is 600 ÷ 2⁴⁰ wide and the upper, clear end is taken. The stored shift is rounded to 6 decimals.

  • addons/cabinetcraft/lib/project.js
  • lines 385 to 389
  • CadCraft 0.8.2
if (clashes(0)) {
  let lo = 0, hi = conv(600, unit);
  if (!clashes(hi)) { for (let k = 0; k < 40; k++) { const mid = (lo + hi) / 2; if (clashes(mid)) lo = mid; else hi = mid; } shift = hi; }
}
if (shift > 0) { st = stepArc(g, items, { from: rw.start + shift, to: rw.end }); rw.arcShift = r6(shift); }

Straight countertop length and width

64-bit

The length and width of a countertop over a straight run of base cabinets.

length = x₁ − x₀ + overhang at each open end; width = depth + front overhang + seat

Differences and sums of stored positions and the counter settings, rounded to 6 decimals. The depth is the largest cabinet depth in the run.

  • addons/cabinetcraft/lib/project.js
  • line 437
  • CadCraft 0.8.2
cs.push({ run: L.run.id, wall: L.wall, x0: r6(x0 - ov(ends.start)), x1: r6(x1 + ov(ends.end)), y0: r6(-seat), depth, cabs: seg.length, ids: seg.map((c) => c.no), ends, length: r6(x1 - x0 + ov(ends.start) + ov(ends.end)), width: r6(depth + p.counter.front + seat) });

Countertop on a curved wall

64-bit

The outline and area of a one-piece countertop that follows cabinets stepped along a curved wall.

area = |Σ (xᵢ yᵢ₊₁ − xᵢ₊₁ yᵢ)| ÷ 2

The outline's points are rounded to 6 decimals before the shoelace sum. The sum uses room coordinates, not coordinates relative to the piece, so far from the origin the products are large next to their difference. The reported length is the sum of the cabinet widths, not a length along the outline.

  • addons/cabinetcraft/lib/project.js
  • lines 429 to 434
  • CadCraft 0.8.2
const back = run.flatMap((c) => [c.arcCorners.bl, c.arcCorners.br]);
const fr = run.map((c) => { const d = c.kind === 'cab' ? (depthOf ? depthOf(c) : c.cab.d) : (L.rows.base.depth || 0); const n = c.pf.n, u = c.pf.u; return [ { x: c.pf.o.x + n.x * (d + f), y: c.pf.o.y + n.y * (d + f) }, { x: c.pf.o.x + u.x * c.w + n.x * (d + f), y: c.pf.o.y + u.y * c.w + n.y * (d + f) } ]; });
const poly = [...back, ...fr.slice().reverse().flatMap(([l, r]) => [r, l])].map((q) => [r6(q.x), r6(q.y)]);
const area = Math.abs(poly.reduce((q, pt, k) => { const nx = poly[(k + 1) % poly.length]; return q + pt[0] * nx[1] - nx[0] * pt[1]; }, 0)) / 2;
const xs = poly.map((q) => q[0]), ys = poly.map((q) => q[1]);
cs.push({ run: L.run.id, wall: L.wall, world: true, poly, x0: Math.min(...xs), x1: Math.max(...xs), y0: Math.min(...ys), y1: Math.max(...ys), depth, cabs: seg.length, ids: seg.map((c) => c.no), ends, length: r6(run.reduce((q, c) => q + c.w, 0)), width: r6(depth + f), area: r6(area) });

Corner cabinet countertop

64-bit

The outline and area of the countertop over a corner cabinet.

area = shoelace of the outline; length = width = √area

The diagonal form pushes the front out by f × √2 using Math.SQRT2. The outline is rounded to 6 decimals, then the area is a shoelace sum. The length and width stored for the piece are both √area, not measured sides.

  • addons/cabinetcraft/lib/project.js
  • lines 443 to 454
  • CadCraft 0.8.2
const d = depthOf ? depthOf(c) : c.cab.d, f = p.counter.front, w = c.cab.w, a = w - d;
let pts = c.turn === 'l' ? [[0, 0], [w, 0], [w, w], [a - f, w], [a - f, d + f], [0, d + f]] : [[0, 0], [w, 0], [w, w], [a - f * Math.SQRT2, w], [0, d + f * Math.SQRT2]];
if (c.turn === 'diag' && c.tau && Math.abs(c.tau - 90) >= 0.01) {   // at another angle: the outline of diagAt with its front pushed out by the overhang
  const dg = diagAt(c.tau, w, d), dx = dg.FB[0] - dg.FA[0], dy = dg.FB[1] - dg.FA[1], ln = Math.hypot(dx, dy) || 1, nx = dy / ln, ny = -dx / ln;   // the front's normal away from the corner
  const sgn = (nx * (dg.Q[0] - dg.FA[0]) + ny * (dg.Q[1] - dg.FA[1])) > 0 ? -1 : 1;
  pts = [[0, 0], dg.P1, dg.P2, [dg.FB[0] + sgn * nx * f, dg.FB[1] + sgn * ny * f], [dg.FA[0] + sgn * nx * f, dg.FA[1] + sgn * ny * f]];
}
if (c.corner === 'start') pts = pts.map(([x, y]) => [w - x, y]).reverse();
pts = pts.map(([x, y]) => [r6(c.x + x), r6(y)]);
const area = Math.abs(pts.reduce((q, pt, i) => { const n = pts[(i + 1) % pts.length]; return q + pt[0] * n[1] - n[0] * pt[1]; }, 0)) / 2;
const xs = pts.map((q) => q[0]), ys = pts.map((q) => q[1]), side = Math.sqrt(area);
cs.push({ run: L.run.id, wall: L.wall, corner: c.turn, cab: c.no, poly: pts, x0: Math.min(...xs), x1: Math.max(...xs), y0: Math.min(...ys), y1: Math.max(...ys), depth: d, cabs: 1, ids: [c.no], ends: { start: 'wall', end: 'wall' }, length: r6(side), width: r6(side), area: r6(area) });

Extent of a cell along its wall

64-bit

The stretch of wall each cell covers, used to test it against doors and windows.

curved wall: min and max of (corner − a)·u; straight: [x, x + w]

On a curved wall the four corners are projected on the chord with the wall's 6-decimal direction, and the result is rounded to 6 decimals.

  • addons/cabinetcraft/lib/project.js
  • lines 461 to 463
  • CadCraft 0.8.2
  const a = L.wallInfo.a, u = L.wallInfo.frame.u, qs = Object.values(c.arcCorners).map((q) => (q.x - a.x) * u.x + (q.y - a.y) * u.y);
  c.ext = [r6(Math.min(...qs)), r6(Math.max(...qs))];
} else c.ext = [c.x, r6(c.x + c.w)];

End panel height

64-bit

The height of an end panel beside a cabinet.

height = cabinet height − kick height

One subtraction, rounded to 6 decimals. Wall cabinets and jobs without a kick subtract 0.

  • addons/cabinetcraft/lib/project.js
  • lines 469 to 473
  • CadCraft 0.8.2
function panelHeight(cell, R) {
  if (!cell || cell.kind !== 'cab') return 0;
  const kick = cell.cab.type === 'wall' || R.kick === 'none' ? 0 : R.kickH;
  return r6(cell.cab.h - kick);
}
addons/cabinetcraft/lib/footprint.js CadCraft 0.8.2 64-bit 5 calculations Reviewed

Tests None found by the review

Wall frame to room coordinates

64-bit

Turns a distance along a wall and a distance out from it into a room point.

p = o + u × s + n × o′

Two products and two additions per coordinate, then rounded to 6 decimals. The frame's u and n were already rounded to 6 decimals in room.js.

  • addons/cabinetcraft/lib/footprint.js
  • line 12
  • CadCraft 0.8.2
export const toWorld = (frame, s, o) => ({ x: r6(frame.o.x + frame.u.x * s + frame.n.x * o), y: r6(frame.o.y + frame.u.y * s + frame.n.y * o) });

Floor footprint of each cell

64-bit

The polygon each cabinet and end panel covers on the floor, its bounding box and its height range.

Rectangles are built in the cell's frame and moved to room coordinates by toWorld, so their corners carry its 6-decimal rounding. The bounding box is the minimum and maximum of those corners. z₁ = elevation + height is not rounded.

  • addons/cabinetcraft/lib/footprint.js
  • lines 18 to 45
  • CadCraft 0.8.2
export function footprints(build) {
  const { layout, R, F, project } = build;
  const out = [];
  const byNo = new Map(build.cells.map((c) => [c.no, c]));
  for (const L of layout.runs) for (const row of ['base', 'upper']) for (const c of L.rows[row].cells) {
    if (c.kind === 'gap' || c.kind === 'filler') continue;
    let local;
    let z0 = 0, z1 = 0;
    if (c.kind === 'endpanel') { const sx = c.pf ? 0 : c.x; local = [[[sx, 0], [sx + c.w, 0], [sx + c.w, c.depth], [sx, c.depth]]]; z1 = c.height; }
    else {
      const b = byNo.get(c.no);
      const sx = c.pf ? 0 : c.x;
      if (c.curved) local = null;
      else if (b && b.corner) local = b.corner.footprint.map((poly) => poly.map(([x, y]) => [sx + x, y]));
      else {
        const depth = c.cab.d;   // the carcass (and frame): doors stand a few mm proud at a corner, which is what a filler is for
        local = [[[sx, 0], [sx + c.w, 0], [sx + c.w, depth], [sx, depth]]];
      }
      z0 = c.cab.elev || 0; z1 = z0 + c.cab.h;
    }
    const fr = c.pf || L.frame;
    const pieces = local ? local.map((poly) => poly.map(([s, o]) => { const p = toWorld(fr, s, o); return [p.x, p.y]; })) : c.curved.slices;   // a curved-front cabinet: its ring sector in convex slices
    const xs = pieces.flat().map((p) => p[0]), ys = pieces.flat().map((p) => p[1]);
    out.push({ no: c.no, run: L.run.id, island: L.island ? L.island.id : null, row, kind: c.kind, cell: c, pieces, bbox: [Math.min(...xs), Math.min(...ys), Math.max(...xs), Math.max(...ys)], z0, z1 });
  }
  void F; void project;
  return out;
}

How far two footprints overlap

64-bit

The penetration depth of two convex polygons, 0 when they are apart or only touch.

for each edge normal n: overlap = min(a₁, b₁) − max(a₀, b₀) of the projections; result = smallest overlap

Separating-axis test with each normal divided by its length from Math.hypot. An overlap of 1e-6 or less on any axis counts as not overlapping, an absolute value in job units. Edges shorter than 1e-9 are skipped.

  • addons/cabinetcraft/lib/footprint.js
  • lines 47 to 63
  • CadCraft 0.8.2
/** Penetration depth of two convex polygons (separating axis test); 0 when they only touch or are apart. */
export function overlap(A, B) {
  let best = Infinity;
  for (const poly of [A, B]) {
    for (let i = 0; i < poly.length; i++) {
      const p = poly[i], q = poly[(i + 1) % poly.length];
      const nx = q[1] - p[1], ny = p[0] - q[0], len = Math.hypot(nx, ny);
      if (len < 1e-9) continue;
      const proj = (P) => { let lo = Infinity, hi = -Infinity; for (const [x, y] of P) { const v = (x * nx + y * ny) / len; if (v < lo) lo = v; if (v > hi) hi = v; } return [lo, hi]; };
      const [a0, a1] = proj(A), [b0, b1] = proj(B);
      const o = Math.min(a1, b1) - Math.max(a0, b0);
      if (o <= 1e-6) return 0;
      if (o < best) best = o;
    }
  }
  return Number.isFinite(best) ? best : 0;
}

Gap between two rectangles

64-bit

The distance between two axis-aligned rectangles.

gap = √(dx² + dy²), dx and dy the clear distances on each axis, 0 when they overlap on it

Two subtractions per axis and one Math.hypot; nothing is rounded.

  • addons/cabinetcraft/lib/footprint.js
  • lines 65 to 68
  • CadCraft 0.8.2
export function rectGap([ax0, ay0, ax1, ay1], [bx0, by0, bx1, by1]) {
  const dx = Math.max(bx0 - ax1, ax0 - bx1, 0), dy = Math.max(by0 - ay1, ay0 - by1, 0);
  return Math.hypot(dx, dy);
}

Gap between two sets of convex polygons

64-bit

The smallest distance between two footprints made of convex pieces, 0 when they touch or overlap.

The minimum of every corner-to-edge distance in both directions, which is the exact distance for polygons that do not overlap. Overlap is decided first with the 1e-6 threshold of overlap().

  • addons/cabinetcraft/lib/footprint.js
  • lines 70 to 79
  • CadCraft 0.8.2
/** Distance between two sets of convex polygons (0 when they touch or overlap). */
export function polyGap(setA, setB) {
  const segDist = (p, a, b) => { const dx = b[0] - a[0], dy = b[1] - a[1], L2 = dx * dx + dy * dy; const t = L2 ? Math.max(0, Math.min(1, ((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / L2)) : 0; return Math.hypot(p[0] - a[0] - t * dx, p[1] - a[1] - t * dy); };
  let best = Infinity;
  for (const A of setA) for (const B of setB) {
    if (overlap(A, B) > 0) return 0;
    for (const [P, Q] of [[A, B], [B, A]]) for (const p of P) for (let i = 0; i < Q.length; i++) best = Math.min(best, segDist(p, Q[i], Q[(i + 1) % Q.length]));
  }
  return best === Infinity ? 0 : best;
}

In detail

Method
Running-sum placement; corner stop = the other run's depth (or cornerBlock in angled.js for other angles) plus tilt and bend terms on arc walls; bisection for a filler on a curve (30 halvings) and for the first cabinet's shift at a corner (40 halvings of a 600 mm interval); shoelace sum for countertop areas; separating-axis test for convex footprints.
Number types
64-bit numbers; footprints are arrays of [x, y] pairs.
Tolerances
tol = 0.01 job units for reaching a wall end, adjacency and filler size; a corner is square when its turn is within 0.01 degrees of 90; largest automatic filler 75 mm (2.9375 in in an inch job); overlap counted above 1e-6; polygon edges shorter than 1e-9 skipped. All absolute.
Limits
The 0.01 tolerance is 0.01 mm in a millimeter job and 0.01 inch in an inch job. A corner countertop's length and width are both reported as the square root of its area.

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