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;
}
}