treeToShapers = function (tree) {
const totalDepth = getDepth(tree);
const shapers = new Map();
function process(node, shaper, depth = 0) {
if (!shaper) {
shaper = (x, y) => y;
}
shapers.set(node.id, shaper);
const spreadPositions = stackChildren(node, true);
const stackedPositions = stackChildren(node, false);
const childDepth = depth + 1;
const fractionalChildDepth = childDepth / totalDepth;
const interpolateSpreadStacked = (childIdx, x) => {
let a = smoothstep(fractionalChildDepth, 1, x);
const s = 1 - spreadStrength;
a = a * (1 - s) + s;
return lerp(spreadPositions[childIdx], stackedPositions[childIdx], a);
};
for (let i = 0; i < node.children.length; i++) {
const childNode = node.children[i];
const childFraction = childNode.fraction;
const initialSize = childNode.initialSize ?? 0;
const doInterpolateSpreadStacked =
initialSize > 0
? (childIdx, x) => stackedPositions[childIdx]
: interpolateSpreadStacked;
const childShaper = (x, y) => {
const transformedY =
lerp(
fancystep(initialSize > 0 ? 0 : fractionalChildDepth, 1, x),
1,
initialSize
) *
childFraction *
(y - 0.5) +
0.5 +
doInterpolateSpreadStacked(i, x);
return shaper(x, transformedY);
};
process(childNode, childShaper, childDepth);
}
}
const pseudoRoot = {
id: "pseudoRoot",
fraction: 1,
children: [tree]
};
process(
pseudoRoot,
null,
-1
);
return shapers;
}