Resources Numerical accuracy Calculation policy

Printing patterns at full size

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.

addons/apparel/lib/print.js CadCraft 0.8.2 64-bit 6 calculations Reviewed

Tests None found by the review

Paper sizes

Exact

The two home-printer papers, in millimeters.

A4 = 210 × 297; Letter = 215.9 × 279.4 (8.5 × 11 in × 25.4)

215.9 and 279.4 are the exact millimeter values of 8.5 and 11 inches, written as decimal constants.

  • addons/apparel/lib/print.js
  • line 26
  • CadCraft 0.8.2
export const PAPERS = { a4: { w: 210, h: 297, label: 'A4' }, letter: { w: 215.9, h: 279.4, label: 'Letter' } };

Test square

Exact

The side of the square printed on the cover page to check the scale.

10 cm = 100 mm; 4 in = 101.6 mm

101.6 is exactly 4 × 25.4. The square is drawn with this side in page millimeters.

  • addons/apparel/lib/print.js
  • line 30
  • CadCraft 0.8.2
export const testSquare = (u) => (u === 'in' ? { side: 101.6, label: '4 in' } : { side: 100, label: '10 cm' });

Full-size page

64-bit

The page size and the placement of the pieces on a single full-size page.

w = (maxX − minX)·k + 2·margin; h = (maxY − minY)·k + 2·margin + 8; matrix = [k, 0, 0, k, margin − minX·k, margin − minY·k]

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.

  • addons/apparel/lib/print.js
  • lines 149 to 151
  • CadCraft 0.8.2
const tx = c * sx, ty = -r * sy;   // the tile's top-left in content mm
const m = [k, 0, 0, k, margin - tx - b.minX * k, (P.h - margin - 8) - ty - b.maxY * k];
const clip = [{ x: margin, y: margin }, { x: margin + pw, y: margin }, { x: margin + pw, y: margin + ph }, { x: margin, y: margin + ph }];

In detail

Method
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.

Every policy that takes this approach