thi-ng/umbrella

View on GitHub
packages/poisson/src/stratified.ts

Summary

Maintainability
F
3 days
Test Coverage
import { isNumber } from "@thi.ng/checks/is-number";
import { SYSTEM } from "@thi.ng/random/system";
import type { ReadonlyVec } from "@thi.ng/vectors";
import { add2, add3 } from "@thi.ng/vectors/add";
import { distSq2, distSq3 } from "@thi.ng/vectors/distsq";
import { mul2, mul3 } from "@thi.ng/vectors/mul";
import { random2, random3 } from "@thi.ng/vectors/random";
import type { StratifiedGridOpts } from "./api.js";

/**
 * Yields iterator of 2D point samples of for given stratified grid
 * config.
 *
 * @remarks
 * All samples will be in `[[0,0] .. [dimx,dimy])` interval
 *
 * @param opts -
 */
export function* stratifiedGrid2(opts: StratifiedGridOpts) {
    let { rnd = SYSTEM, separation: sep = Math.SQRT1_2 } = opts;
    sep *= sep;
    const scale =
        opts.scale !== undefined
            ? isNumber(opts.scale)
                ? [opts.scale, opts.scale]
                : opts.scale
            : undefined;
    const [sx, sy] = opts.dim;
    const sx1 = sx - 1;
    const tmp = [0, 0];
    let prevY: ReadonlyVec[] = [];
    let currY: ReadonlyVec[] = [];
    let q;
    for (let y = 0; y < sy; y++) {
        for (let x = 0; x < sx; x++) {
            while (true) {
                q = add2(null, [x, y], random2(tmp, 0, 1, rnd));
                if (x > 0 && distSq2(currY[x - 1], q) < sep) continue;
                if (y > 0) {
                    if (
                        distSq2(prevY[x], q) < sep ||
                        (x > 0 && distSq2(prevY[x - 1], q) < sep) ||
                        (x < sx1 && distSq2(prevY[x + 1], q) < sep)
                    )
                        continue;
                }
                break;
            }
            currY.push(q);
            yield scale ? mul2([], q, scale) : q;
        }
        prevY = currY;
        currY = [];
    }
}

/**
 * Yields iterator of 3D point samples of for given stratified grid
 * config.
 *
 * @remarks
 * All samples will be in `[[0,0,0] .. [dimx,dimy,dimz])` interval
 *
 * @param opts -
 */
export function* stratifiedGrid3(opts: StratifiedGridOpts) {
    let { rnd = SYSTEM, separation: sep = Math.SQRT1_2 } = opts;
    sep *= sep;
    const scale =
        opts.scale !== undefined
            ? isNumber(opts.scale)
                ? [opts.scale, opts.scale]
                : opts.scale
            : undefined;
    const [sx, sy, sz] = opts.dim;
    const sx1 = sx - 1;
    const tmp = [0, 0, 0];
    let prevY: ReadonlyVec[] = [];
    let prevZ: ReadonlyVec[][] = [];
    let currY: ReadonlyVec[] = [];
    let currZ: ReadonlyVec[][] = [];
    let q;
    for (let z = 0; z < sz; z++) {
        for (let y = 0; y < sy; y++) {
            for (let x = 0; x < sx; x++) {
                while (true) {
                    q = add3(null, [x, y, z], random3(tmp, 0, 1, rnd));
                    if (x > 0 && distSq3(currY[x - 1], q) < sep) continue;
                    if (y > 0) {
                        if (
                            distSq3(prevY[x], q) < sep ||
                            (x > 0 && distSq3(prevY[x - 1], q) < sep) ||
                            (x < sx1 && distSq3(prevY[x + 1], q) < sep)
                        )
                            continue;
                    }
                    if (z > 0) {
                        let py = prevZ[y];
                        if (
                            distSq3(py[x], q) < sep ||
                            (x > 0 && distSq3(py[x - 1], q) < sep) ||
                            (x < sx1 && distSq3(py[x + 1], q) < sep)
                        )
                            continue;
                        if (y > 0) {
                            py = prevZ[y - 1];
                            if (
                                distSq3(py[x], q) < sep ||
                                (x > 0 && distSq3(py[x - 1], q) < sep) ||
                                (x < sx1 && distSq3(py[x + 1], q) < sep)
                            )
                                continue;
                        }
                    }
                    break;
                }
                currY.push(q);
                yield scale ? mul3([], q, scale) : q;
            }
            currZ.push(currY);
            prevY = currY;
            currY = [];
        }
        prevZ = currZ;
        currZ = [];
    }
}