Browse Source

feat(network): Improve the performance of the network layout engine (#2729)

* Improve the performance of the network layout engine

Short-cut the execution of a number of methods in LayoutEngine to make them
handle highly-connected graphs better.

* Demonstrations of layouts of large networks
revert-2743-editable-option-2017-02-16
Richard van der Hoff 7 years ago
committed by Alexander Wunschik
parent
commit
6acc7bdd8c
4 changed files with 5741 additions and 21 deletions
  1. +1894
    -0
      examples/network/layout/demo.jsonp
  2. +3762
    -0
      examples/network/layout/demo_big.jsonp
  3. +46
    -0
      examples/network/layout/hierarchicalLayoutBigUserDefined.html
  4. +39
    -21
      lib/network/modules/LayoutEngine.js

+ 1894
- 0
examples/network/layout/demo.jsonp
File diff suppressed because it is too large
View File


+ 3762
- 0
examples/network/layout/demo_big.jsonp
File diff suppressed because it is too large
View File


+ 46
- 0
examples/network/layout/hierarchicalLayoutBigUserDefined.html View File

@ -0,0 +1,46 @@
<!doctype html>
<html>
<head>
<title>Network | Hierarchical layout</title>
<style type="text/css">
body {
font: 10pt sans;
}
#mynetwork {
width: 600px;
height: 600px;
border: 1px solid lightgray;
}
</style>
<script type="text/javascript" src="../../../dist/vis.js"></script>
<link href="../../../dist/vis-network.min.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript">
var network = null;
function p(data) {
var container = document.getElementById('mynetwork');
var options = {
layout: {
hierarchical: {},
},
};
console.log("starting layout");
network = new vis.Network(container, data, options);
console.log("layout complete");
}
</script>
</head>
<body>
<h2>Hierarchical Layout</h2>
<div id="mynetwork"></div>
<script type="text/javascript" src="./demo.jsonp"></script>
</body>
</html>

+ 39
- 21
lib/network/modules/LayoutEngine.js View File

@ -429,6 +429,9 @@ class LayoutEngine {
// get a map of all nodes in this branch
let getBranchNodes = (source, map) => {
if (map[source.id]) {
return;
}
map[source.id] = true;
if (this.hierarchicalChildrenReference[source.id]) {
let children = this.hierarchicalChildrenReference[source.id];
@ -471,16 +474,24 @@ class LayoutEngine {
// get the maximum level of a branch.
let getMaxLevel = (nodeId) => {
let level = this.hierarchicalLevels[nodeId];
if (this.hierarchicalChildrenReference[nodeId]) {
let children = this.hierarchicalChildrenReference[nodeId];
if (children.length > 0) {
for (let i = 0; i < children.length; i++) {
level = Math.max(level,getMaxLevel(children[i]));
let accumulator = {};
let _getMaxLevel = (nodeId) => {
if (accumulator[nodeId] !== undefined) {
return accumulator[nodeId];
}
let level = this.hierarchicalLevels[nodeId];
if (this.hierarchicalChildrenReference[nodeId]) {
let children = this.hierarchicalChildrenReference[nodeId];
if (children.length > 0) {
for (let i = 0; i < children.length; i++) {
level = Math.max(level,_getMaxLevel(children[i]));
}
}
}
}
return level;
accumulator[nodeId] = level;
return level;
};
return _getMaxLevel(nodeId);
};
// check what the maximum level is these nodes have in common.
@ -532,8 +543,8 @@ class LayoutEngine {
let diffAbs = Math.abs(pos2 - pos1);
//console.log("NOW CHEcKING:", node1.id, node2.id, diffAbs);
if (diffAbs > this.options.hierarchical.nodeSpacing) {
let branchNodes1 = {}; branchNodes1[node1.id] = true;
let branchNodes2 = {}; branchNodes2[node2.id] = true;
let branchNodes1 = {};
let branchNodes2 = {};
getBranchNodes(node1, branchNodes1);
getBranchNodes(node2, branchNodes2);
@ -639,7 +650,6 @@ class LayoutEngine {
// check movable area of the branch
if (branches[node.id] === undefined) {
let branchNodes = {};
branchNodes[node.id] = true;
getBranchNodes(node, branchNodes);
branches[node.id] = branchNodes;
}
@ -1238,17 +1248,25 @@ class LayoutEngine {
* @private
*/
_shiftBlock(parentId, diff) {
if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') {
this.body.nodes[parentId].x += diff;
}
else {
this.body.nodes[parentId].y += diff;
}
if (this.hierarchicalChildrenReference[parentId] !== undefined) {
for (let i = 0; i < this.hierarchicalChildrenReference[parentId].length; i++) {
this._shiftBlock(this.hierarchicalChildrenReference[parentId][i], diff);
let progress = {};
let shifter = (parentId) => {
if (progress[parentId]) {
return;
}
}
progress[parentId] = true;
if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') {
this.body.nodes[parentId].x += diff;
}
else {
this.body.nodes[parentId].y += diff;
}
if (this.hierarchicalChildrenReference[parentId] !== undefined) {
for (let i = 0; i < this.hierarchicalChildrenReference[parentId].length; i++) {
shifter(this.hierarchicalChildrenReference[parentId][i]);
}
}
};
shifter(parentId);
}

Loading…
Cancel
Save