Moving circles around until they stop overlapping.
Log in to post a comment.
// LL 2021 const particle_count = 250; // min=1 max=1000 step=1 const iterations = 100; // min=0 max=1000 step=1 const collision_loop = 101 // min=1 max=1000 step=10 const min_radius = 0.06 // min=0.001 max=0.1 step=0.001 const max_radius = 0.7 // min=0.01 max=1.0 step=0.01 const min_bias = 6 // min=1 max=50 step=1 const fill_step = 0.75; // min=0.05 max=1 step=0.05 const seed = 0; // min=0 max=100 step=1 const scale = 100; // min=10 max=1000 step=10 Canvas.setpenopacity(1); const turtle = new Turtle(); class Particle { constructor(x, y, r) { this.x = x; this.y = y; this.r = r; } update() { const factor = 0.99; this.x *= factor; this.y *= factor; } } function resolve_collisions() { for (var r=0; r<collision_loop; r++) { for (var i=0; i<particle_count; i++) { for (var j=i+1; j<particle_count; j++) { var dx = particles[i].x - particles[j].x; var dy = particles[i].y - particles[j].y; var dist = Math.sqrt(dx*dx + dy*dy); const min_dist = particles[i].r + particles[j].r; while (dist < min_dist) { const factor = 0.001; particles[i].x += dx * factor; particles[i].y += dy * factor; particles[j].x -= dx * factor; particles[j].y -= dy * factor; dx = particles[i].x - particles[j].x; dy = particles[i].y - particles[j].y; dist = Math.sqrt(dx*dx + dy*dy); } } } } } function random_particle() { const x = rng.nextFloat() * 2 - 1; const y = rng.nextFloat() * 2 - 1; const r = Math.pow(rng.nextFloat(), min_bias) * (max_radius - min_radius) + min_radius; return new Particle(x, y, r); } var particles = null; function update_particles(loop_count) { resolve_collisions(); for (var i=0; i<loop_count; i++) { for (var p=0; p<particle_count; p++) { particles[p].update(); } resolve_collisions(); } } function walk(i, t) { if (particles == null) { particles = Array.from({length: particle_count}, (_, id) => (random_particle())); update_particles(t * iterations); } turtle.jump(particles[i].x * scale, particles[i].y * scale - particles[i].r * scale); turtle.circle(particles[i].r * scale); for (var r = particles[i].r * scale - fill_step; r > 0 && fill_step < 1; r -= fill_step) { turtle.jump(particles[i].x * scale, particles[i].y * scale - r); turtle.circle(r) } return (i+1) < particle_count; } /////// //// Random with seed function RNG(_seed) { // LCG using GCC's constants this.m = 0x80000000; // 2**31; this.a = 1103515245; this.c = 12345; this.state = _seed ? _seed : Math.floor(Math.random() * (this.m - 1)); } RNG.prototype.nextFloat = function() { // returns in range [0,1] this.state = (this.a * this.state + this.c) % this.m; return this.state / (this.m - 1); } var rng = new RNG(seed);