Warns about bolts a socket cannot reach, bolts too close for a socket, fillet welds outside size limits, welds a torch cannot reach, and tubes that hold water.
How the precision is kept
64-bit arithmetic on sample points. A socket or a torch is modeled as a cylinder and tested at a grid of points against the parts' true sections, so the result depends on the grid. The tool sizes are typical ratios stated in the file (nut 1.96 × d across corners, 4 mm socket wall, 60 mm socket length, 10 mm torch radius) and can be changed.
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 socket's disc is sampled on a square grid, clipped to the circle by gx² + gy² ≤ R_s². The grid loop adds the step repeatedly from −R_s, so the last row can stop just short of +R_s. The free length reported is the first of the five stations with a hit, not the exact distance.
constructability.js
lines 76 to 93
DetailCraft 0.8.1
const corners = o.cornersRatio * d, Rs = corners / 2 + o.socketWall;
const nutT = o.nutRatio * d;
const sides = [
{ side: 'head', from: add(b.head, mul(ax, -2)), dir: mul(ax, -1) },
{ side: 'nut', from: add(b.head, mul(ax, b.grip + nutT + 2)), dir: ax },
];
if (on.has('access')) for (const sd of sides) {
const [u, v] = perp(sd.dir);
let first = null;
const step = Math.max(2.5, Rs / 8), pts = [[0, 0]]; // a grid over the socket's disc, fine enough to meet a 6 mm web
for (let gx = -Rs; gx <= Rs; gx += step) for (let gy = -Rs; gy <= Rs; gy += step) if ((gx || gy) && gx * gx + gy * gy <= Rs * Rs) pts.push([gx, gy]);
for (let k = 0; k <= 4 && !first; k++) {
const s = k === 0 ? 0 : (o.socketLength * k) / 4;
for (const [gx, gy] of (k === 0 ? [[0, 0]] : pts)) {
const p = add(add(sd.from, mul(sd.dir, s)), add(mul(u, gx), mul(v, gy)));
for (const q of S) {
if (!inBox(q, p)) continue;
if (depthIn(q, p) > 0.5) { first = { q, s, r: Math.hypot(gx, gy) }; break; }
Room between neighboring bolts
64-bit
Whether the socket over one bolt touches the head of the next.
lat = |dv − A·(dv·A)|; need = 1.96·d_max ÷ 2 + wall + 1.96·d_min ÷ 2
The sideways distance is the head-to-head vector with its part along the bolt axis taken off. It is compared with the needed distance less 1e-6 mm. The values in the message are rounded to 0.1 mm.
constructability.js
lines 116 to 122
DetailCraft 0.8.1
const dv = sub(c.head, a.head), along = dot(dv, A), lat = Math.hypot(...sub(dv, mul(A, along)));
const need = Math.max(a.d, c.d) * o.cornersRatio / 2 + o.socketWall + Math.min(a.d, c.d) * o.cornersRatio / 2;
const headH = o.headRatio * Math.max(a.d, c.d);
if (sameSide && Math.abs(along) <= headH + 1 && lat < need - 1e-6 && (!worst || lat < worst.lat)) worst = { lat, need, d: Math.max(a.d, c.d) };
if (!sameSide && Math.abs(along - b2grip(a)) <= headH + 1 && lat < need - 1e-6 && (!worst || lat < worst.lat)) worst = { lat, need, d: Math.max(a.d, c.d) };
}
if (worst) push('bolts', 'warning', { conn, spacing: r1(worst.lat), need: r1(worst.need), d: worst.d }, [{ kind: 'conn', id: conn }], conn);
Fillet weld size limits
64-bit
The smallest and largest fillet weld allowed for the thinner of the two parts joined.
min = 3, 5, 6 or 8 mm for thickness up to 6.35, 12.7, 19.05 mm or more; max = t when t < 6.35, else t − 1.6
The thickness steps 6.35, 12.7 and 19.05 mm are exact conversions of 1/4, 1/2 and 3/4 inch. The 1.6 mm taken off for the maximum stands for 1/16 inch, which is 1.5875 mm. Comparisons allow 1e-6 mm.
The share of an all-round fillet weld's line where a torch on the 45 degree bisector is blocked.
start s0 = r·√2 + 1; direction = unit(outward + away); tested every 5 mm for the reach
Uses Math.SQRT2. Each outline edge is sampled at round(length ÷ 20) points, between 1 and 40, so on an edge longer than 800 mm the points are more than 20 mm apart. The torch is tested at its axis and eight points on its rim.
constructability.js
lines 155 to 185
DetailCraft 0.8.1
const s0 = o.torchRadius * Math.SQRT2 + 1; // where the nozzle's side first clears both faces of the fillet
let blocked = 0, total = 0, free = Infinity, by = null;
for (const loop of A.loops) {
for (let i = 0, j = loop.length - 1; i < loop.length; j = i++) {
const a = loop[j], b = loop[i], e = [b[0] - a[0], b[1] - a[1]], len = Math.hypot(e[0], e[1]);
if (len < 1e-6) continue;
const steps = Math.max(1, Math.min(40, Math.round(len / 20)));
let nrm = [e[1] / len, -e[0] / len];
// the outward side is the one that leaves the member's section
const mid = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2], probe = world(mid[0] + nrm[0] * 0.8, mid[1] + nrm[1] * 0.8);
const inside = (pt) => depthIn(A, add(pt, mul(away, 0.01))) > 0 || depthIn(A, pt) > 0;
if (inside(probe)) nrm = [-nrm[0], -nrm[1]];
const outW = add(mul(A.frame.u, nrm[0]), mul(A.frame.v, nrm[1]));
const dir = unit(add(outW, away)); // 45° between the member's face and the plate's face
const [pu, pv] = perp(dir);
for (let k = 0; k < steps; k++) {
const f = (k + 0.5) / steps, p0 = world(a[0] + e[0] * f, a[1] + e[1] * f);
total++;
let hit = null;
const rings = [[0, 0], [1, 0], [-1, 0], [0, 1], [0, -1], [0.7, 0.7], [-0.7, 0.7], [0.7, -0.7], [-0.7, -0.7]];
for (let s = s0; s <= s0 + o.torchReach && !hit; s += 5) {
for (const [gx, gy] of rings) {
const pt = add(add(p0, mul(dir, s)), add(mul(pu, gx * o.torchRadius), mul(pv, gy * o.torchRadius)));
for (const q of S) {
if (q.id === B.id || !inBox(q, pt)) continue;
if (depthIn(q, pt) > 0.5) { hit = { q, s }; break; }
}
if (hit) break;
}
}
if (hit) { blocked++; if (hit.s < free) { free = hit.s; by = hit.q; } }
Slope of a hollow section
64-bit
The slope of a tube, used to decide whether an open upper end lets rain in.
slope = asin(|Δz| ÷ length) × 180 ÷ π
The argument of Math.asin is not clamped to 1. For a vertical tube it is |Δz| ÷ hypot(0, 0, Δz); if that ratio ever rounded above 1 the slope would be not-a-number and the open-end note would not be given. Members shorter than 1 mm are left out.
Sampled cylinders against the clash check's point-in-part test; fillet weld limits from AISC 360-16 J2.2b and Table J2.4 as cited in the file.
Number types
64-bit numbers.
Tolerances
A sample counts as blocked when it is more than 0.5 mm inside a part. Box pre-test margin 2 mm. Weld and spacing comparisons use 1e-6 mm. Parallel bolts: |cos| ≥ 0.999.
Limits
Socket grid step max(2.5 mm, radius ÷ 8) at four stations along the socket, plus the axis point at the bearing face; torch tested at nine points every 5 mm, every 20 mm or so along the weld line. Only all-round fillet welds are located.
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.