Skip to content

Commit

Permalink
Fix #27 - save node order for resquarify.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Mar 28, 2016
1 parent 191236f commit 7b2aeb6
Showing 1 changed file with 48 additions and 54 deletions.
102 changes: 48 additions & 54 deletions src/treemap/squarify.js
Original file line number Diff line number Diff line change
@@ -1,82 +1,76 @@
import treemapDice from "./dice";
import treemapSlice from "./slice";

export default (function custom(ratio) {

function squarify(parent, x0, y0, x1, y1) {
var nodes = parent.children,
node,
if (parent._squarify) return resquarify(parent, x0, y0, x1, y1);

var squarified = parent._squarify = [],
nodes = parent.children,
row,
nodeValue,
i0 = 0,
i1,
n = nodes.length,
x2, y2,
dx, dy,
value = parent.value,
sumValue,
minValue,
maxValue,
alpha,
beta,
newRatio,
minRatio;
minRatio,
alpha,
beta;

while (i0 < n) {
dx = x1 - x0, dy = y1 - y0;
sumValue = (node = nodes[i0]).value;
minValue = maxValue = sumValue = nodes[i0].value;
alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
beta = sumValue * sumValue * alpha;
minRatio = Math.max(maxValue / beta, beta / minValue);

// Are we updating a previous squarified layout?
if (node._squarify) {
for (i1 = i0 + 1; i1 < Math.abs(node._squarify); ++i1) {
sumValue += nodes[i1].value;
}
}

// Otherwise, we’re computing a squarified layout from scratch.
else {
minValue = maxValue = sumValue;
alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
// Keep adding nodes while the aspect ratio maintains or improves.
for (i1 = i0 + 1; i1 < n; ++i1) {
sumValue += nodeValue = nodes[i1].value;
if (nodeValue < minValue) minValue = nodeValue;
if (nodeValue > maxValue) maxValue = nodeValue;
beta = sumValue * sumValue * alpha;
minRatio = Math.max(maxValue / beta, beta / minValue);

// Keep adding nodes while the aspect ratio maintains or improves.
for (i1 = i0 + 1; i1 < n; ++i1) {
sumValue += nodeValue = nodes[i1].value;
if (nodeValue < minValue) minValue = nodeValue;
if (nodeValue > maxValue) maxValue = nodeValue;
beta = sumValue * sumValue * alpha;
newRatio = Math.max(maxValue / beta, beta / minValue);
if (newRatio > minRatio) { sumValue -= nodeValue; break; }
minRatio = newRatio;
}

node._squarify = dx < dy ? i1 : -i1;
newRatio = Math.max(maxValue / beta, beta / minValue);
if (newRatio > minRatio) { sumValue -= nodeValue; break; }
minRatio = newRatio;
}

// Position the row horizontally along the top of the rect.
if (node._squarify > 0) {
for (x2 = x0, y2 = y0 + dy * sumValue / value, dx /= sumValue; i0 < i1; ++i0) {
node = nodes[i0], node.x0 = x2, node.y0 = y0, node.y1 = y2;
node.x1 = x2 += node.value * dx;
}
node.x1 = x1, y0 = y2;
}

// Position the row vertically along the left of the rect.
else {
for (y2 = y0, x2 = x0 + dx * sumValue / value, dy /= sumValue; i0 < i1; ++i0) {
node = nodes[i0], node.y0 = y2, node.x0 = x0, node.x1 = x2;
node.y1 = y2 += node.value * dy;
}
node.y1 = y1, x0 = x2;
}

value -= sumValue;
// Position and record the row orientation.
squarified.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
if (row.dice) treemapDice(row, x0, y0, x1, y0 += dy * sumValue / value);
else treemapSlice(row, x0, y0, x0 += dx * sumValue / value, y1);
value -= sumValue, i0 = i1;
}

node.x1 = x1, node.y1 = y1;
}

squarify.ratio = function(x) {
return custom((x = +x) > 1 ? x : 1);
};

return squarify;
})((1 + Math.sqrt(5)) / 2);
})((1 + Math.sqrt(5)) / 2, false);

function resquarify(parent, x0, y0, x1, y1) {
var squarified = parent._squarify,
row,
nodes,
i,
j = -1,
n,
m = squarified.length,
value = parent.value;

while (++j < m) {
row = squarified[j], nodes = row.children;
for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
value -= row.value;
}
}

0 comments on commit 7b2aeb6

Please sign in to comment.