Resources Numerical accuracy Calculation policy

Sketch exchange macro and import

Writes the drawing as a .swb sketch macro with its coordinates in meters, and reads an exported sketch back as geometry, constraints and dimensions.

How the precision is kept

On the way out every coordinate is rounded to 9 decimals of a drawing unit, converted to meters, rounded to 12 decimals of a meter and written with 15 significant digits. On the way in, points are taken as given, but each dimension's driving value is written from the value rounded to 9 decimals. So the exchange keeps about 1e-9 of a unit, not the full 64-bit value.

Open item. Write coordinates with 17 significant digits and without the 9- and 12-decimal rounding, or say in the export notes that values are rounded.

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.

swsketch.js CadCraft 0.8.2 64-bit 8 calculations Reviewed

Tests bin/test-cadcraft-constraints.mjs

Drawing units to meters

64-bit

A coordinate or length as the text the macro passes, in meters.

m = round₁₂(round₉(v) × mm per unit ÷ 1000)

The value is fixed to 9 decimals of a drawing unit, multiplied by millimeters per unit and divided by 1000, fixed again to 12 decimals of a meter, and then written by num. The comment gives the reason for the first rounding: solver noise below 1e-9 is dropped.

  • swsketch.js
  • lines 66 to 67
  • CadCraft 0.8.2
const M = (v) => num(Number((Number(v.toFixed(9)) * k / 1000).toFixed(12)));   // drawing units → metres (the API's unit); solver noise below 1e-9 dropped
const ents = [...doc.model.values()];

Numbers written into the macro

64-bit

A number as text in the macro.

v.toPrecision(15)

15 significant digits; 17 are needed to give back every 64-bit number exactly. Very large or small values are written in exponent form with 15 digits.

  • swsketch.js
  • line 344
  • CadCraft 0.8.2
const num = (v) => { const s = Number(v.toPrecision(15)).toString(); return /e/i.test(s) ? v.toExponential(14).replace('e', 'E') : s; };

Millimeters per drawing unit

Exact

The size of the drawing's unit in millimeters.

inch 25.4; foot 304.8; yard 914.4; mil 0.0254; microinch 0.0000254

The values are the defined sizes. A unit that is not in the table is treated as millimeters and a note says so.

  • swsketch.js
  • line 45
  • CadCraft 0.8.2
const UNIT_MM = { '': 1, millimeters: 1, centimeters: 10, meters: 1000, inches: 25.4, feet: 304.8, yards: 914.4, mils: 0.0254, microinches: 0.0000254 };

Arc ends on export

64-bit

The start and end points of an arc, which the macro needs beside its center.

start = c + r(cos a₀, sin a₀); end = c + r(cos a₁, sin a₁)

The ends are computed from the stored center, radius and angles in 64-bit, then each coordinate is rounded by M. The center and the two ends are rounded separately, so the written ends can sit off the written circle by the rounding step.

  • swsketch.js
  • lines 91 to 93
  • CadCraft 0.8.2
case 'arc': {
  const s = [e.cx + e.r * Math.cos(e.a0), e.cy + e.r * Math.sin(e.a0)], t = [e.cx + e.r * Math.cos(e.a1), e.cy + e.r * Math.sin(e.a1)];
  const i = seg('swSkMgr.CreateArc(' + [M(e.cx), M(e.cy), 0, M(s[0]), M(s[1]), 0, M(t[0]), M(t[1]), 0, 1].join(', ') + ')', 'arc ' + e.id);

Center of a polyline arc segment

64-bit

The center of the arc between two polyline vertices with a bulge.

θ = 4·atan(b); r = |chord ÷ (2·sin(θ ÷ 2))|; center = middle ± r·cos(θ ÷ 2) across the chord

The chord direction is divided by the chord length without a check, so two equal vertices with a bulge give a non-finite center. For a nearly flat bulge sin(θ ÷ 2) is small and the radius is large.

  • swsketch.js
  • lines 347 to 351
  • CadCraft 0.8.2
function bulgeCentre(p, q, b) {
  const th = 4 * Math.atan(b), c = Math.hypot(q.x - p.x, q.y - p.y), r = Math.abs(c / (2 * Math.sin(th / 2)));
  const h = r * Math.cos(th / 2) * (b > 0 ? 1 : -1), ux = (q.x - p.x) / c, uy = (q.y - p.y) / c;
  return { x: (p.x + q.x) / 2 - uy * h, y: (p.y + q.y) / 2 + ux * h };
}

Dimension values on export

64-bit

The value given to each dimension in the macro.

angle: degrees × π ÷ 180; length: M(value)

Angles are multiplied by π and divided by 180 in that order and written with 15 significant digits. Lengths go through the same 9- and 12-decimal rounding as coordinates.

  • swsketch.js
  • lines 193 to 194
  • CadCraft 0.8.2
const value = c.type === 'angle' ? num(c.value * Math.PI / 180) : M(c.value);
dims.push('swModel.ClearSelection2 True');

Arcs on import

64-bit

Builds an arc from the center, start and end points of an imported sketch.

r = |start − center|; a₀ = atan2(start − center); a₁ = atan2(end − center), each in [0, 2π)

The radius is the start point's distance from the center; the end point gives only an angle, so an end that is not at that distance is moved onto the circle.

  • swsketch.js
  • lines 451 to 452
  • CadCraft 0.8.2
const c = P.get(s.c), st = P.get(s.s), en = P.get(s.e);
ents.push({ type: 'arc', layer: s.construction ? 'CONSTRUCTION' : '0', cx: c.x, cy: c.y, r: Math.hypot(st.x - c.x, st.y - c.y), a0: ang(st.y - c.y, st.x - c.x), a1: ang(en.y - c.y, en.x - c.x) });

Dimension values on import

64-bit

The value each imported dimension gets, and the parameter that drives it.

parameter = round(value × 1e9) ÷ 1e9

The constraint first takes the file's value, in millimeters or degrees. The parameter that then drives it is written as text from the value rounded to 9 decimals.

  • swsketch.js
  • lines 522 to 523
  • CadCraft 0.8.2
if (Number.isFinite(p.value) && p.value > 0) c.value = p.value;   // millimetres; angles in degrees
params.vars.push({ name: c.name, expr: formatNumber(Math.round(c.value * 1e9) / 1e9) });

In detail

Method
Unit conversion through millimeters per unit ÷ 1000; arcs by center, start and end; polyline bulges to arc centers.
Number types
64-bit numbers; decimal text with 15 significant digits.
Tolerances
A bulge under 1e-12 is a straight segment. Imported numbers must be finite and under 1e9 in size.
Limits
Coordinates are rounded to 1e-9 drawing units and 1e-12 m on export; dimension values to 1e-9 on import. The header says nothing this module writes has been run in the target program.

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.

Every policy that takes this approach