Sampling 2D distance field with union via smooth min (logsumexp)
Log in to post a comment.
const R = 45;
const r1 = 11;
const r2 = 4.5;
const max_d = r1;
const step = 0.2;
const alpha = 0.2;
Canvas.setpenopacity(-0.2);
const t = new Turtle();
function minus(v1, v2) {
return [v1[0] - v2[0], v1[1] - v2[1]];
}
function length(v) {
return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
}
function df_circ(v, c, r) {
return length(minus(v, c)) - r;
}
function smooth_max(a, b, alpha) {
return Math.log(Math.exp(alpha * a) + Math.exp(alpha * b)) / alpha;
}
function smooth_min(a, b, alpha) {
return -smooth_max(-a, -b, alpha)
}
const circles = [];
const N = 6;
for (let i = 0; i < N; i++) {
let phi = Math.PI / 6 + 2 * Math.PI / N * i;
let c1 = [[R * Math.cos(phi), R * Math.sin(phi)], r1];
let c2 = [[(R + r1 + 6 * r2) * Math.cos(phi), (R + r1 + 6 * r2) * Math.sin(phi)], r2];
circles.push(c1);
circles.push(c2);
}
let x = -100;
let y = -100;
function walk(frame) {
let p = [x, y];
let d = 400;
for (let c of circles) {
let dc = df_circ(p, c[0], c[1]);
d = smooth_min(d, dc, alpha);
}
if (Math.abs(d) < max_d) {
let s = step * (1 - d / max_d);
t.seth(360 * Math.random());
for (let i = 0; i < 4; i++) {
t.jump(x, y);
t.forward(s);
t.right(90);
}
}
x += step;
if (x > 100) {
x = -100;
y += step;
}
return y <= 100;
}