Skip to content

Commit

Permalink
Related #74.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Jan 28, 2017
1 parent 417e544 commit 102024d
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 31 deletions.
46 changes: 17 additions & 29 deletions src/pack/siblings.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,39 +84,27 @@ export function packEnclose(circles) {
pack: for (i = 3; i < n; ++i) {
place(a._, b._, c = circles[i]), c = new Node(c);

// If there are only three elements in the front-chain…
if ((k = a.previous) === (j = b.next)) {
// If the new circle intersects the third circle,
// rotate the front chain to try the next position.
if (intersects(j._, c._)) {
a = b, b = j, --i;
continue pack;
}
}

// Find the closest intersecting circle on the front-chain, if any.
// “Closeness” is determined by linear distance along the front-chain.
// “Ahead” or “behind” is likewise determined by linear distance.
else {
sj = b._.r + j._.r, sk = a._.r + k._.r;
do {
if (sj <= sk) {
if (intersects(j._, c._)) {
if (distance1(a, j) > distance1(j, b)) a = j; else b = j;
a.next = b, b.previous = a, --i;
continue pack;
}
sj += (j = j.next)._.r;
} else {
if (intersects(k._, c._)) {
if (distance1(a, k) > distance1(k, b)) a = k; else b = k;
a.next = b, b.previous = a, --i;
continue pack;
}
sk += (k = k.previous)._.r;
j = b.next, k = a.previous, sj = b._.r + j._.r, sk = a._.r + k._.r;
do {
if (sj <= sk) {
if (intersects(j._, c._)) {
if (distance1(a, j) > distance1(j, b)) a = j; else b = j;
a.next = b, b.previous = a, --i;
continue pack;
}
} while (j !== k.next);
}
sj += (j = j.next)._.r;
} else {
if (intersects(k._, c._)) {
if (distance1(a, k) > distance1(k, b)) a = k; else b = k;
a.next = b, b.previous = a, --i;
continue pack;
}
sk += (k = k.previous)._.r;
}
} while (j !== k.next);

// Success! Insert the new circle c between a and b.
c.previous = a, c.next = b, a.next = b.previous = b = c;
Expand Down
21 changes: 19 additions & 2 deletions test/pack/siblings-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ var tape = require("tape"),
d3 = require("../../");

tape("packSiblings(circles) produces a non-overlapping layout of circles", function(test) {
test.equal(intersectsAny(d3.packSiblings([3, 30, 50, 400, 600].map(circleValue))), false);
test.equal(intersectsAny(d3.packSiblings([1, 1, 3, 30, 50, 400, 600].map(circleValue))), false);
permute([100, 200, 500, 70, 3].map(circleValue), p => intersectsAny(d3.packSiblings(p)) && test.fail(p.map(c => c.r)));
permute([3, 30, 50, 400, 600].map(circleValue), p => intersectsAny(d3.packSiblings(p)) && test.fail(p.map(c => c.r)));
permute([1, 1, 3, 30, 50, 400, 600].map(circleValue), p => intersectsAny(d3.packSiblings(p)) && test.fail(p.map(c => c.r)));
test.equal(intersectsAny(d3.packSiblings([2, 9071, 79, 51, 325, 867, 546, 19773, 371, 16, 165781, 10474, 6928, 40201, 31062, 14213, 8626, 12, 299, 1075, 98918, 4738, 664, 2694, 2619, 51237, 21431, 99, 5920, 1117, 321, 519162, 33559, 234, 4207].map(circleValue))), false);
test.equal(intersectsAny(d3.packSiblings([0.3371386860049076, 58.65337373332081, 2.118883785686244, 1.7024669121097333, 5.834919697833051, 8.949453403094978, 6.792586534702093, 105.30490014617664, 6.058936212213754, 0.9535722042975694, 313.7636051642043].map(circleRadius))), false);
test.equal(intersectsAny(d3.packSiblings([6.26551789195159, 1.707773433636342, 9.43220282933871, 9.298909705475646, 5.753163715613753, 8.882383159012575, 0.5819319661882536, 2.0234859171687747, 2.096171518434433, 9.762727931304937].map(circleRadius))), false);
Expand All @@ -12,6 +13,22 @@ tape("packSiblings(circles) produces a non-overlapping layout of circles", funct
test.end();
});

function swap(array, i, j) {
var t = array[i];
array[i] = array[j];
array[j] = t;
}

function permute(array, f, n) {
if (n == null) n = array.length;
if (n === 1) return void f(array);
for (var i = 0; i < n - 1; ++i) {
permute(array, f, n - 1);
swap(array, n & 1 ? 0 : i, n - 1);
}
permute(array, f, n - 1);
}

function circleValue(value) {
return {r: Math.sqrt(value)};
}
Expand Down

0 comments on commit 102024d

Please sign in to comment.