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; }