Resources Numerical accuracy Calculation policy

Exact surface records for meshing

Reads each curved face's true surface (sphere, cone, torus, revolution, extrusion, spline) out of the kernel as plain numbers for the analysis mesher, and verifies it.

How the precision is kept

Sphere, revolution, extrusion and spline data are copied from OpenCascade as 64-bit numbers. Cone and torus parameters are derived from the surface's derivatives at the middle of the face. Every record is then tested: 25 points of the real face must lie on the record's surface within 1e-9 of the face's size, or the record is discarded.

Calculations under this policy

3 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.

brep-surf.js PartCraft 0.8.1 64-bit 3 calculations Reviewed

Tests tools/partcraft-test/test-tet-exact.mjs

Cone from its derivatives

64-bit

A cone's axis point, axis direction, radius and slope from the surface's derivatives at one point.

ρ = |P_uu|; e = −P_uu ÷ ρ; z = P_v − (P_v · e) e; axis point = P − ρ e; slope k = (P_v · e) ÷ |z|

The derivatives are evaluated by OpenCascade at the middle of the face's parameter box. The divisions by ρ and |z| are not guarded; a zero or non-finite result fails the 25-point check that follows, which is written so that NaN is rejected.

  • brep-surf.js
  • lines 62 to 65
  • PartCraft 0.8.1
// P = L + (R + v sinα)(cos u X + sin u Y) + v cosα Z: ∂²P/∂u² = −ρe (ρ the radius here), ∂P/∂v = sinα e + cosα Z
const P = xyz(T(ad.EvalD0(um, vm))), Puu = D(2, 0), Pv = D(0, 1), rho = Math.hypot(...Puu), e = Puu.map((x) => -x / rho);
const se = Pv[0] * e[0] + Pv[1] * e[1] + Pv[2] * e[2], z = [0, 1, 2].map((a) => Pv[a] - se * e[a]), zl = Math.hypot(...z);
s = { type: 'cone', o: [0, 1, 2].map((a) => P[a] - rho * e[a]), d: z.map((x) => x / zl), r0: rho, k: se / zl };

Torus from its derivatives

64-bit

A torus's center, axis and two radii from the surface's derivatives at one point.

ρ = |P_uu|; A = P − ρ e; d = unit(e × P_u); tube center M = P + P_vv; c = A + ((M − A) · d) d; R = |M − c|; r = |P_vv|

The tube center uses P + P_vv, which holds because the second derivative round the tube has length r and points at the tube's center. R is a distance between two computed points, so for a thin tube far from the origin it carries rounding at the scale of the coordinates.

  • brep-surf.js
  • lines 67 to 71
  • PartCraft 0.8.1
// ∂²P/∂u² = −ρe (ρ = R + r cos v, the distance to the axis), ∂²P/∂v² = −r n (n from the tube centre)
const P = xyz(T(ad.EvalD0(um, vm))), Puu = D(2, 0), Pu = D(1, 0), Pvv = D(0, 2), rho = Math.hypot(...Puu), e = Puu.map((x) => -x / rho);
const A = [0, 1, 2].map((a) => P[a] - rho * e[a]), d = unit([e[1] * Pu[2] - e[2] * Pu[1], e[2] * Pu[0] - e[0] * Pu[2], e[0] * Pu[1] - e[1] * Pu[0]]);
const M = [0, 1, 2].map((a) => P[a] + Pvv[a]), t = (M[0] - A[0]) * d[0] + (M[1] - A[1]) * d[1] + (M[2] - A[2]) * d[2], c = [0, 1, 2].map((a) => A[a] + t * d[a]);
s = { type: 'torus', c, d, R: Math.hypot(M[0] - c[0], M[1] - c[1], M[2] - c[2]), r: Math.hypot(...Pvv) };

Check against the kernel's face

64-bit

Confirms the record describes the same surface as the kernel's face before it is used.

25 points on a 5 × 5 grid (2 % to 98 % of the parameter box); each within 1e-9 × size of the record's surface

The tolerance is relative to the face's size (the spread of the samples or its radii, at least 1e-6). The comparison is written as not (d ≤ tol), so a NaN distance also rejects the record.

  • brep-surf.js
  • lines 83 to 89
  • PartCraft 0.8.1
// check: points of the OCCT face lie on the record's surface
const pts = [];
for (let i = 0; i < 5; i++) for (let j = 0; j < 5; j++) pts.push(xyz(T(ad.EvalD0(range[0] + (range[1] - range[0]) * (0.02 + 0.24 * i), range[2] + (range[3] - range[2]) * (0.02 + 0.24 * j)))));
let size = 0; for (const p of pts) size = Math.max(size, Math.hypot(p[0] - pts[0][0], p[1] - pts[0][1], p[2] - pts[0][2]));
size = Math.max(size, s.r || 0, s.R || 0, 1e-6);
for (const p of pts) if (!(closestOnSurface(s, p).d <= 1e-9 * size)) return null;
return s;

In detail

Method
Cone: radius ρ = |∂²P/∂u²|, radial direction e = −∂²P/∂u² ÷ ρ, axis from ∂P/∂v with its radial part removed. Torus: tube radius r = |∂²P/∂v²|, axis direction e × ∂P/∂u, center by projecting the tube center onto the axis.
Number types
64-bit numbers in plain arrays.
Tolerances
Acceptance: distance of each of 25 face points to the record's surface ≤ 1e-9 × size, where size is the largest of the sample spread, the radii and 1e-6.
Checked by
tools/partcraft-test/test-tet-exact.mjs calls exactSurface on sphere, torus, cone, revolution, extrusion and B-spline faces and checks the type of each record. It loads the development build's copy of this file.
Limits
Size caps: 40,000 surface poles, 10,000 curve poles. A rejected face is meshed from the tessellation instead.

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.

Every policy that takes this approach