Collisions of circles on a grid
Log in to post a comment.
Canvas.setpenopacity(0.85); const turtle = new Turtle(); const grid = 11; // min=5, max=17, step=2 const radius = 11; // min=2, max=23, step=2 const size = 7/9 * 200 / grid; function getX(x) { return x - (grid/2|0) }; function getY(y) { return y - (grid/2|0) }; function walk() { const circles = []; for(let idx=0;idx<grid*grid;idx++) { const px = getX(idx % grid); const py = getY(idx / grid | 0); const r = 3 + Math.random() * radius; circles.push([px * size, py * size, r]); } circles.forEach(circle => drawCircle(circle, turtle)); let collisions = []; for(let idx=0;idx<circles.length-1;idx++) { let circle1 = circles[idx]; for(let idy=idx + 1;idy<circles.length;idy++) { let circle2 = circles[idy]; let intersection = circleToCircle(circle1, circle2); if (intersection) { collisions.push({circle1, circle2, intersection}); } } } collisions.forEach((col, idx) => { const circle1 = col.circle1; const circle2 = col.circle2; const [p1, p2] = col.intersection; drawCircle([...p1, 0.75], turtle); drawCircle([...p2, 0.75], turtle); }); } // centered circle function drawCircle(c, t) { t.jump(add(c, scl([0, -c[2] ],1))); t.circle(c[2]); } function drawArc(c, a1, a2, t, DENSITY = 0.25) { while (a2 < a1) a2 += Math.PI*2; const [x,y,r] = c; for (let a = a1; a < a2; a += 1/r/DENSITY) { if (a == a1) t.jump(x + Math.cos(a) * r, y + Math.sin(a) * r); t.goto(x + Math.cos(a) * r, y + Math.sin(a) * r); } t.goto(x + Math.cos(a2) * r, y + Math.sin(a2) * r); } // https://www.xarg.org/2016/07/calculate-the-intersection-points-of-two-circles/ function circleToCircle(p0, p1) { const r0 = p0[2]; const r1 = p1[2]; const dd = sub(p1, p0); const d = len(dd); if (d <= r0 + r1 && d >= Math.abs(r1 - r0)) { const e = scl(dd, 1 / d); const x = ((r0**2) - (r1**2) + (d**2)) / (2*d); const y = Math.sqrt((r0**2) - (x**2)); return [ [ p0[0] + x * e[0] - y * e[1], p0[1] + x * e[1] + y * e[0], ], [ p0[0] + x * e[0] + y * e[1], p0[1] + x * e[1] - y * e[0], ] ]; } else { return null; } } function pointInCircle(p,c) { return len(sub(p,c)) + 0.001 < c[2]; } // vec2 functions function vec2(a) { return [a,a]; } function scl(a,b) { return [a[0]*b, a[1]*b]; } function add(a,b) { return [a[0]+b[0], a[1]+b[1]]; } function sub(a,b) { return [a[0]-b[0], a[1]-b[1]]; } function dot(a,b) { return a[0]*b[0] + a[1]*b[1]; } function len(a) { return Math.sqrt(a[0]**2 + a[1]**2); } function nrm(a) { return scl(a, 1/len(a)); } function lrp(a,b,f) { return [a[0]*f+b[0]*(1-f), a[1]*f+b[1]*(1-f)]; } function angle(a) { return Math.atan2(a[1], a[0]); } function eql(a,b) { return a[0]==b[0] && a[1]==b[1]; }