Lengths, perimeters and areas of measured runs and outlines, with arcs and cut-outs.
How the precision is kept
Straight outlines use the shoelace formula in 64-bit. Arcs are measured in closed form (radius times angle for length, the circular segment for area) and are never replaced by short chords for a quantity. Chords are used only for drawing and picking.
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.
The true length of one straight or curved piece of a run.
θ = 4 · atan(b); r = c ÷ (2 · sin(θ ÷ 2)); length = r × |θ|
Closed form from the chord c and the bulge b. No chords are added up.
geom.js
lines 21 to 27
TakeoffCraft 0.8.1
/** Exact length of one segment p → q with bulge b. */
export function segLength(p, q, b = 0) {
const c = dist(p, q);
if (!b || !c) return c;
const th = 4 * Math.atan(b);
return Math.abs((c / 2) / Math.sin(th / 2) * th);
}
Area under an arc
64-bit
The area between an arc and its chord.
area = r² × (θ − sin θ) ÷ 2
For a very shallow arc θ − sin θ subtracts two nearly equal numbers and loses digits. The area concerned is itself very small, so the total is barely affected.
geom.js
lines 29 to 36
TakeoffCraft 0.8.1
/** Signed area between the chord p → q and its arc (adds to signedArea; positive bulge = CCW). */
export function segArea(p, q, b = 0) {
if (!b) return 0;
const c = dist(p, q);
if (!c) return 0;
const th = 4 * Math.atan(b), r = c / (2 * Math.sin(th / 2));
return r * r * (th - Math.sin(th)) / 2;
}
Area of an outline
64-bit
The area inside a closed outline by the shoelace formula, arcs included.
A = ½ Σ (xᵢ · yᵢ₊₁ − xᵢ₊₁ · yᵢ) + Σ arc areas
Computed in the page's own coordinates as drawn. On a drawing page those are small numbers, so the products in the sum keep their digits.
geom.js
lines 126 to 135
TakeoffCraft 0.8.1
/** Signed area (positive counter-clockwise in a y-up space): shoelace + each arc's segment. */
export function signedArea(pts) {
let a = 0, s = 0;
for (let i = 0, n = pts.length; i < n; i++) {
const p = pts[i], q = pts[(i + 1) % n];
a += p.x * q.y - q.x * p.y;
if (p.b) s += segArea(p, q, p.b);
}
return a / 2 + s;
}
Perimeter
64-bit
The length around a closed outline.
P = Σ segment lengths, the closing segment included
Each piece is the exact segment or arc length above; the pieces are added in order.
geom.js
lines 120 to 124
TakeoffCraft 0.8.1
/** Closed outline's perimeter (the closing segment uses the last point's bulge). */
export function perimeter(pts) {
if (pts.length < 2) return 0;
return polylineLength(pts) + segLength(pts[pts.length - 1], pts[0], pts[pts.length - 1].b);
}
Net area with cut-outs
64-bit
Gross area, cut-outs, net area and perimeter of an area mark.
net = gross − Σ cut-outs
Each cut-out is measured by the same outline calculation and subtracted once.
geom.js
lines 138 to 144
TakeoffCraft 0.8.1
/** An area mark: outline minus cut-outs, perimeter of the outline plus each cut-out. */
export function areaWithHoles(outer, holes = []) {
const gross = polygonArea(outer);
const cut = holes.reduce((s, h) => s + polygonArea(h), 0);
const p = perimeter(outer) + holes.reduce((s, h) => s + perimeter(h), 0);
return { gross, cut, net: gross - cut, perimeter: p, outerPerimeter: perimeter(outer) };
}
Centroid
64-bit
The center of area of an outline, where its label goes.
An outline with arcs is first broken into 5° chords, so its centroid is approximate. Lengths and areas never use those chords.
geom.js
lines 250 to 260
TakeoffCraft 0.8.1
export function centroid(pts0) {
const pts = hasArcs(pts0) ? flatten(pts0, true) : pts0;
const a = signedArea(pts);
if (Math.abs(a) < 1e-12) { const b = bounds(pts); return { x: (b.minX + b.maxX) / 2, y: (b.minY + b.maxY) / 2 }; }
let cx = 0, cy = 0;
for (let i = 0, n = pts.length; i < n; i++) {
const p = pts[i], q = pts[(i + 1) % n], f = p.x * q.y - q.x * p.y;
cx += (p.x + q.x) * f; cy += (p.y + q.y) * f;
}
return { x: cx / (6 * a), y: cy / (6 * a) };
}
In detail
Method
Area is the shoelace sum over the corners plus the circular segment of each arc, r²/2 × (θ − sin θ). Arc length is r × θ. Cut-outs are subtracted from the gross area, and their edges are added to the perimeter.
Number types
64-bit numbers in the page's own coordinates. The drawing scale and units are applied to the result afterwards.
Tolerances
An outline with an area under 1e-9 square units is reported as empty. Crossing checks use 1e-9 relative to the size of the segments.
Checked by
The TakeoffCraft test suite checks lengths and areas of straight and arc outlines against known values.
Limits
Totals are ordinary 64-bit sums, added in order. The centroid of an outline with arcs is found on 5° chords.
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.