Works out each part's cut size from its finished size and edge banding, and totals pieces, areas, banding lengths and a rough sheet count.
How the precision is kept
Sizes stay in the caller's unit; nothing converts. Cut sizes, group areas and banding lengths are 64-bit sums rounded to 6 decimals. The CSV export rounds every number to 2 decimals by default. The sheet count is an estimate from area with a fixed waste factor, as the file's header says.
Open item. Write CSV sizes with at least 4 decimals, so sizes in sixteenths of an inch are exported exactly.
Calculations under this policy
7 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.
The two banding thicknesses are added first and subtracted once. The result is rounded to 6 decimals.
addons/cabinetcraft/lib/cutlist/cutlist.js
lines 64 to 76
CadCraft 0.8.2
export function cutSize(part, { deductBand = true, premill = 0 } = {}) {
let length = part.length, width = part.width;
if (deductBand) {
// the L edges run along the length: their banding sits at the ends of the width, and the other way round
width -= bt(part, 'l1') + bt(part, 'l2');
length -= bt(part, 'w1') + bt(part, 'w2');
}
if (premill) {
width += premill * ((part.band?.l1 ? 1 : 0) + (part.band?.l2 ? 1 : 0));
length += premill * ((part.band?.w1 ? 1 : 0) + (part.band?.w2 ? 1 : 0));
}
return { length: round(length), width: round(width) };
}
Pieces and areas per material
64-bit
The piece count, finished area and cut area of each material and thickness.
area = Σ qty × length × width; cut area = Σ qty × cut length × cut width
Sums in part order with no compensation; the totals are rounded to 6 decimals after the loop. The cut area uses cut sizes that were already rounded to 6 decimals.
The quotient is rounded to 9 decimals before Math.ceil, so a value a rounding error above a whole number does not add a sheet. The 15 % waste is a default the caller can change.
Each part as a rectangle at its cut size for the nesting engine.
The rectangle's corners are 0 and the cut length and width, which are rounded to 6 decimals. A part with its own outline is passed on unchanged.
addons/cabinetcraft/lib/cutlist/cutlist.js
lines 128 to 143
CadCraft 0.8.2
/**
* Parts → lib/nest's part list (no import: the shape is lib/nest/nest.js `nest(parts, …)`'s). Each part is nested at its CUT
* size (the bander adds the rest); x runs along the length, so a part with grain has grain angle 0 and may turn round
* (turn: true = 0° or 180°), a part without grain any way. One nest per material and thickness: `byMaterial` groups them.
*/
export function toNestParts(partsIn, { deductBand = true, premill = 0 } = {}) {
const out = [];
for (const p0 of partsIn) {
const p = cleanPart(p0);
if (!p) continue;
const c = cutSize(p, { deductBand, premill });
const rect = [{ x: 0, y: 0 }, { x: c.length, y: 0 }, { x: c.length, y: c.width }, { x: 0, y: c.width }];
out.push({ id: p.id, name: p.name, loops: p.outline || [rect], qty: p.qty, grain: p.grain === 'length' ? 0 : null, turn: true, material: p.material, thickness: p.thickness });
}
return out;
}
Cut list CSV numbers
64-bit
Writes the cut list as CSV text.
number cell = round(v, dp), dp = 2 by default
Every numeric cell is rounded to dp decimals, 2 unless the caller passes another value. With 2 decimals a length of 23.0625 is written 23.06.
addons/cabinetcraft/lib/cutlist/cutlist.js
lines 176 to 188
CadCraft 0.8.2
/** The cut list as CSV: one row per list row, grouped by material. `head` relabels columns (a translated header). */
export function toCsv(list, { columns = CSV_COLUMNS, head = CSV_HEAD, dp = 2 } = {}) {
const f = (v) => (typeof v === 'number' ? String(round(v, dp)) : v);
const rows = [columns.map((c) => csvCell(head[c] ?? c))];
for (const g of list.groups) for (const r of g.rows) {
const cell = {
...r, id: r.ids.join(' '), grain: r.grain, cutLength: r.cut.length, cutWidth: r.cut.width,
l1: r.band.l1?.code || '', l2: r.band.l2?.code || '', w1: r.band.w1?.code || '', w2: r.band.w2?.code || '',
};
rows.push(columns.map((c) => csvCell(f(cell[c]))));
}
return rows.map((r) => r.join(',')).join('\r\n') + '\r\n';
}
In detail
Method
Cut size = finished size − banding thickness on each banded edge + pre-mill per banded edge; area = Σ qty × length × width; banding = Σ qty × edge length; sheets ≈ ⌈cut area × (1 + 0.15) ÷ sheet area⌉.
Number types
64-bit numbers.
Checked by
tools/cutlist/test.mjs runs lib/cutlist/cutlist.js, which was byte-identical to this file at the review. It compares cutSize of a 717 × 597 door banded 2 mm all round with 713 × 593, group areas and banding lengths with hand sums, and the sheet estimate with the same formula.
Limits
With 2 decimals in the CSV, a size in sixteenths of an inch is not written exactly: 23.0625 becomes 23.06. The sheet count ignores shapes and grain; nesting gives the real count.
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.