Browse Source

improvements on hierarchical layout

fixDataView
Alex de Mulder 9 years ago
parent
commit
1330708f63
4 changed files with 122 additions and 2575 deletions
  1. +1
    -0
      HISTORY.md
  2. +37
    -3
      dist/vis.js
  3. +35
    -2
      lib/network/modules/LayoutEngine.js
  4. +49
    -2570
      test/networkTest.html

+ 1
- 0
HISTORY.md View File

@ -21,6 +21,7 @@ http://visjs.org
- Fixed #1408: Unclustering without release function respects fixed positions now. - Fixed #1408: Unclustering without release function respects fixed positions now.
- Fixed #1358: Fixed example for clustering on zoom. - Fixed #1358: Fixed example for clustering on zoom.
- Fixed #1416: Fixed error in improvedLayout. - Fixed #1416: Fixed error in improvedLayout.
- Improvements on hierarchical layout.
### Timeline ### Timeline

+ 37
- 3
dist/vis.js View File

@ -5,7 +5,7 @@
* A dynamic, browser-based visualization library. * A dynamic, browser-based visualization library.
* *
* @version 4.9.1-SNAPSHOT * @version 4.9.1-SNAPSHOT
* @date 2015-11-26
* @date 2015-11-27
* *
* @license * @license
* Copyright (C) 2011-2015 Almende B.V, http://almende.com * Copyright (C) 2011-2015 Almende B.V, http://almende.com
@ -39644,12 +39644,45 @@ return /******/ (function(modules) { // webpackBootstrap
// check the distribution of the nodes per level. // check the distribution of the nodes per level.
var distribution = this._getDistribution(); var distribution = this._getDistribution();
// add offset to distribution
this._addOffsetsToDistribution(distribution);
// place the nodes on the canvas. // place the nodes on the canvas.
this._placeNodesByHierarchy(distribution); this._placeNodesByHierarchy(distribution);
} }
} }
} }
/**
* center align the nodes in the hierarchy for quicker display.
* @param distribution
* @private
*/
}, {
key: '_addOffsetsToDistribution',
value: function _addOffsetsToDistribution(distribution) {
var maxDistances = 0;
// get the maximum amount of distances between nodes over all levels
for (var level in distribution) {
if (distribution.hasOwnProperty(level)) {
if (maxDistances < distribution[level].amount) {
maxDistances = distribution[level].amount;
}
}
}
// o---o---o : 3 nodes, 2 disances. hence -1
maxDistances -= 1;
// set the distances for all levels but normalize on the first level (0)
var zeroLevelDistance = distribution[0].amount - 1 - maxDistances;
for (var level in distribution) {
if (distribution.hasOwnProperty(level)) {
var distances = distribution[level].amount - 1 - zeroLevelDistance;
distribution[level].distance = (maxDistances - distances) * 0.5 * this.nodeSpacing;
}
}
}
/** /**
* This function places the nodes on the canvas based on the hierarchial distribution. * This function places the nodes on the canvas based on the hierarchial distribution.
* *
@ -39674,6 +39707,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (node.x === undefined) { if (node.x === undefined) {
node.x = distribution[level].distance; node.x = distribution[level].distance;
} }
// since the placeBranchNodes can make this process not exactly sequential, we have to avoid overlap by either spacing from the node, or simply adding distance. // since the placeBranchNodes can make this process not exactly sequential, we have to avoid overlap by either spacing from the node, or simply adding distance.
distribution[level].distance = Math.max(distribution[level].distance + this.nodeSpacing, node.x + this.nodeSpacing); distribution[level].distance = Math.max(distribution[level].distance + this.nodeSpacing, node.x + this.nodeSpacing);
} else { } else {
@ -39896,13 +39930,13 @@ return /******/ (function(modules) { // webpackBootstrap
if (childNodeLevel > parentLevel) { if (childNodeLevel > parentLevel) {
if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') { if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') {
if (childNode.x === undefined) { if (childNode.x === undefined) {
childNode.x = Math.max(distribution[childNodeLevel].distance, parentNode.x);
childNode.x = Math.max(distribution[childNodeLevel].distance);
} }
distribution[childNodeLevel].distance = childNode.x + this.nodeSpacing; distribution[childNodeLevel].distance = childNode.x + this.nodeSpacing;
this.positionedNodes[childNode.id] = true; this.positionedNodes[childNode.id] = true;
} else { } else {
if (childNode.y === undefined) { if (childNode.y === undefined) {
childNode.y = Math.max(distribution[childNodeLevel].distance, parentNode.y);
childNode.y = Math.max(distribution[childNodeLevel].distance);
} }
distribution[childNodeLevel].distance = childNode.y + this.nodeSpacing; distribution[childNodeLevel].distance = childNode.y + this.nodeSpacing;
} }

+ 35
- 2
lib/network/modules/LayoutEngine.js View File

@ -325,12 +325,44 @@ class LayoutEngine {
// check the distribution of the nodes per level. // check the distribution of the nodes per level.
let distribution = this._getDistribution(); let distribution = this._getDistribution();
// add offset to distribution
this._addOffsetsToDistribution(distribution);
// place the nodes on the canvas. // place the nodes on the canvas.
this._placeNodesByHierarchy(distribution); this._placeNodesByHierarchy(distribution);
} }
} }
} }
/**
* center align the nodes in the hierarchy for quicker display.
* @param distribution
* @private
*/
_addOffsetsToDistribution(distribution) {
let maxDistances = 0;
// get the maximum amount of distances between nodes over all levels
for (let level in distribution) {
if (distribution.hasOwnProperty(level)) {
if (maxDistances < distribution[level].amount) {
maxDistances = distribution[level].amount;
}
}
}
// o---o---o : 3 nodes, 2 disances. hence -1
maxDistances -= 1;
// set the distances for all levels but normalize on the first level (0)
var zeroLevelDistance = distribution[0].amount - 1 - maxDistances;
for (let level in distribution) {
if (distribution.hasOwnProperty(level)) {
var distances = distribution[level].amount - 1 - zeroLevelDistance;
distribution[level].distance = ((maxDistances - distances) * 0.5) * this.nodeSpacing;
}
}
}
/** /**
* This function places the nodes on the canvas based on the hierarchial distribution. * This function places the nodes on the canvas based on the hierarchial distribution.
* *
@ -350,6 +382,7 @@ class LayoutEngine {
if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') { if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') {
if (node.x === undefined) {node.x = distribution[level].distance;} if (node.x === undefined) {node.x = distribution[level].distance;}
// since the placeBranchNodes can make this process not exactly sequential, we have to avoid overlap by either spacing from the node, or simply adding distance. // since the placeBranchNodes can make this process not exactly sequential, we have to avoid overlap by either spacing from the node, or simply adding distance.
distribution[level].distance = Math.max(distribution[level].distance + this.nodeSpacing, node.x + this.nodeSpacing); distribution[level].distance = Math.max(distribution[level].distance + this.nodeSpacing, node.x + this.nodeSpacing);
} }
@ -570,14 +603,14 @@ class LayoutEngine {
if (childNodeLevel > parentLevel) { if (childNodeLevel > parentLevel) {
if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') { if (this.options.hierarchical.direction === 'UD' || this.options.hierarchical.direction === 'DU') {
if (childNode.x === undefined) { if (childNode.x === undefined) {
childNode.x = Math.max(distribution[childNodeLevel].distance, parentNode.x);
childNode.x = Math.max(distribution[childNodeLevel].distance);
} }
distribution[childNodeLevel].distance = childNode.x + this.nodeSpacing; distribution[childNodeLevel].distance = childNode.x + this.nodeSpacing;
this.positionedNodes[childNode.id] = true; this.positionedNodes[childNode.id] = true;
} }
else { else {
if (childNode.y === undefined) { if (childNode.y === undefined) {
childNode.y = Math.max(distribution[childNodeLevel].distance, parentNode.y)
childNode.y = Math.max(distribution[childNodeLevel].distance)
} }
distribution[childNodeLevel].distance = childNode.y + this.nodeSpacing; distribution[childNodeLevel].distance = childNode.y + this.nodeSpacing;
} }

+ 49
- 2570
test/networkTest.html
File diff suppressed because it is too large
View File


Loading…
Cancel
Save