Skip to content

Commit 7338c4c

Browse files
Filmbostock
andauthored
faster dodge (#901)
* faster dodge * tweak style Co-authored-by: Mike Bostock <[email protected]>
1 parent f9ec0c9 commit 7338c4c

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

src/transforms/dodge.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,28 +54,33 @@ function dodge(y, x, anchor, padding, options) {
5454
for (let I of facets) {
5555
const tree = IntervalTree();
5656
I = I.filter(R ? i => finite(X[i]) && positive(R[i]) : i => finite(X[i]));
57+
const intervals = new Float64Array(2 * I.length);
5758
for (const i of I) {
58-
const intervals = [];
5959
const l = X[i] - radius(i);
6060
const h = X[i] + radius(i);
6161

6262
// For any previously placed circles that may overlap this circle, compute
6363
// the y-positions that place this circle tangent to these other circles.
6464
// https://observablehq.com/@mbostock/circle-offset-along-line
65+
let k = 0;
6566
tree.queryInterval(l - padding, h + padding, ([,, j]) => {
6667
const yj = Y[j];
6768
const dx = X[i] - X[j];
6869
const dr = padding + (R ? R[i] + R[j] : 2 * r);
6970
const dy = Math.sqrt(dr * dr - dx * dx);
70-
intervals.push([yj - dy, yj + dy]);
71+
intervals[k++] = yj - dy;
72+
intervals[k++] = yj + dy;
7173
});
7274

7375
// Find the best y-value where this circle can fit.
74-
for (let y of intervals.flat().sort(compare)) {
75-
if (intervals.every(([lo, hi]) => y <= lo || y >= hi)) {
76-
Y[i] = y;
77-
break;
76+
out: for (const y of intervals.slice(0, k).sort(compare)) {
77+
for (let j = 0; j < k; j += 2) {
78+
if (y > intervals[j] && y < intervals[j + 1]) {
79+
continue out;
80+
}
7881
}
82+
Y[i] = y;
83+
break;
7984
}
8085

8186
// Insert the placed circle into the interval tree.

0 commit comments

Comments
 (0)