|
import {optional} from "../accessors.js"; |
|
import constant, {constantZero} from "../constant.js"; |
|
import lcg from "../lcg.js"; |
|
import {packSiblingsRandom} from "./siblings.js"; |
|
|
|
function defaultRadius(d) { |
|
return Math.sqrt(d.value); |
|
} |
|
|
|
export default function() { |
|
var radius = null, |
|
dx = 1, |
|
dy = 1, |
|
padding = constantZero; |
|
|
|
function pack(root) { |
|
const random = lcg(); |
|
root.x = dx / 2, root.y = dy / 2; |
|
if (radius) { |
|
root.eachBefore(radiusLeaf(radius)) |
|
.eachAfter(packChildrenRandom(padding, 0.5, random)) |
|
.eachBefore(translateChild(1)); |
|
} else { |
|
root.eachBefore(radiusLeaf(defaultRadius)) |
|
.eachAfter(packChildrenRandom(constantZero, 1, random)) |
|
.eachAfter(packChildrenRandom(padding, root.r / Math.min(dx, dy), random)) |
|
.eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); |
|
} |
|
return root; |
|
} |
|
|
|
pack.radius = function(x) { |
|
return arguments.length ? (radius = optional(x), pack) : radius; |
|
}; |
|
|
|
pack.size = function(x) { |
|
return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; |
|
}; |
|
|
|
pack.padding = function(x) { |
|
return arguments.length ? (padding = typeof x === "function" ? x : constant(+x), pack) : padding; |
|
}; |
|
|
|
return pack; |
|
} |
|
|
|
function radiusLeaf(radius) { |
|
return function(node) { |
|
if (!node.children) { |
|
node.r = Math.max(0, +radius(node) || 0); |
|
} |
|
}; |
|
} |
|
|
|
function packChildrenRandom(padding, k, random) { |
|
return function(node) { |
|
if (children = node.children) { |
|
var children, |
|
i, |
|
n = children.length, |
|
r = padding(node) * k || 0, |
|
e; |
|
|
|
if (r) for (i = 0; i < n; ++i) children[i].r += r; |
|
e = packSiblingsRandom(children, random); |
|
if (r) for (i = 0; i < n; ++i) children[i].r -= r; |
|
node.r = e + r; |
|
} |
|
}; |
|
} |
|
|
|
function translateChild(k) { |
|
return function(node) { |
|
var parent = node.parent; |
|
node.r *= k; |
|
if (parent) { |
|
node.x = parent.x + k * node.x; |
|
node.y = parent.y + k * node.y; |
|
} |
|
}; |
|
} |
|
|