@thi.ng/geom-arc
Version:
2D circular / elliptic arc operations
50 lines (49 loc) • 1.64 kB
JavaScript
import { isNumber } from "@thi.ng/checks/is-number";
import { isPlainObject } from "@thi.ng/checks/is-plain-object";
import { DEFAULT_SAMPLES } from "@thi.ng/geom-resample/api";
import { Sampler } from "@thi.ng/geom-resample/sampler";
import { TAU } from "@thi.ng/math/api";
import { cartesian2 } from "@thi.ng/vectors/cartesian";
import { pointAtTheta } from "./point-at.js";
const sample = (pos, r, axis, start, end, opts) => {
if (isPlainObject(opts) && opts.dist !== void 0) {
return new Sampler(
sample(
pos,
r,
axis,
start,
end,
opts.num || DEFAULT_SAMPLES
)
).sampleUniform(opts.dist, opts.last !== false);
}
opts = isNumber(opts) ? { num: opts, last: true } : { num: DEFAULT_SAMPLES, ...opts };
let delta = end - start;
let num = opts.theta ? Math.round(delta / opts.theta) : opts.num;
delta /= num;
opts.last !== false && num++;
const pts = new Array(num);
for (let i = 0; i < num; i++) {
pts[i] = pointAtTheta(pos, r, axis, start + i * delta);
}
return pts;
};
const sampleCircular = (origin, r, a, b, out = [], steps = 8, outwards = true, addLast = true) => {
let ta = Math.atan2(a[1] - origin[1], a[0] - origin[0]);
let tb = Math.atan2(b[1] - origin[1], b[0] - origin[0]);
ta < 0 && (ta += TAU);
tb < 0 && (tb += TAU);
const theta = ta > tb ? ta - tb : ta + TAU - tb;
const delta = (outwards ? -theta : TAU - theta) / steps;
out.push(a);
for (let i = 1; i < steps; i++) {
out.push(cartesian2(null, [r, ta + delta * i], origin));
}
addLast && out.push(b);
return out;
};
export {
sample,
sampleCircular
};