Rib slab outline
64-bitThe flat region the rib is cut from: the sketch chain carried past both ends and offset to one side.
E = 4 × max(1, diagonal + |box center − sketch origin|); ends ± E along the end directions; far side = + E × D
End directions and the chord are normalized with Math.hypot. The far corners are sums of a sketch coordinate and a length of several body sizes, so they carry rounding at that larger scale; they lie outside the body and are removed by the cut.
const E = 4 * Math.max(1, V.len(V.sub(bb.max, bb.min)) + V.len(V.sub(V.mul(V.add(bb.max, bb.min), 0.5), frame.o)));
const sub = (a, b) => [a[0] - b[0], a[1] - b[1]], len = (a) => Math.hypot(a[0], a[1]);
const unit = (a) => [a[0] / len(a), a[1] / len(a)];
const n = pts.length;
const d0 = unit(sub(pts[1], pts[0])), d1 = unit(sub(pts[n - 1], pts[n - 2]));
const chord = unit(sub(pts[n - 1], pts[0]));
// the side the rib fills: toward the body's centre of mass (a bracket's inside corner), flip: away — whichever end was drawn first
const gp = T(new oc.GProp_GProps());
oc.BRepGProp.VolumeProperties(ctx.body, gp, false, false, false);
const cm = V.toPlane(frame, H.xyz(T(gp.CentreOfMass())));
const left = [-chord[1], chord[0]], mid0 = [(pts[0][0] + pts[n - 1][0]) / 2, (pts[0][1] + pts[n - 1][1]) / 2];
const toward = (cm[0] - mid0[0]) * left[0] + (cm[1] - mid0[1]) * left[1] >= 0 ? 1 : -1;
const side = toward * (f.flip ? -1 : 1);
const D = [left[0] * side, left[1] * side];
const ext = [[pts[0][0] - d0[0] * E, pts[0][1] - d0[1] * E], ...pts.slice(1, -1), [pts[n - 1][0] + d1[0] * E, pts[n - 1][1] + d1[1] * E]];
const far = ext.map((p) => [p[0] + D[0] * E, p[1] + D[1] * E]).reverse();
const poly = [...ext, ...far];