Resources Numerical accuracy Calculation policy

Roof pitch and slope factors

Reads a roof pitch and turns plan lengths and areas into lengths and areas along the slope.

How the precision is kept

A pitch is stored as rise in inches per 12 inches of run, as a 64-bit number, unrounded. The slope factors are one square root of a sum of positive terms, so nothing cancels.

Calculations under this policy

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

units.js TakeoffCraft 0.8.1 64-bit 4 calculations Reviewed

Tests bin/test-takeoffcraft.mjs

Typed pitch to rise per 12

64-bit

Reads 6:12, 6/12, 4:10, a bare rise, or an angle in degrees.

rise = tan(a·π ÷ 180) × 12; rise = rise ÷ run × 12

An angle a becomes tan(a·π ÷ 180) × 12; a ratio becomes rise ÷ run × 12. The value is returned unrounded. A decimal comma is read as a point.

  • units.js
  • lines 366 to 386
  • TakeoffCraft 0.8.1
/**
 * Read a pitch: "6:12", "6/12", "6 in 12", "6" (rise per 12), "4:10" (any run), "26.57°" or "26.57 deg" (an angle),
 * "0" or "" (flat). → { ok, rise } (rise per 12) | { ok: false, error: key }
 */
export function parsePitch(text) {
  const s = String(text ?? '').trim().toLowerCase().replace(/,/g, '.');
  if (!s) return { ok: true, rise: 0 };
  let m = s.match(/^(\d+(?:\.\d+)?|\.\d+)\s*(?:°|deg|degrees?)$/);
  if (m) {
    const a = parseFloat(m[1]);
    if (!(a >= 0 && a < 85)) return { ok: false, error: 'pitch.err.angle' };
    return { ok: true, rise: Math.tan(a * Math.PI / 180) * 12 };
  }
  m = s.match(/^(\d+(?:\.\d+)?|\.\d+)(?:\s*(?::|\/|in)\s*(\d+(?:\.\d+)?))?$/);
  if (!m) return { ok: false, error: 'pitch.err.read' };
  const rise = parseFloat(m[1]), run = m[2] === undefined ? 12 : parseFloat(m[2]);
  if (!(run > 0)) return { ok: false, error: 'pitch.err.read' };
  const r12 = rise / run * 12;
  if (!(r12 <= MAX_PITCH)) return { ok: false, error: 'pitch.err.steep' };
  return { ok: true, rise: r12 };
}

Slope factor of a roof plane

64-bit

Surface length or area per unit of plan length or area.

f = √(1 + (rise ÷ 12)²)

One expression: a square, an addition to 1 and a square root. Both terms are positive, so no digits are lost.

  • units.js
  • line 390
  • TakeoffCraft 0.8.1
export const slopeFactor = (rise) => Math.sqrt(1 + (rise / 12) ** 2);

Hip and valley factor

64-bit

True length of a hip or valley per unit of its plan length.

f = √(1 + (rise ÷ 12)² ÷ 2)

One expression: √(1 + (rise ÷ 12)² ÷ 2). Positive terms only.

  • units.js
  • line 392
  • TakeoffCraft 0.8.1
export const hipFactor = (rise) => Math.sqrt(1 + (rise / 12) ** 2 / 2);

Pitch as text

64-bit

Writes the rise as 6:12 or 6.5:12.

The rise is rounded to 2 decimals with Math.round(rise × 100) ÷ 100 for the text. parsePitch returns the unrounded rise, so a pitch typed as an angle shows rounded while the stored value is not.

  • units.js
  • line 388
  • TakeoffCraft 0.8.1
export const formatPitch = (rise) => (rise > 0 ? (Math.round(rise * 100) / 100) + ':12' : '');

In detail

Method
Slope factor √(1 + (rise ÷ 12)²) for rakes and roof planes; hip or valley factor √(1 + (rise ÷ 12)² ÷ 2) for a plan line at 45° between two planes of the same pitch.
Number types
64-bit numbers.
Limits
An angle must be from 0° up to but not including 85°; a pitch steeper than 144 in 12 is refused. The hip factor assumes equal pitches on both planes and a 45° plan line.

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