Bricks to compute
64-bitWhich bricks of the lattice can hold the surface.
brick range = floor((box ∓ band × h) ÷ h ÷ 8); ball radius = 3.5√3 × h
Brick indices are floors of the box limits divided by h and by 8, in 64-bit. Each brick is classified with a ball around its center at (index × 8 + 3.5) × h; only bricks that may hold the surface are computed.
export function plan(spec, { h, bbox = null, band = 3 } = {}) {
const node = compile(spec);
const box = bbox || node.bounds;
if (!box.every(Number.isFinite)) throw new FieldError('nobox', 'field: this field has no finite box; pass bbox or intersect it with a box');
const pad = band * h;
const lo = [0, 1, 2].map((a) => Math.floor((box[a] - pad) / h / 8)), hi = [0, 1, 2].map((a) => Math.floor((box[a + 3] + pad) / h / 8));
for (let a = 0; a < 3; a++) if (!inRange(lo[a]) || !inRange(hi[a])) throw new FieldError('toolarge', 'field: part too large for the grid (more than 16 000 bricks along an axis)');
const keys = [], inside = [], r = R_BRICK * h;
for (let bx = lo[0]; bx <= hi[0]; bx++) for (let by = lo[1]; by <= hi[1]; by++) for (let bz = lo[2]; bz <= hi[2]; bz++) {
const cls = node.cls((bx * 8 + 3.5) * h, (by * 8 + 3.5) * h, (bz * 8 + 3.5) * h, r, band * h);
if (cls === OUT) continue;
if (cls === IN) inside.push(keyOf(bx, by, bz)); else keys.push(keyOf(bx, by, bz));
}
return { h, band, keys, inside, bricks: (hi[0] - lo[0] + 1) * (hi[1] - lo[1] + 1) * (hi[2] - lo[2] + 1) };
}