Diffusion-limited aggregation
Log in to post a comment.
Canvas.setpenopacity(1);
const turtle = new Turtle();
turtle.home();
turtle.pendown();
var particle_count = 10000;
var sampling_radius = 70; // min=0.01, max=100, step=0.01
const stuck_radius = 1; // min=0.01, max=10, step=0.01
const stick_probability = 1; // min=0.0, max=1, step=0.01
const step_size = 1; // min=0.0, max=10, step=0.01
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
}
move() {
this.x += (Math.random() - 0.5) * 2 * step_size;
this.y += (Math.random() - 0.5) * 2 * step_size;
}
}
var stuck = [new Particle(0, 0)];
var free = [];
function distance(p0, p1) {
return Math.sqrt((p0.x - p1.x) ** 2 + (p0.y - p1.y) ** 2);
}
function sample_disk(r) {
let angle = Math.random() * 2 * Math.PI;
return [Math.cos(angle) * r, Math.sin(angle) * r];
}
turtle.jump(0, 0);
turtle.circle(1);
var maxdist = sampling_radius;
function walk(i) {
while (free.length < particle_count) {
let [x, y] = sample_disk(sampling_radius);
free.push(new Particle(x, y));
}
let new_free = [];
for (let idx = 0; idx < free.length; idx++) {
let particle = free[idx];
particle.move();
if (Math.sqrt(particle.x * particle.x + particle.y * particle.y) > sampling_radius * 2) {
let [nx, ny] = sample_disk(sampling_radius);
particle.x = nx;
particle.y = ny;
}
let attached = false;
for (let j = 0; j < stuck.length; j++) {
if (distance(particle, stuck[j]) < stuck_radius) {
if (Math.random() < stick_probability) {
stuck.push(new Particle(particle.x, particle.y));
turtle.pendown();
turtle.jump(particle.x, particle.y);
turtle.circle(stuck_radius);
let d = Math.sqrt(particle.x * particle.x + particle.y * particle.y);
if (d > maxdist) {
maxdist = d;
sampling_radius = maxdist * 1.1;
}
attached = true;
break;
}
}
}
if (!attached) {
new_free.push(particle);
}
}
free = new_free;
return i < 10000;
}