DLA

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