Looks up a steel section or builds a plate or custom profile, and gives its outline, area, mass per meter, width, depth and perimeter.
How the precision is kept
Catalog sizes come from the shared section table in shapes/sections.js. Mass per meter is the published figure where the table has one; otherwise it is area × density in 64-bit. Area, outline and perimeter are computed by functions of the shared table, not in this file.
Calculations under this policy
5 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.
Fills in the values every member, bill of materials and drawing reads from a profile.
mass kg/m = published value, else area mm² × 10⁻⁶ × ρ kg/m³
Area, outline, bounding box and perimeter come from exactArea, outline, bbox and loopLength in shapes/sections.js. The computed mass is one 64-bit product chain, and massFrom records which of the two sources was used. A custom profile may carry its own density.
The name of a plate profile from its thickness and width.
PL<t>x<w>, each to 2 decimals
Thickness and width are rounded with toFixed(2) for the name only. A profile asked for as PL12.346x200 keeps t = 12.346 but is named PL12.35x200, and looking that name up again gives 12.35.
profiles.js
lines 64 to 65
DetailCraft 0.8.1
/** "PL20x200" = 20 mm thick, 200 mm wide. */
export function plateName(t, w) { return 'PL' + num(t) + 'x' + num(w); }
Thickness a hole goes through
64-bit
The material thickness on the face a hole is made in.
A lookup with no arithmetic: the plate or angle thickness, the web or flange thickness, the wall of a hollow section, and for the web face of a rectangular hollow section the full width b.
profiles.js
lines 155 to 161
DetailCraft 0.8.1
/** Thickness a hole on a face goes through. */
export function faceThickness(p, face) {
if (p.kind === 'PL' || p.kind === 'L') return p.t; // an angle's legs (connection holes only: 'bottom' = the leg along u, 'web' = along v)
if (face === 'web') return p.kind === 'RHS' ? p.b : p.tw;
if (p.kind === 'RHS') return p.t;
return p.tf;
}
Profile summary in the properties panel
64-bit
The rows of sizes, area and mass shown for a profile.
area cm² = area mm² ÷ 100
Sizes are shown with 1 decimal in mm, area with 2 decimals in cm² and mass with 2 decimals in kg/m. This is display rounding; the profile's own values are unchanged.
Each size is converted with Number() and must be finite and from 0 to 5000 mm; comparisons check that web, flanges, fillet and walls fit. A rectangular hollow section gets outer and inner corner radii of 2t and t. A density is accepted from 100 to 8000 kg/m³.
profiles.js
lines 77 to 105
DetailCraft 0.8.1
/**
* Checks a custom profile definition (untrusted: from a file or a form). Returns { ok, profile | error }.
* `saved`: it comes from a model file, which may predate a catalog size of that name (allowed unless it is a LEGACY name).
*/
export function cleanCustom(c, { saved = false } = {}) {
if (!c || typeof c !== 'object') return { ok: false, error: t('prof.err.not-profile') };
const name = String(c.name || '').replace(/[\u0000-\u001f\u007f]/g, '').trim().slice(0, 40);
if (!name) return { ok: false, error: t('prof.err.name') };
if ((CATALOG.has(name.toUpperCase()) && (!saved || LEGACY.has(name.toUpperCase()))) || PL_RE.test(name)) return { ok: false, error: t('prof.err.catalog-name', { name }) };
const kind = String(c.kind || '');
if (!CUSTOM_KINDS[kind]) return { ok: false, error: t('prof.err.shape', { kind }) };
const p = { name, kind, family: 'custom', source: 'custom' };
for (const k of CUSTOM_KINDS[kind]) {
const v = Number(c[k]);
if (!Number.isFinite(v) || v < 0 || v > 5000 || (k !== 'r' && v === 0)) return { ok: false, error: t('prof.err.size', { name: k }) };
p[k] = v;
}
if (kind === 'I' || kind === 'C') {
if (p.tw >= p.bf || 2 * p.tf >= p.d) return { ok: false, error: t('prof.err.web-flanges') };
if (kind === 'I' && p.tw / 2 + p.r > p.bf / 2) return { ok: false, error: t('prof.err.fillet-flange') };
if (kind === 'I' && 2 * (p.tf + p.r) >= p.d) return { ok: false, error: t('prof.err.fillet-depth') };
}
const dn = Number(c.density); // 0.8 round 3: a profile of another material (a placed timber panel, EG.6) says its density in kg/m³
if (c.density !== undefined && Number.isFinite(dn) && dn >= 100 && dn <= 8000) p.density = dn;
if (kind === 'L' && p.t >= p.b) return { ok: false, error: t('prof.err.leg') };
if (kind === 'RHS') { if (2 * p.t >= Math.min(p.h, p.b)) return { ok: false, error: t('prof.err.wall') }; p.ro = 2 * p.t; p.ri = p.t; }
if (kind === 'CHS' && 2 * p.t >= p.D) return { ok: false, error: t('prof.err.wall') };
return { ok: true, profile: p };
}
In detail
Method
Catalog lookup by name (AISC Shapes Database v16.0 and EN 10365:2017, as the header states), parametric plates PL<t>x<w>, and custom profiles checked on entry.
Number types
64-bit numbers.
Limits
Published masses carry the digits of the source table. Plate names keep two decimals of thickness and width. The properties panel rounds to 0.1 mm, 0.01 cm² and 0.01 kg/m.
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.