function squarePacking(root) {
let config = {
heuristic: "best",
metric: "chessboard",
closeFreq: 1,
closeFactor: 0.3
};
let pack = function (node) {
if (node.children) {
let arrangement = new SquareArrangement([0, 0], config);
node.children.sort((a, b) => b.value - a.value);
node.children.forEach((d) => {
pack(d);
arrangement.addSquare(d.side ** 2);
});
let { min, max } = boundingBox(arrangement.polygon);
let [xside, yside] = [max[0] - min[0], max[1] - min[1]];
let [side, dx, dy] =
xside > yside
? [xside, 0, (xside - yside) / 2]
: [yside, (yside - xside) / 2, 0];
Object.assign(node, { x: padding, y: padding, side: side + padding * 2 });
arrangement.squares.forEach((vlist, i) => {
let childNode = node.children[i];
childNode.x += vlist[0].p[0] - min[0] + dx;
childNode.y += vlist[0].p[1] - min[1] + dy;
});
} else {
Object.assign(node, {
side: Math.sqrt(node.value) + padding * 2,
x: padding,
y: padding
});
}
};
let translate = function (node, dx = 0, dy = 0) {
node.x += dx;
node.y += dy;
if (node.children) {
for (let child of node.children) {
translate(child, node.x, node.y);
}
}
};
pack(root);
translate(root);
return root;
}