Lays pattern pieces on one large page or on tiled home-printer pages at 1:1, with a test square to check the print scale (Apparel add-on).
How the precision is kept
Page coordinates are millimeters. Drawing units are multiplied by 1 (millimeter drawings) or 25.4 (inch drawings), which is the exact definition of the inch, and placed by a 2 × 3 matrix in 64-bit numbers. The pieces are passed to CadCraft's plot code as vectors; this file does not sample them.
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.
k is 1 or 25.4. The scale on both axes is k itself, so 1 drawing millimeter is 1 page millimeter with no rounding step in this file.
addons/apparel/lib/print.js
lines 72 to 73
CadCraft 0.8.2
const w = (b.maxX - b.minX) * k + 2 * margin, h = (b.maxY - b.minY) * k + 2 * margin + 8;
const m = [k, 0, 0, k, margin - b.minX * k, margin - b.minY * k];
Tile grid
64-bit
How many tiles across and down the pieces need.
pw = paper w − 2·margin; ph = paper h − 2·margin − 8; step = pw − overlap, ph − overlap; cols = max(1, ⌈(W − overlap) ÷ step − 1e-9⌉)
The 1e-9 keeps a content width that is a whole number of tiles from rounding up to one more. It is taken off a count of tiles, not off a length.
addons/apparel/lib/print.js
lines 94 to 103
CadCraft 0.8.2
const pw = P.w - 2 * margin, ph = P.h - 2 * margin - 8; // 8 mm at the top for the tile's name line
const sx = pw - overlap, sy = ph - overlap;
for (const size of sizesOf(pieces, sizes)) {
const { pd, ents } = printDoc(doc, pieces, size, draw);
const b = boundsOf(pd, ents);
if (!b) continue;
const W = (b.maxX - b.minX) * k, H = (b.maxY - b.minY) * k;
const cols = Math.max(1, Math.ceil((W - overlap) / sx - 1e-9)), rows = Math.max(1, Math.ceil((H - overlap) / sy - 1e-9));
// the content in mm, its top-left at (0, 0) of the tile grid, y up; tile (r, c) covers x c·sx … c·sx + pw, y −(r·sy + ph) … −r·sy
const base = [k, 0, 0, k, -b.minX * k, -b.maxY * k];
Which tiles have something on them
64-bit
Marks the tiles a point of the drawing falls on, so empty tiles are not printed.
c from ⌈(x − pw) ÷ sx⌉ to ⌊x ÷ sx⌋; r from ⌈(−y − ph) ÷ sy⌉ to ⌊−y ÷ sy⌋
Lines are tested at points no further apart than a quarter of the smaller tile step and arcs at 16 steps. This decides only whether a page is printed; the geometry on each page comes from the vectors.
addons/apparel/lib/print.js
lines 107 to 113
CadCraft 0.8.2
const hit = (x, y) => {
const c0 = Math.max(0, Math.ceil((x - pw) / sx - 1e-9)), c1 = Math.min(cols - 1, Math.floor(x / sx + 1e-9));
const r0 = Math.max(0, Math.ceil((-y - ph) / sy - 1e-9)), r1 = Math.min(rows - 1, Math.floor(-y / sy + 1e-9));
for (let r = r0; r <= r1; r++) for (let c = c0; c <= c1; c++) inks[r * cols + c] = true;
};
const step = Math.min(sx, sy) / 4;
const seg = (x1, y1, x2, y2) => { const n = Math.max(1, Math.ceil(Math.hypot(x2 - x1, y2 - y1) / step)); for (let i = 0; i <= n; i++) hit(x1 + (x2 - x1) * i / n, y1 + (y2 - y1) * i / n); };
Placement on one tile
64-bit
Where the pieces land on the page of one tile.
tx = c·sx; ty = −r·sy; matrix = [k, 0, 0, k, margin − tx − minX·k, (paper h − margin − 8) − ty − maxY·k]
Each tile's offset is a whole number of tile steps, formed by one multiplication, so neighboring pages are shifted by exactly one step with no error carried from tile to tile.
Bounding box of what the pieces draw; scale and offset matrix per page; tile grid from the printable area minus the overlap.
Number types
64-bit numbers.
Tolerances
Tile counts and tile hits use 1e-9 on a count of tiles. Which tiles have ink is found from points every quarter of a tile step along each line, and 16 steps along each arc.
Limits
A tile that an object only crosses between two sample points could be left out as empty. Pages over 5080 mm on a side are flagged as too big.
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.