Resources Numerical accuracy Calculation policy

Parametric PCB footprints

Pad positions, pad sizes and the courtyard of standard-style footprints, worked out from pitch, row spacing and pin count.

How the precision is kept

The file says its land patterns are examples worked out from body and lead sizes with plain rules, not values of the IPC-7351 standard. Pad centers are computed from the pin index with one multiplication by the pitch, not by adding the pitch repeatedly, so no error builds up along a row. The courtyard is the pads' extent grown by a fixed margin. All values are 64-bit numbers.

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.

footlib.js Shared shell, every app 64-bit 7 calculations Reviewed

Tests None found by the review

Courtyard of a footprint

64-bit

The rectangle around all pads, grown by a margin.

courtyard = (min(x − w ÷ 2) − m, min(y − h ÷ 2) − m, max(x + w ÷ 2) + m, max(y + h ÷ 2) + m)

Minimum and maximum over the pads' edges, then one subtraction or addition of the margin. No rounding.

  • footlib.js
  • lines 2 to 10
/**
 * Parametric footprints (0.8 XE.11). Land patterns here are EXAMPLES worked out from body and lead sizes with plain rules; they are not IPC-7351 values
 * (that standard is not reproduced) — a shop's own library replaces them. Pad numbers are strings. Local origin = the part centre, pin 1 at the left/top.
 */
const mk = (name, pads, margin = 0.25, silk = []) => {
  let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
  for (const p of pads) { x0 = Math.min(x0, p.x - p.w / 2); x1 = Math.max(x1, p.x + p.w / 2); y0 = Math.min(y0, p.y - p.h / 2); y1 = Math.max(y1, p.y + p.h / 2); }
  return { name, pads, courtyard: [x0 - margin, y0 - margin, x1 + margin, y1 + margin], silk };
};

Two-terminal chip

64-bit

Two pads at half the pitch either side of the center.

x = ∓ pitch ÷ 2

One division by 2 per pad, which is exact in binary. The listed chip sizes are literal example values.

  • footlib.js
  • lines 14 to 15
/** Two-terminal chip: pitch between pad centres, pad w×h (w along the pitch axis). */
export const chip = (name, pitch, padW, padH) => mk(name, [smd(1, 'rect', -pitch / 2, 0, padW, padH), smd(2, 'rect', pitch / 2, 0, padW, padH)], 0.2);

Dual-row surface-mount package

64-bit

Pads in two rows, numbered counter-clockwise from the top left.

y = ((n ÷ 2 − 1) ÷ 2 − i) × pitch; x = ∓ row spacing ÷ 2

Each pad's position along the row is one product of the pitch and an index offset that is exact in binary, so pads at mirrored places have exactly opposite coordinates.

  • footlib.js
  • lines 17 to 22
/** Dual-row SMD (SOIC style): n pins, pitch, row-to-row distance between pad centres. Pin 1 top-left, counter-clockwise. */
export function soic(n, pitch = 1.27, rowSpacing = 5.4, padW = 0.6, padL = 1.5, name = 'SOIC-' + n) {
  const half = n / 2, pads = [];
  for (let i = 0; i < half; i++) { const y = ((half - 1) / 2 - i) * pitch; pads.push(smd(i + 1, 'rect', -rowSpacing / 2, y, padL, padW)); pads.push(smd(n - i, 'rect', rowSpacing / 2, y, padL, padW)); }
  return mk(name, pads.sort((a, b) => +a.num - +b.num), 0.3);
}

Dual in-line through-hole package

64-bit

Drilled pads in two rows.

y = ((n ÷ 2 − 1) ÷ 2 − i) × pitch; x = ∓ row spacing ÷ 2

The same index-times-pitch placement as the surface-mount rows, with a drill diameter per pad.

  • footlib.js
  • lines 23 to 28
/** Dual in-line through-hole. */
export function dip(n, pitch = 2.54, rows = 7.62, drill = 0.8, pad = 1.6, name = 'DIP-' + n) {
  const half = n / 2, pads = [];
  for (let i = 0; i < half; i++) { const y = ((half - 1) / 2 - i) * pitch; pads.push(tht(i + 1, i === 0 ? 'rect' : 'oval', -rows / 2, y, pad, pad, drill)); pads.push(tht(n - i, 'oval', rows / 2, y, pad, pad, drill)); }
  return mk(name, pads.sort((a, b) => +a.num - +b.num), 0.4);
}

Pin header

64-bit

Drilled pads in one or two rows at a pitch.

x = (r − (rows − 1) ÷ 2) × pitch; y = ((n − 1) ÷ 2 − i) × pitch

Both coordinates are the pitch times an index offset that is exact in binary; nothing is accumulated along the row.

  • footlib.js
  • lines 29 to 34
/** Pin header, one or two rows. */
export function header(n, rows = 1, pitch = 2.54, drill = 1.0, pad = 1.7, name = 'HDR-' + rows + 'x' + n) {
  const pads = []; let k = 1;
  for (let i = 0; i < n; i++) for (let r = 0; r < rows; r++) pads.push(tht(k, k++ === 1 ? 'rect' : 'circle', (r - (rows - 1) / 2) * pitch, ((n - 1) / 2 - i) * pitch, pad, pad, drill));
  return mk(name, pads, 0.4);
}

Quad flat package

64-bit

Pads on four sides, numbered counter-clockwise from the top left.

along a side: ((n − 1) ÷ 2 − i) × pitch; across: ± span ÷ 2

Each side is placed from the index by one product; the four sides use the same expression with the sign or the axis changed.

  • footlib.js
  • lines 36 to 44
/** Quad flat pack: nPerSide pins on each side, pitch, span between opposite pad-row centres. Pin 1 top-left, counter-clockwise. */
export function quad(nPerSide, pitch = 0.5, span = 8.4, padW = 0.3, padL = 1.4, name = 'QFP-' + nPerSide * 4) {
  const pads = []; let k = 1;
  for (let i = 0; i < nPerSide; i++) pads.push(smd(k++, 'rect', -span / 2, ((nPerSide - 1) / 2 - i) * pitch, padL, padW));
  for (let i = 0; i < nPerSide; i++) pads.push(smd(k++, 'rect', (-(nPerSide - 1) / 2 + i) * pitch, -span / 2, padW, padL));
  for (let i = 0; i < nPerSide; i++) pads.push(smd(k++, 'rect', span / 2, (-(nPerSide - 1) / 2 + i) * pitch, padL, padW));
  for (let i = 0; i < nPerSide; i++) pads.push(smd(k++, 'rect', ((nPerSide - 1) / 2 - i) * pitch, span / 2, padW, padL));
  return mk(name, pads, 0.4);
}

Axial through-hole part

64-bit

Two drilled pads at half the lead pitch either side of the center.

x = ∓ pitch ÷ 2

One exact halving per pad. The default pitch 7.62 is a decimal literal.

  • footlib.js
  • lines 45 to 46
/** Axial through-hole part (resistor, diode): lead pitch. */
export const axial = (pitch = 7.62, drill = 0.8, pad = 1.6, name = 'AXIAL-' + pitch) => mk(name, [tht(1, 'rect', -pitch / 2, 0, pad, pad, drill), tht(2, 'circle', pitch / 2, 0, pad, pad, drill)], 0.4);

In detail

Method
Pad center along a row = ((pins per row − 1) ÷ 2 − i) × pitch; rows at ± half the row spacing. Courtyard = minimum and maximum of pad center ± half pad size, grown by the margin.
Number types
64-bit numbers; pad numbers are strings.
Limits
The dimensions are the file's own example values, to be replaced by a shop's library. Pitches such as 1.27 and 2.54 are decimal literals.

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