dodge = (data, radius) => {
const radius2 = radius ** 2;
const circles = data.map(d => ({y: y(d.value), data: d})).sort((a, b) => a.y - b.y);
const epsilon = 1e-3;
let head = null, tail = null;
function intersects(x, y) {
let a = head;
while (a) {
if (radius2 - epsilon > (a.x - x) ** 2 + (a.y - y) ** 2) {
return true;
}
a = a.next;
}
return false;
}
for (const b of circles) {
while (head && head.y < b.y - radius2) head = head.next;
if (intersects(b.x = 0, b.y)) {
let a = head;
b.x = Infinity;
do {
let x = a.x + Math.sqrt(radius2 - (a.y - b.y) ** 2);
if (x < b.x && !intersects(x, b.y)) b.x = x;
a = a.next;
} while (a);
}
b.next = null;
if (head === null) head = tail = b;
else tail = tail.next = b;
}
return circles;
}