import * as _ from 'lodash-es';
import * as util from './util.js';
export { run, cleanup };
function run(g) {
var root = util.addDummyNode(g, 'root', {}, '_root');
var depths = treeDepths(g);
var height = _.max(_.values(depths)) - 1; var nodeSep = 2 * height + 1;
g.graph().nestingRoot = root;
_.forEach(g.edges(), function (e) {
g.edge(e).minlen *= nodeSep;
});
var weight = sumWeights(g) + 1;
_.forEach(g.children(), function (child) {
dfs(g, root, nodeSep, weight, height, depths, child);
});
g.graph().nodeRankFactor = nodeSep;
}
function dfs(g, root, nodeSep, weight, height, depths, v) {
var children = g.children(v);
if (!children.length) {
if (v !== root) {
g.setEdge(root, v, { weight: 0, minlen: nodeSep });
}
return;
}
var top = util.addBorderNode(g, '_bt');
var bottom = util.addBorderNode(g, '_bb');
var label = g.node(v);
g.setParent(top, v);
label.borderTop = top;
g.setParent(bottom, v);
label.borderBottom = bottom;
_.forEach(children, function (child) {
dfs(g, root, nodeSep, weight, height, depths, child);
var childNode = g.node(child);
var childTop = childNode.borderTop ? childNode.borderTop : child;
var childBottom = childNode.borderBottom ? childNode.borderBottom : child;
var thisWeight = childNode.borderTop ? weight : 2 * weight;
var minlen = childTop !== childBottom ? 1 : height - depths[v] + 1;
g.setEdge(top, childTop, {
weight: thisWeight,
minlen: minlen,
nestingEdge: true,
});
g.setEdge(childBottom, bottom, {
weight: thisWeight,
minlen: minlen,
nestingEdge: true,
});
});
if (!g.parent(v)) {
g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });
}
}
function treeDepths(g) {
var depths = {};
function dfs(v, depth) {
var children = g.children(v);
if (children && children.length) {
_.forEach(children, function (child) {
dfs(child, depth + 1);
});
}
depths[v] = depth;
}
_.forEach(g.children(), function (v) {
dfs(v, 1);
});
return depths;
}
function sumWeights(g) {
return _.reduce(
g.edges(),
function (acc, e) {
return acc + g.edge(e).weight;
},
0
);
}
function cleanup(g) {
var graphLabel = g.graph();
g.removeNode(graphLabel.nestingRoot);
delete graphLabel.nestingRoot;
_.forEach(g.edges(), function (e) {
var edge = g.edge(e);
if (edge.nestingEdge) {
g.removeEdge(e);
}
});
}