function simulate() {
regions.forEach(function(region) {
region.x = region.x0;
region.y = region.y0;
});
color.domain(d3.extent(regions, d => d.u));
var links = d3.merge(
neighbours.map(function(neighborSet, i) {
return neighborSet
.filter(j => regions[j])
.map(function(j) {
return {
source: i,
target: j,
distance: regions[i].r + regions[j].r + 3
};
});
})
);
var simulation = d3
.forceSimulation(regions)
.force(
"cx",
d3
.forceX()
.x(d => width / 2)
.strength(0.02)
)
.force(
"cy",
d3
.forceY()
.y(d => height / 2)
.strength(0.02)
)
.force("link", d3.forceLink(links).distance(d => d.distance))
.force(
"x",
d3
.forceX()
.x(d => d.x)
.strength(0.1)
)
.force(
"y",
d3
.forceY()
.y(d => d.y)
.strength(0.1)
)
.force(
"collide",
d3
.forceCollide()
.strength(0.8)
.radius(d => d.r + 3)
)
.stop()
.on("end", function() {
});
while (simulation.alpha() > 0.1) {
simulation.tick();
}
regions.forEach(function(region) {
var circle = pseudocircle(region);
var closestPoints = region.rings.slice(1).map(function(ring) {
var i = d3.scan(circle.map(point => distance(point, ring.centroid)));
return ring.map(() => circle[i]);
});
var interpolator = d3.interpolateArray(region.rings, [
circle,
...closestPoints
]);
region.interpolator = function(t) {
var str = pathString(interpolator(t));
if (t > 0.99) {
let s = str.split("Z")[0] + "Z";
return s;
}
return str;
};
});
regionsSvg
.transition()
.attrTween("d", firstTransition)
.attr("fill", d => d3[colorInterpolation](color(d.u)))
.transition()
.delay(delay)
.duration(duration)
.attrTween("d", node => t => secondTransition(node, t))
.attr("d", feature => path(feature))
.on("end", (d, i) => i || setTimeout(()=>{simulate()},endDelay));
}