// wrap tree node // TODO considering size var util = require('../util'); function WrappedTree(height, children) { if (height === void 0) { height = 0; } if (children === void 0) { children = []; } var me = this; me.x = me.y = 0; me.leftChild = me.rightChild = null; me.height = 0; me.children = children; } var DEFAULT_OPTIONS = { isHorizontal: true, nodeSep: 20, nodeSize: 20, rankSep: 200, subTreeSep: 10 }; function convertBack(converted /* WrappedTree */ , root /* TreeNode */ , isHorizontal) { if (isHorizontal) { root.x = converted.x; root.y = converted.y; } else { root.x = converted.y; root.y = converted.x; } converted.children.forEach(function (child, i) { convertBack(child, root.children[i], isHorizontal); }); } module.exports = function (root, options) { if (options === void 0) { options = {}; } options = util.assign({}, DEFAULT_OPTIONS, options); var maxDepth = 0; function wrappedTreeFromNode(n) { if (!n) return null; n.width = 0; if (n.depth && n.depth > maxDepth) { maxDepth = n.depth; // get the max depth } var children = n.children; var childrenCount = children.length; var t = new WrappedTree(n.height, []); children.forEach(function (child, i) { var childWT = wrappedTreeFromNode(child); t.children.push(childWT); if (i === 0) { // t.leftChild = childWT.leftChild ? childWT.leftChild : childWT t.leftChild = childWT; } if (i === childrenCount - 1) { // t.rightChild = childWT.rightChild ? childWT.rightChild : childWT t.rightChild = childWT; } }); t.originNode = n; t.isLeaf = n.isLeaf(); return t; } function getDrawingDepth(t) { if (t.isLeaf || t.children.length === 0) { t.drawingDepth = maxDepth; } else { var depths = t.children.map(function (child) { return getDrawingDepth(child); }); var minChildDepth = Math.min.apply(null, depths); t.drawingDepth = minChildDepth - 1; } return t.drawingDepth; } var prevLeaf; function position(t) { t.x = t.drawingDepth * options.rankSep; if (t.isLeaf) { t.y = 0; if (prevLeaf) { t.y = prevLeaf.y + prevLeaf.height + options.nodeSep; if (t.originNode.parent !== prevLeaf.originNode.parent) { t.y += options.subTreeSep; } } prevLeaf = t; } else { t.children.forEach(function (child) { position(child); }); t.y = (t.leftChild.y + t.rightChild.y) / 2; } } // wrap node var wt = wrappedTreeFromNode(root); // get depth for drawing getDrawingDepth(wt); // get position position(wt); // get x, y convertBack(wt, root, options.isHorizontal); return root; };