function superellipse(a = 1, b = 1, n = 2.5) {
const { sin, cos, tan, atan, sqrt, pow, hypot, abs, sign } = Math,
n2 = 2 / n, ba = b / a, pi = Math.PI, pi2 = pi / 2;
function fn(t) {
const cosT = cos(t), sinT = sin(t);
return [
abs(cosT) ** n2 * a * sign(cosT),
abs(sinT) ** n2 * b * sign(sinT)
]
}
fn.theta = function(t) {
const s = sign(sin(t)), theta = atan(ba * pow(abs(tan(t)), n2));
return sign(cos(t)) < 0 ? pi * s - theta * s : theta * s
};
fn.radiusAt = function(t) {
return Math.hypot(...this(t))
}
fn.points = function(num = 64) {
const step = 2 * pi / num;
return Array.from({length: num}, (_, i) => this(i * step));
}
fn.polar = function(num = 64) {
const step = 2 * pi / num;
return Array.from({length: num}, (_, i) => [this.theta(i * step), this.radiusAt(i * step)]);
}
return fn;
}