block by fil 69f1d5f68099bf6350ed42aed0941e5c

Collision Detection in a tight square

Full Screen

This example uses d3.forceCollide to prevent circles from overlapping.

forked from mbostock‘s block: Collision Detection

See also Bounded Force Layout - very tightly packed.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="800" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var canvas = document.querySelector("canvas"),
    context = canvas.getContext("2d"),
    width = canvas.width,
    height = canvas.height,
    tau = 2 * Math.PI;

var nodes = d3.range(1000).map(function(i) {
  return {
    r: Math.random() * 8 + 3
  };
});

  function neg(u){
    return (-u + Math.abs(u))/2;
  }
  
  function shape(alpha){
   for (var i = 0, n = nodes.length, node, k = alpha * 0.1; i < n; ++i) {
    node = nodes[i];
     var xa = node.x + 200,
         xb = node.x - 200,
         ya = node.y + 200,
         yb = node.y - 200;
     node.vx += (neg(xa) - neg(-xb));
     node.vy += (neg(ya) - neg(-yb));
   }
  }
  
var simulation = d3.forceSimulation(nodes)
    //.velocityDecay(0.2)
    .force("shape", shape)
    .force("collide", d3.forceCollide().radius(function(d) { return d.r + 0.5; }).iterations(2))
    .on("tick", ticked);

var color = d3.scaleOrdinal(d3.schemeCategory10);
  
function ticked() {
  context.clearRect(0, 0, width, height);
  context.save();
  context.translate(width / 2, height / 2);

  nodes.forEach(function(d,i) {
    context.beginPath();
    context.moveTo(d.x + d.r, d.y);
    context.arc(d.x, d.y, d.r, 0, tau);
    context.fillStyle = color(i);
    context.fill();
    context.strokeStyle = "white";
    context.stroke();
  });
  
  context.restore();
}

</script>