Simulation of human movement from their places of birth
Built with blockbuilder.org
| license: mit |
Simulation of human movement from their places of birth
Built with blockbuilder.org
| <!DOCTYPE html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <style> | |
| body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
| </style> | |
| </head> | |
| <body> | |
| <script> | |
| // Feel free to change or delete any of the code you see in this editor! | |
| var canvas = d3.select("body").append("canvas") | |
| .attr("width", 960) | |
| .attr("height", 500); | |
| var c = canvas.node().getContext("2d"), | |
| r = 1.5; | |
| var s = d3.scaleLinear() | |
| .domain([0,1]) | |
| .range([300,400]) | |
| var nodes = d3.range(8000).map(d => ({})); | |
| d3.forceSimulation(nodes) | |
| .force('saute', function(alpha){ | |
| nodes.forEach(d => { | |
| if (Math.random() < 1e-2) { | |
| var k = d3.randomLogNormal()(); | |
| var alpha = k * 100000; | |
| k = Math.sqrt(k); | |
| d[0] = k * Math.cos(alpha); | |
| d[1] = k * Math.sin(alpha); | |
| d.c = true; | |
| } | |
| }); | |
| }) | |
| .alphaTarget(1e-12) | |
| .on('tick', draw); | |
| function draw() { | |
| c.clearRect(0, 0, 960, 500); | |
| var th = 0; | |
| var sums = []; | |
| nodes.forEach(function(d){ | |
| d[2] = Math.sqrt(d[0]*d[0] + d[1]*d[1]); | |
| var u = Math.floor(s(d[2])); | |
| if (sums[u]) d[3] = (sums[u] = sums[u] - 0.01); | |
| else d[3] = sums[u] = -0.001; | |
| }); | |
| c.fillStyle = 'black'; // d.c ? 'rgba(0,0,0,0.1)' : 'rgba(0,0,0,0.1)'; | |
| c.beginPath(); | |
| nodes.forEach(function(d) { | |
| if (d.c) { | |
| d.x = s(d[0]); | |
| d.y = s(d[1]); | |
| } else { | |
| var k = 0.2 * Math.sqrt(th / nodes.length), alpha = th; | |
| d.x = s(k * Math.cos(alpha)); | |
| d.y = s(k * Math.sin(alpha)); | |
| th++; | |
| } | |
| c.moveTo(d.x + r, d.y); | |
| c.arc(d.x, d.y, r, 0, 2 * Math.PI); | |
| }); | |
| c.fill(); | |
| c.beginPath(); | |
| c.moveTo(s(0.2), s(0)); | |
| c.arc(s(0), s(0), s(0.2)-s(0), 0, 2 * Math.PI); | |
| c.stroke(); | |
| c.beginPath(); | |
| c.fillStyle = 'grey'; // d.c ? 'rgba(0,0,0,0.1)' : 'rgba(0,0,0,0.1)'; | |
| nodes.forEach(function(d) { | |
| if (d.c) { | |
| d.x = s(d[2]); | |
| d.y = 180+s(d[3]); | |
| c.moveTo(d.x + r, d.y); | |
| c.arc(d.x, d.y, r, 0, 2 * Math.PI); | |
| } | |
| }); | |
| c.fill(); | |
| } | |
| </script> | |
| </body> |