Lays the model's walls, openings, roofs, foundations, cabinets and devices as marks on scaled plan sheets inside a PDF, so TakeoffCraft measures every quantity from the marks.
How the precision is kept
No quantity is sent as a number: each one is a mark on a sheet plus the sheet's scale. The mark coordinates are rounded to 0.01 PDF point, so what TakeoffCraft measures is limited by that rounding times the sheet scale. Wall heights are rounded to 0.01 foot and roof pitches to 0.01 degree and then to 4 decimals of rise per 12 before they are sent.
Open item. Write the mark coordinates unrounded, or with at least 6 decimals of a point, so the measured quantity is not limited to 0.01 point times the sheet scale.
Calculations under this policy
8 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 number of feet in the building that one PDF point stands for on a sheet drawn at 1:ratio.
ft per point = ratio × (25.4 ÷ 72) ÷ 304.8 = ratio ÷ 864
The factor reduces to the whole number 864, so the only rounding is the one division of a whole-number ratio.
res-takeoff.js
line 31
BimCraft 0.8.1
export const ftPerUnit = (ratio) => ratio / 864; // one point = 25.4 / 72 mm of paper = ratio × that in the building; 304.8 mm a foot
Mark coordinates on the sheet
64-bit
Maps a plan point to the sheet and writes it as the PDF-point coordinates of a takeoff mark.
mark = round(sheet mm × 72 ÷ 25.4 × 100) ÷ 100
Each coordinate is rounded to 0.01 point before it is written. 0.01 point is about 0.0035 mm of paper, which is about 0.17 mm of building on a sheet at 1:48 and more at smaller scales. Every length and area TakeoffCraft measures from the marks carries this rounding.
res-takeoff.js
line 73
BimCraft 0.8.1
const P = (q) => { const s = sh.place.P(q); return [r2(s[0] * PT), r2(s[1] * PT)]; };
Roof pitch as rise per 12
64-bit
Converts a pitch in degrees to the rise per 12 that TakeoffCraft uses for sloped areas and lengths.
rise per 12 = round(12 × tan θ × 10000) ÷ 10000
The rise per 12 is rounded to 4 decimals. The pitch it starts from was already rounded to 2 decimals of a degree for roof faces.
Sends each wall as a run along its center line, grouped by wall type and height.
height (ft) = round(height ÷ 304.8 × 100) ÷ 100
The wall height is rounded to 0.01 ft, which is 3.048 mm, and that rounded height is what the wall area is worked out from in TakeoffCraft. The run is the wall's two end points, unrounded until they become marks.
Places a count mark at the middle of each door and window along its wall.
at = a + (b − a) ÷ L × (offset + width ÷ 2)
One 64-bit interpolation along the wall; a zero wall length is replaced by 1. The position only places the count mark.
res-takeoff.js
lines 142 to 143
BimCraft 0.8.1
const L = Math.hypot(w.b[0] - w.a[0], w.b[1] - w.a[1]) || 1, s = o.offset + o.width / 2;
const at = [w.a[0] + (w.b[0] - w.a[0]) / L * s, w.a[1] + (w.b[1] - w.a[1]) / L * s];
Roof faces and roof lines
64-bit
Sends each roof face as a plan area with its pitch, and the ridges, hips, valleys, eaves and rakes as runs.
face pitch = round(pitch × 100) ÷ 100; line pitch = max over the faces
Each face's pitch is rounded to 0.01 degree. Hips, valleys and rakes are all given the largest pitch among the roof's faces, so on a roof with faces of different pitches their sloped lengths are worked out from the steepest one.
The run is the average of matching outer and inner outline points. A slab's thickness in feet is sent unrounded; a stem wall's height is rounded to 0.01 ft. Widths and thicknesses choose the nearest trade pack size.
The distance between a foundation's outer and inner outlines.
width = cross(b − a, q − a) ÷ |b − a|
The distance of the first inner point from the line through the first outer edge. Only that one edge is measured; a zero edge length is replaced by 1.
res-takeoff.js
lines 196 to 201
BimCraft 0.8.1
/** The width of a ring: the distance between its outer and inner outlines (both parallel insets of one outline). */
function polyPerimeterGap(outer, inner) {
const a = outer[0], b = outer[1], q = inner[0];
const L = Math.hypot(b[0] - a[0], b[1] - a[1]) || 1;
return ((b[0] - a[0]) * (q[1] - a[1]) - (b[1] - a[1]) * (q[0] - a[0])) / L;
}
In detail
Method
Walls as runs along their center lines with a height, roofs as plan areas with a pitch, ridges, hips, valleys, eaves and rakes as runs, foundations as runs along the middle of the footing and as slab areas, openings and devices as counts. Sheet scale as feet per PDF point = ratio ÷ 864.
Number types
64-bit numbers. One point is 25.4 ÷ 72 mm and one foot is 304.8 mm, so ratio ÷ 864 is exact.
Tolerances
Mark coordinates: 0.01 point. Wall and stem wall heights: 0.01 ft. Pitch: 0.01 degree, then 0.0001 of rise per 12.
Limits
Hips, valleys and rakes are all given the steepest pitch of the roof's faces. A foundation's width is measured at the first edge of its outline only.
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.