The coordinates, block placements and rotation angles written when the 3D model is exported to DXF R12 or handed to the DWG writer.
How the precision is kept
Coordinates are multiplied by one unit factor (meters to inches, millimeters, centimeters or meters) in 64-bit. DXF text is written with 15 significant digits. The DWG path passes the same numbers on as 64-bit values without formatting them.
Open item. Write DXF numbers with 17 significant digits and convert to inches by dividing by 0.0254.
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 factor that turns the model's meters into the drawing unit of the export.
inches: 1 ÷ 0.0254; mm: 1000; cm: 100; m: 1
The metric factors are whole numbers. The inch factor is computed once as 1 ÷ 0.0254, which is rounded, and coordinates are then multiplied by it: two roundings where a division by 0.0254 would make one.
The insertion point, scale, rotation and extrusion direction that stand for a placement matrix.
scale = column lengths; n = third unit column; rot = atan2(r₀ · a_y, r₀ · a_x); insertion = (T · a_x, T · a_y, T · n)
The matrix columns are normalized by their lengths; the placement is written as an insert only when the unit columns are square to each other within 1e-9 in their dot products, otherwise it is written out as plain geometry. The rotation comes from atan2 and the insertion point is the translation, times the unit factor, projected on the insert's own axes.
m3d/io.js
lines 1233 to 1247
CadCraft 0.8.2
/** A placement as an INSERT: {ins (OCS), scale [x, y, z], rot (radians), n (extrusion)}, or null when it is not a turn + scale. */
export function insertOf(m, k) {
const c = [[m[0], m[1], m[2]], [m[4], m[5], m[6]], [m[8], m[9], m[10]]];
const s = c.map(len);
if (s.some((x) => !(x > 1e-12))) return null;
const r = c.map((v, i) => mul(v, 1 / s[i]));
if (Math.abs(dot(r[0], r[1])) > 1e-9 || Math.abs(dot(r[0], r[2])) > 1e-9 || Math.abs(dot(r[1], r[2])) > 1e-9) return null;
if (dot(cross(r[0], r[1]), r[2]) < 0) { s[2] = -s[2]; r[2] = mul(r[2], -1); }
const n = r[2];
// the arbitrary axis algorithm (DXF reference): the OCS of this extrusion direction
const ax = norm(Math.abs(n[0]) < 1 / 64 && Math.abs(n[1]) < 1 / 64 ? cross([0, 1, 0], n) : cross([0, 0, 1], n));
const ay = cross(n, ax);
const T = [m[12] * k, m[13] * k, m[14] * k];
return { ins: [dot(T, ax), dot(T, ay), dot(T, n)], scale: s, rot: Math.atan2(dot(r[0], ay), dot(r[0], ax)), n };
}
DXF number format
64-bit
How every coordinate, scale and angle is written in the DXF text.
text = x rounded to 15 significant digits
toPrecision(15) keeps 15 significant digits; a value below 1e-12 in size, in the drawing's unit, is written as 0.
m3d/io.js
line 1304
CadCraft 0.8.2
const df = (x) => { let v = +(+x).toPrecision(15); if (Object.is(v, -0) || Math.abs(v) < 1e-12) v = 0; return String(v); };
DXF insert record
64-bit
The numbers of one block placement in the DXF text.
rotation in degrees = rot × 180 ÷ π
The rotation is converted from radians to degrees in one expression and written, like the point, scale and extrusion direction, with 15 significant digits.
Each definition becomes a block and each placement an INSERT whose insertion point, scale, rotation and extrusion direction come from the placement matrix by the arbitrary axis algorithm (the code cites the DXF reference). A placement that is not a turn and scale is written out in place.
Number types
64-bit numbers; DXF text via toPrecision(15).
Tolerances
A placement is a turn and scale when its unit columns' dot products are within 1e-9 and no column is shorter than 1e-12. DXF: a value below 1e-12 in size is written as 0. Arbitrary axis switch at 1/64, as the format defines.
Limits
15 significant digits are written, not the 17 needed to read back the same 64-bit value. The inch factor is the rounded value of 1 ÷ 0.0254.
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.