Picked point as an anchor
64-bitThe anchor position in the part's own axes and the face normal at the pick.
p = M⁻¹ p_pick, each coordinate rounded to 6 decimals; n = (b − a) × (c − a) ÷ length
The stored anchor passes through Number(x.toFixed(6)), so it is rounded to 1e-6 in model units before it is saved in the manual. The normal divides by the cross product's length only when that length is above 0.
/** A picked point as an anchor (in the part's own axes) and the picked face's normal there. */
function anchorAt(h) {
const m = S.doc.m, inst = m.instances.find((i) => i.id === h.inst);
const M = MN.worldOf(m, shownScene()).get(h.inst), inv = invert(M);
const p = applyM(inv, h.point);
let n = [0, 1, 0];
const mesh = S.doc.meshes.get(inst.part);
if (mesh && Number.isInteger(h.face) && h.face * 3 + 2 < mesh.indices.length) {
const P = mesh.positions, I = mesh.indices, k = h.face * 3;
const a = [P[I[k] * 3], P[I[k] * 3 + 1], P[I[k] * 3 + 2]], b = [P[I[k + 1] * 3], P[I[k + 1] * 3 + 1], P[I[k + 1] * 3 + 2]], c = [P[I[k + 2] * 3], P[I[k + 2] * 3 + 1], P[I[k + 2] * 3 + 2]];
const u = [b[0] - a[0], b[1] - a[1], b[2] - a[2]], v = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];
const nn = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]], l = Math.hypot(...nn);
if (l > 0) n = nn.map((x) => x / l);
}
return { anchor: { inst: h.inst, p: p.map((x) => Number(x.toFixed(6))) }, normal: n };
}