From 5fd89bd08392015c7a79801278d75feb2c21c0d9 Mon Sep 17 00:00:00 2001 From: Alex de Mulder Date: Tue, 15 Jul 2014 15:30:06 +0200 Subject: [PATCH] Fixed hierarchical layouts with nodes that start at a level > 0 #220 --- HISTORY.md | 1 + examples/network/27_world_cup_network.html | 1 - lib/network/Edge.js | 35 +++++++++++---- lib/network/Network.js | 2 + lib/network/mixins/HierarchicalLayoutMixin.js | 43 +++++++++++-------- 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 8c0cbe96..307ccd7c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -28,6 +28,7 @@ http://visjs.org - Updated max velocity of nodes to three times it's original value. - Made "stabilized" event fire every time the network stabilizes. - Fixed drift in dragging nodes while zooming. +- Fixed recursively constructing of hierarchical layouts. diff --git a/examples/network/27_world_cup_network.html b/examples/network/27_world_cup_network.html index a081e254..54e85cb5 100644 --- a/examples/network/27_world_cup_network.html +++ b/examples/network/27_world_cup_network.html @@ -24,7 +24,6 @@ This example shows the effect of the different types on a large network.

Also shown in this example is the inheritColor option of the edges as well as the roundness factor.
- The roundness factor is only functional with "continuous", "discrete" and "diagonalCross".

To improve performance, the physics have been disabled with:
{barnesHut: {gravitationalConstant: 0, centralGravity: 0, springConstant: 0}}
and we have enabled diff --git a/lib/network/Edge.js b/lib/network/Edge.js index 9c11c94f..99a49245 100644 --- a/lib/network/Edge.js +++ b/lib/network/Edge.js @@ -361,9 +361,6 @@ Edge.prototype._getViaCoordinates = function () { var yVia = null; var factor = this.smoothCurves.roundness; var type = this.smoothCurves.type; - if (factor == 0) { - return {x:null,y:null}; - } var dx = Math.abs(this.from.x - this.to.x); var dy = Math.abs(this.from.y - this.to.y); @@ -420,22 +417,42 @@ Edge.prototype._getViaCoordinates = function () { } } else if (type == "straightCross") { - if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { + if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { // up - down xVia = this.from.x; - yVia = this.to.y + if (this.from.y < this.to.y) { + yVia = this.to.y - (1-factor) * dy; + } + else { + yVia = this.to.y + (1-factor) * dy; + } } - else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { - xVia = this.to.x; + else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { // left - right + if (this.from.x < this.to.x) { + xVia = this.to.x - (1-factor) * dx; + } + else { + xVia = this.to.x + (1-factor) * dx; + } yVia = this.from.y; } } else if (type == 'horizontal') { - xVia = this.to.x; + if (this.from.x < this.to.x) { + xVia = this.to.x - (1-factor) * dx; + } + else { + xVia = this.to.x + (1-factor) * dx; + } yVia = this.from.y; } else if (type == 'vertical') { xVia = this.from.x; - yVia = this.to.y; + if (this.from.y < this.to.y) { + yVia = this.to.y - (1-factor) * dy; + } + else { + yVia = this.to.y + (1-factor) * dy; + } } else { // continuous if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { diff --git a/lib/network/Network.js b/lib/network/Network.js index b9ac51ee..16a99330 100644 --- a/lib/network/Network.js +++ b/lib/network/Network.js @@ -1068,6 +1068,8 @@ Network.prototype._onDragEnd = function () { s.node.xFixed = s.xFixed; s.node.yFixed = s.yFixed; }); + this.moving = true; + this.start(); } this._redraw(); }; diff --git a/lib/network/mixins/HierarchicalLayoutMixin.js b/lib/network/mixins/HierarchicalLayoutMixin.js index 78f75373..b866774d 100644 --- a/lib/network/mixins/HierarchicalLayoutMixin.js +++ b/lib/network/mixins/HierarchicalLayoutMixin.js @@ -94,26 +94,31 @@ exports._placeNodesByHierarchy = function(distribution) { var nodeId, node; // start placing all the level 0 nodes first. Then recursively position their branches. - for (nodeId in distribution[0].nodes) { - if (distribution[0].nodes.hasOwnProperty(nodeId)) { - node = distribution[0].nodes[nodeId]; - if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { - if (node.xFixed) { - node.x = distribution[0].minPos; - node.xFixed = false; - - distribution[0].minPos += distribution[0].nodeSpacing; - } - } - else { - if (node.yFixed) { - node.y = distribution[0].minPos; - node.yFixed = false; + for (var level in distribution) { + if (distribution.hasOwnProperty(level)) { - distribution[0].minPos += distribution[0].nodeSpacing; + for (nodeId in distribution[level].nodes) { + if (distribution[level].nodes.hasOwnProperty(nodeId)) { + node = distribution[level].nodes[nodeId]; + if (this.constants.hierarchicalLayout.direction == "UD" || this.constants.hierarchicalLayout.direction == "DU") { + if (node.xFixed) { + node.x = distribution[level].minPos; + node.xFixed = false; + + distribution[level].minPos += distribution[level].nodeSpacing; + } + } + else { + if (node.yFixed) { + node.y = distribution[level].minPos; + node.yFixed = false; + + distribution[level].minPos += distribution[level].nodeSpacing; + } + } + this._placeBranchNodes(node.edges,node.id,distribution,node.level); } } - this._placeBranchNodes(node.edges,node.id,distribution,node.level); } } @@ -145,11 +150,11 @@ exports._getDistribution = function() { else { node.x = this.constants.hierarchicalLayout.levelSeparation*node.level; } - if (!distribution.hasOwnProperty(node.level)) { + if (distribution[node.level] === undefined) { distribution[node.level] = {amount: 0, nodes: {}, minPos:0, nodeSpacing:0}; } distribution[node.level].amount += 1; - distribution[node.level].nodes[node.id] = node; + distribution[node.level].nodes[nodeId] = node; } }