Browse Source

- Fixed #1529, clustering and declustering now respects the original settings of the edges for physics and hidden.

codeClimate
Alex de Mulder 8 years ago
parent
commit
ceac4bf6a4
7 changed files with 117 additions and 94 deletions
  1. +1
    -0
      HISTORY.md
  2. +58
    -46
      dist/vis.js
  3. +4
    -4
      docs/network/index.html
  4. +4
    -8
      lib/network/NetworkUtil.js
  5. +42
    -28
      lib/network/modules/Clustering.js
  6. +5
    -5
      lib/network/modules/LayoutEngine.js
  7. +3
    -3
      lib/network/modules/View.js

+ 1
- 0
HISTORY.md View File

@ -13,6 +13,7 @@ http://visjs.org
- Fixed #1531 , #1335: border distances for arrow positioning
- Fixed findNode method. It now does not return internal objects anymore.
- Fixed #1529, clustering and declustering now respects the original settings of the edges for physics and hidden.
## 2015-12-18, version 4.11.0

+ 58
- 46
dist/vis.js View File

@ -35752,13 +35752,14 @@ return /******/ (function(modules) { // webpackBootstrap
this.body = body;
this.clusteredNodes = {};
this.clusteredEdges = {};
this.options = {};
this.defaultOptions = {};
util.extend(this.options, this.defaultOptions);
this.body.emitter.on('_resetData', function () {
_this.clusteredNodes = {};
_this.clusteredNodes = {};_this.clusteredEdges = {};
});
}
@ -35823,14 +35824,14 @@ return /******/ (function(modules) { // webpackBootstrap
for (var i = 0; i < this.body.nodeIndices.length; i++) {
var nodeId = this.body.nodeIndices[i];
var node = this.body.nodes[nodeId];
var clonedOptions = _NetworkUtil2['default']._cloneOptions(node);
var clonedOptions = _NetworkUtil2['default'].cloneOptions(node);
if (options.joinCondition(clonedOptions) === true) {
childNodesObj[nodeId] = this.body.nodes[nodeId];
// collect the nodes that will be in the cluster
for (var _i = 0; _i < node.edges.length; _i++) {
var edge = node.edges[_i];
if (edge.hiddenByCluster !== true) {
if (this.clusteredEdges[edge.id] === undefined) {
childEdgesObj[edge.id] = edge;
}
}
@ -35872,7 +35873,7 @@ return /******/ (function(modules) { // webpackBootstrap
edges = [];
for (var j = 0; j < node.edges.length; j++) {
edge = node.edges[j];
if (edge.hiddenByCluster !== true) {
if (this.clusteredEdges[edge.id] === undefined) {
if (edge.toId !== edge.fromId) {
relevantEdgeCount++;
}
@ -35893,7 +35894,7 @@ return /******/ (function(modules) { // webpackBootstrap
childNodesObj[childNodeId] = this.body.nodes[childNodeId];
usedNodes[nodeId] = true;
} else {
var clonedOptions = _NetworkUtil2['default']._cloneOptions(this.body.nodes[nodeId]);
var clonedOptions = _NetworkUtil2['default'].cloneOptions(this.body.nodes[nodeId]);
if (options.joinCondition(clonedOptions) === true) {
childEdgesObj[edge.id] = edge;
childNodesObj[nodeId] = this.body.nodes[nodeId];
@ -35985,16 +35986,16 @@ return /******/ (function(modules) { // webpackBootstrap
var childNodesObj = {};
var childEdgesObj = {};
var parentNodeId = node.id;
var parentClonedOptions = _NetworkUtil2['default']._cloneOptions(node);
var parentClonedOptions = _NetworkUtil2['default'].cloneOptions(node);
childNodesObj[parentNodeId] = node;
// collect the nodes that will be in the cluster
for (var i = 0; i < node.edges.length; i++) {
var edge = node.edges[i];
if (edge.hiddenByCluster !== true) {
if (this.clusteredEdges[edge.id] === undefined) {
var childNodeId = this._getConnectedId(edge, parentNodeId);
// if the child node is not in a cluster (may not be needed now with the edge.hiddenByCluster check)
// if the child node is not in a cluster
if (this.clusteredNodes[childNodeId] === undefined) {
if (childNodeId !== parentNodeId) {
if (options.joinCondition === undefined) {
@ -36002,7 +36003,7 @@ return /******/ (function(modules) { // webpackBootstrap
childNodesObj[childNodeId] = this.body.nodes[childNodeId];
} else {
// clone the options and insert some additional parameters that could be interesting.
var childClonedOptions = _NetworkUtil2['default']._cloneOptions(this.body.nodes[childNodeId]);
var childClonedOptions = _NetworkUtil2['default'].cloneOptions(this.body.nodes[childNodeId]);
if (options.joinCondition(parentClonedOptions, childClonedOptions) === true) {
childEdgesObj[edge.id] = edge;
childNodesObj[childNodeId] = this.body.nodes[childNodeId];
@ -36024,8 +36025,9 @@ return /******/ (function(modules) { // webpackBootstrap
* It looks for edges that are connected to the nodes from the "outside' of the cluster.
*
* @param childNodesObj
* @param newEdges
* @param options
* @param childEdgesObj
* @param clusterNodeProperties
* @param clusterEdgeProperties
* @private
*/
}, {
@ -36050,7 +36052,7 @@ return /******/ (function(modules) { // webpackBootstrap
for (var j = 0; j < childNode.edges.length; j++) {
edge = childNode.edges[j];
// we only handle edges that are visible to the system, not the disabled ones from the clustering process.
if (edge.hiddenByCluster !== true) {
if (this.clusteredEdges[edge.id] === undefined) {
// self-referencing edges will be added to the "hidden" list
if (edge.toId == edge.fromId) {
childEdgesObj[edge.id] = edge;
@ -36081,7 +36083,7 @@ return /******/ (function(modules) { // webpackBootstrap
for (var j = 0; j < createEdges.length; j++) {
var _edge = createEdges[j].edge;
// copy the options of the edge we will replace
var clonedOptions = _NetworkUtil2['default']._cloneOptions(_edge, 'edge');
var clonedOptions = _NetworkUtil2['default'].cloneOptions(_edge, 'edge');
// make sure the properties of clusterEdges are superimposed on it
util.deepExtend(clonedOptions, clusterEdgeProperties);
@ -36100,8 +36102,8 @@ return /******/ (function(modules) { // webpackBootstrap
newEdge.connect();
// hide the replaced edge
this._backupEdgeOptions(_edge);
_edge.setOptions({ physics: false, hidden: true });
_edge.hiddenByCluster = true;
}
}
@ -36140,7 +36142,7 @@ return /******/ (function(modules) { // webpackBootstrap
value: function _cluster(childNodesObj, childEdgesObj, options) {
var refreshData = arguments.length <= 3 || arguments[3] === undefined ? true : arguments[3];
// kill condition: no children so can't cluster or only one node in the cluster, dont bother
// kill condition: no children so can't cluster or only one node in the cluster, don't bother
if (Object.keys(childNodesObj).length < 2) {
return;
}
@ -36162,18 +36164,18 @@ return /******/ (function(modules) { // webpackBootstrap
var childNodesOptions = [];
for (var nodeId in childNodesObj) {
if (childNodesObj.hasOwnProperty(nodeId)) {
var clonedOptions = _NetworkUtil2['default']._cloneOptions(childNodesObj[nodeId]);
var clonedOptions = _NetworkUtil2['default'].cloneOptions(childNodesObj[nodeId]);
childNodesOptions.push(clonedOptions);
}
}
// get clusterproperties based on childNodes
// get cluster properties based on childNodes
var childEdgesOptions = [];
for (var edgeId in childEdgesObj) {
if (childEdgesObj.hasOwnProperty(edgeId)) {
// these cluster edges will be removed on creation of the cluster.
if (edgeId.substr(0, 12) !== "clusterEdge:") {
var clonedOptions = _NetworkUtil2['default']._cloneOptions(childEdgesObj[edgeId], 'edge');
var clonedOptions = _NetworkUtil2['default'].cloneOptions(childEdgesObj[edgeId], 'edge');
childEdgesOptions.push(clonedOptions);
}
}
@ -36195,7 +36197,7 @@ return /******/ (function(modules) { // webpackBootstrap
clusterNodeProperties.label = 'cluster';
}
// give the clusterNode a postion if it does not have one.
// give the clusterNode a position if it does not have one.
var pos = undefined;
if (clusterNodeProperties.x === undefined) {
pos = this._getClusterPosition(childNodesObj);
@ -36230,8 +36232,10 @@ return /******/ (function(modules) { // webpackBootstrap
if (childEdgesObj.hasOwnProperty(edgeId)) {
if (this.body.edges[edgeId] !== undefined) {
var edge = this.body.edges[edgeId];
// cache the options before changing
this._backupEdgeOptions(edge);
// disable physics and hide the edge
edge.setOptions({ physics: false, hidden: true });
edge.hiddenByCluster = true;
}
}
}
@ -36252,6 +36256,22 @@ return /******/ (function(modules) { // webpackBootstrap
this.body.emitter.emit('_dataChanged');
}
}
}, {
key: '_backupEdgeOptions',
value: function _backupEdgeOptions(edge) {
if (this.clusteredEdges[edge.id] === undefined) {
this.clusteredEdges[edge.id] = { physics: edge.options.physics, hidden: edge.options.hidden };
}
}
}, {
key: '_restoreEdge',
value: function _restoreEdge(edge) {
var originalOptions = this.clusteredEdges[edge.id];
if (originalOptions !== undefined) {
edge.setOptions({ physics: originalOptions.physics, hidden: originalOptions.hidden });
delete this.clusteredEdges[edge.id];
}
}
/**
* Check if a node is a cluster.
@ -36367,7 +36387,7 @@ return /******/ (function(modules) { // webpackBootstrap
containedNode.vx = clusterNode.vx;
containedNode.vy = clusterNode.vy;
// we use these methods to avoid reinstantiating the shape, which happens with setOptions.
// we use these methods to avoid re-instantiating the shape, which happens with setOptions.
containedNode.setOptions({ hidden: false, physics: true });
delete this.clusteredNodes[nodeId];
@ -36407,7 +36427,7 @@ return /******/ (function(modules) { // webpackBootstrap
}
// clone the options and apply the cluster options to them
var clonedOptions = _NetworkUtil2['default']._cloneOptions(transferEdge, 'edge');
var clonedOptions = _NetworkUtil2['default'].cloneOptions(transferEdge, 'edge');
util.deepExtend(clonedOptions, otherCluster.clusterEdgeProperties);
// apply the edge specific options to it.
@ -36423,8 +36443,7 @@ return /******/ (function(modules) { // webpackBootstrap
} else {
var replacedEdge = this.body.edges[edge.clusteringEdgeReplacingId];
if (replacedEdge !== undefined) {
replacedEdge.setOptions({ physics: true, hidden: false });
replacedEdge.hiddenByCluster = false;
this._restoreEdge(replacedEdge);
}
}
edge.cleanup();
@ -36436,10 +36455,7 @@ return /******/ (function(modules) { // webpackBootstrap
// handle the releasing of the edges
for (var edgeId in containedEdges) {
if (containedEdges.hasOwnProperty(edgeId)) {
var edge = containedEdges[edgeId];
edge.setOptions({ physics: true, hidden: false });
edge.hiddenByCluster = undefined;
delete edge.hiddenByCluster;
this._restoreEdge(containedEdges[edgeId]);
}
}
@ -36575,12 +36591,11 @@ return /******/ (function(modules) { // webpackBootstrap
/**
* Find the center position of the network considering the bounding boxes
* @private
*/
_createClass(NetworkUtil, null, [{
key: "_getRange",
value: function _getRange(allNodes) {
key: "getRange",
value: function getRange(allNodes) {
var specificNodes = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
var minY = 1e9,
@ -36614,11 +36629,10 @@ return /******/ (function(modules) { // webpackBootstrap
/**
* Find the center position of the network
* @private
*/
}, {
key: "_getRangeCore",
value: function _getRangeCore(allNodes) {
key: "getRangeCore",
value: function getRangeCore(allNodes) {
var specificNodes = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
var minY = 1e9,
@ -36653,11 +36667,10 @@ return /******/ (function(modules) { // webpackBootstrap
/**
* @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY};
* @returns {{x: number, y: number}}
* @private
*/
}, {
key: "_findCenter",
value: function _findCenter(range) {
key: "findCenter",
value: function findCenter(range) {
return { x: 0.5 * (range.maxX + range.minX),
y: 0.5 * (range.maxY + range.minY) };
}
@ -36667,11 +36680,10 @@ return /******/ (function(modules) { // webpackBootstrap
* @param item
* @param type
* @returns {{}}
* @private
*/
}, {
key: "_cloneOptions",
value: function _cloneOptions(item, type) {
key: "cloneOptions",
value: function cloneOptions(item, type) {
var clonedOptions = {};
if (type === undefined || type === 'node') {
util.deepExtend(clonedOptions, item.options, true);
@ -37654,7 +37666,7 @@ return /******/ (function(modules) { // webpackBootstrap
return;
}
range = _NetworkUtil2['default']._getRange(this.body.nodes, options.nodes);
range = _NetworkUtil2['default'].getRange(this.body.nodes, options.nodes);
var numberOfNodes = this.body.nodeIndices.length;
zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good.
@ -37664,7 +37676,7 @@ return /******/ (function(modules) { // webpackBootstrap
zoomLevel *= factor;
} else {
this.body.emitter.emit("_resizeNodes");
range = _NetworkUtil2['default']._getRange(this.body.nodes, options.nodes);
range = _NetworkUtil2['default'].getRange(this.body.nodes, options.nodes);
var xDistance = Math.abs(range.maxX - range.minX) * 1.1;
var yDistance = Math.abs(range.maxY - range.minY) * 1.1;
@ -37681,7 +37693,7 @@ return /******/ (function(modules) { // webpackBootstrap
zoomLevel = 1.0;
}
var center = _NetworkUtil2['default']._findCenter(range);
var center = _NetworkUtil2['default'].findCenter(range);
var animationOptions = { position: center, scale: zoomLevel, animation: options.animation };
this.moveTo(animationOptions);
}
@ -40159,8 +40171,8 @@ return /******/ (function(modules) { // webpackBootstrap
}, {
key: '_shiftToCenter',
value: function _shiftToCenter() {
var range = _NetworkUtil2['default']._getRangeCore(this.body.nodes, this.body.nodeIndices);
var center = _NetworkUtil2['default']._findCenter(range);
var range = _NetworkUtil2['default'].getRangeCore(this.body.nodes, this.body.nodeIndices);
var center = _NetworkUtil2['default'].findCenter(range);
for (var i = 0; i < this.body.nodeIndices.length; i++) {
this.body.nodes[this.body.nodeIndices[i]].x -= center.x;
this.body.nodes[this.body.nodeIndices[i]].y -= center.y;
@ -40423,7 +40435,7 @@ return /******/ (function(modules) { // webpackBootstrap
_this3.hierarchicalLevels[nodeA.id] = minLevel;
}
var diff = customCallback(_NetworkUtil2['default']._cloneOptions(nodeA, 'node'), _NetworkUtil2['default']._cloneOptions(nodeB, 'node'), _NetworkUtil2['default']._cloneOptions(edge, 'edge'));
var diff = customCallback(_NetworkUtil2['default'].cloneOptions(nodeA, 'node'), _NetworkUtil2['default'].cloneOptions(nodeB, 'node'), _NetworkUtil2['default'].cloneOptions(edge, 'edge'));
_this3.hierarchicalLevels[nodeB.id] = _this3.hierarchicalLevels[nodeA.id] + diff;
};

+ 4
- 4
docs/network/index.html View File

@ -1319,19 +1319,19 @@ var options = {
</tr>
<tr><td id="event_hoverNode">hoverNode</td>
<td><code>{node: nodeId}</code></td>
<td>Fired interaction:{hover:true} and the mouse hovers over a node.</td>
<td>Fired if the option <code>interaction:{hover:true}</code> is enabled and the mouse hovers over a node.</td>
</tr>
<tr><td id="event_blurNode">blurNode</td>
<td><code>{node: nodeId}</code></td>
<td>Fired interaction:{hover:true} and the mouse moved away from a node it was hovering over before.</td>
<td>Fired if the option <code>interaction:{hover:true}</code> is enabled and the mouse moved away from a node it was hovering over before.</td>
</tr>
<tr><td id="event_hoverEdge">hoverEdge</td>
<td><code>{edge: edgeId}</code></td>
<td>Fired interaction:{hover:true} and the mouse hovers over an edge.</td>
<td>Fired if the option <code>interaction:{hover:true}</code> is enabled and the mouse hovers over an edge.</td>
</tr>
<tr><td id="event_blurEdge">blurEdge</td>
<td><code>{edge: edgeId}</code></td>
<td>Fired interaction:{hover:true} and the mouse moved away from an edge it was hovering over before.</td>
<td>Fired if the option <code>interaction:{hover:true}</code> is enabled and the mouse moved away from an edge it was hovering over before.</td>
</tr>
<tr><td id="event_zoom">zoom</td>
<td><code>{direction:'+'/'-', scale: Number}</code></td>

+ 4
- 8
lib/network/NetworkUtil.js View File

@ -4,9 +4,8 @@ class NetworkUtil {
/**
* Find the center position of the network considering the bounding boxes
* @private
*/
static _getRange(allNodes, specificNodes = []) {
static getRange(allNodes, specificNodes = []) {
var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node;
if (specificNodes.length > 0) {
for (var i = 0; i < specificNodes.length; i++) {
@ -34,9 +33,8 @@ class NetworkUtil {
/**
* Find the center position of the network
* @private
*/
static _getRangeCore(allNodes, specificNodes = []) {
static getRangeCore(allNodes, specificNodes = []) {
var minY = 1e9, maxY = -1e9, minX = 1e9, maxX = -1e9, node;
if (specificNodes.length > 0) {
for (var i = 0; i < specificNodes.length; i++) {
@ -66,9 +64,8 @@ class NetworkUtil {
/**
* @param {object} range = {minX: minX, maxX: maxX, minY: minY, maxY: maxY};
* @returns {{x: number, y: number}}
* @private
*/
static _findCenter(range) {
static findCenter(range) {
return {x: (0.5 * (range.maxX + range.minX)),
y: (0.5 * (range.maxY + range.minY))};
}
@ -79,9 +76,8 @@ class NetworkUtil {
* @param item
* @param type
* @returns {{}}
* @private
*/
static _cloneOptions(item, type) {
static cloneOptions(item, type) {
let clonedOptions = {};
if (type === undefined || type === 'node') {
util.deepExtend(clonedOptions, item.options, true);

+ 42
- 28
lib/network/modules/Clustering.js View File

@ -6,12 +6,13 @@ class ClusterEngine {
constructor(body) {
this.body = body;
this.clusteredNodes = {};
this.clusteredEdges = {};
this.options = {};
this.defaultOptions = {};
util.extend(this.options, this.defaultOptions);
this.body.emitter.on('_resetData', () => {this.clusteredNodes = {};})
this.body.emitter.on('_resetData', () => {this.clusteredNodes = {}; this.clusteredEdges = {};})
}
setOptions(options) {
@ -68,14 +69,14 @@ class ClusterEngine {
for (let i = 0; i < this.body.nodeIndices.length; i++) {
let nodeId = this.body.nodeIndices[i];
let node = this.body.nodes[nodeId];
let clonedOptions = NetworkUtil._cloneOptions(node);
let clonedOptions = NetworkUtil.cloneOptions(node);
if (options.joinCondition(clonedOptions) === true) {
childNodesObj[nodeId] = this.body.nodes[nodeId];
// collect the nodes that will be in the cluster
for (let i = 0; i < node.edges.length; i++) {
let edge = node.edges[i];
if (edge.hiddenByCluster !== true) {
if (this.clusteredEdges[edge.id] === undefined) {
childEdgesObj[edge.id] = edge;
}
}
@ -110,7 +111,7 @@ class ClusterEngine {
edges = [];
for (let j = 0; j < node.edges.length; j++) {
edge = node.edges[j];
if (edge.hiddenByCluster !== true) {
if (this.clusteredEdges[edge.id] === undefined) {
if (edge.toId !== edge.fromId) {
relevantEdgeCount++;
}
@ -132,7 +133,7 @@ class ClusterEngine {
usedNodes[nodeId] = true;
}
else {
let clonedOptions = NetworkUtil._cloneOptions(this.body.nodes[nodeId]);
let clonedOptions = NetworkUtil.cloneOptions(this.body.nodes[nodeId]);
if (options.joinCondition(clonedOptions) === true) {
childEdgesObj[edge.id] = edge;
childNodesObj[nodeId] = this.body.nodes[nodeId];
@ -208,16 +209,16 @@ class ClusterEngine {
let childNodesObj = {};
let childEdgesObj = {};
let parentNodeId = node.id;
let parentClonedOptions = NetworkUtil._cloneOptions(node);
let parentClonedOptions = NetworkUtil.cloneOptions(node);
childNodesObj[parentNodeId] = node;
// collect the nodes that will be in the cluster
for (let i = 0; i < node.edges.length; i++) {
let edge = node.edges[i];
if (edge.hiddenByCluster !== true) {
if (this.clusteredEdges[edge.id] === undefined) {
let childNodeId = this._getConnectedId(edge, parentNodeId);
// if the child node is not in a cluster (may not be needed now with the edge.hiddenByCluster check)
// if the child node is not in a cluster
if (this.clusteredNodes[childNodeId] === undefined) {
if (childNodeId !== parentNodeId) {
if (options.joinCondition === undefined) {
@ -226,7 +227,7 @@ class ClusterEngine {
}
else {
// clone the options and insert some additional parameters that could be interesting.
let childClonedOptions = NetworkUtil._cloneOptions(this.body.nodes[childNodeId]);
let childClonedOptions = NetworkUtil.cloneOptions(this.body.nodes[childNodeId]);
if (options.joinCondition(parentClonedOptions, childClonedOptions) === true) {
childEdgesObj[edge.id] = edge;
childNodesObj[childNodeId] = this.body.nodes[childNodeId];
@ -250,8 +251,9 @@ class ClusterEngine {
* It looks for edges that are connected to the nodes from the "outside' of the cluster.
*
* @param childNodesObj
* @param newEdges
* @param options
* @param childEdgesObj
* @param clusterNodeProperties
* @param clusterEdgeProperties
* @private
*/
_createClusterEdges (childNodesObj, childEdgesObj, clusterNodeProperties, clusterEdgeProperties) {
@ -269,7 +271,7 @@ class ClusterEngine {
for (let j = 0; j < childNode.edges.length; j++) {
edge = childNode.edges[j];
// we only handle edges that are visible to the system, not the disabled ones from the clustering process.
if (edge.hiddenByCluster !== true) {
if (this.clusteredEdges[edge.id] === undefined) {
// self-referencing edges will be added to the "hidden" list
if (edge.toId == edge.fromId) {
childEdgesObj[edge.id] = edge;
@ -301,7 +303,7 @@ class ClusterEngine {
for (let j = 0; j < createEdges.length; j++) {
let edge = createEdges[j].edge;
// copy the options of the edge we will replace
let clonedOptions = NetworkUtil._cloneOptions(edge, 'edge');
let clonedOptions = NetworkUtil.cloneOptions(edge, 'edge');
// make sure the properties of clusterEdges are superimposed on it
util.deepExtend(clonedOptions, clusterEdgeProperties);
@ -320,8 +322,8 @@ class ClusterEngine {
newEdge.connect();
// hide the replaced edge
this._backupEdgeOptions(edge);
edge.setOptions({physics:false, hidden:true});
edge.hiddenByCluster = true;
}
}
@ -349,7 +351,7 @@ class ClusterEngine {
* @private
*/
_cluster(childNodesObj, childEdgesObj, options, refreshData = true) {
// kill condition: no children so can't cluster or only one node in the cluster, dont bother
// kill condition: no children so can't cluster or only one node in the cluster, don't bother
if (Object.keys(childNodesObj).length < 2) {return;}
// check if this cluster call is not trying to cluster anything that is in another cluster.
@ -369,18 +371,18 @@ class ClusterEngine {
let childNodesOptions = [];
for (let nodeId in childNodesObj) {
if (childNodesObj.hasOwnProperty(nodeId)) {
let clonedOptions = NetworkUtil._cloneOptions(childNodesObj[nodeId]);
let clonedOptions = NetworkUtil.cloneOptions(childNodesObj[nodeId]);
childNodesOptions.push(clonedOptions);
}
}
// get clusterproperties based on childNodes
// get cluster properties based on childNodes
let childEdgesOptions = [];
for (let edgeId in childEdgesObj) {
if (childEdgesObj.hasOwnProperty(edgeId)) {
// these cluster edges will be removed on creation of the cluster.
if (edgeId.substr(0, 12) !== "clusterEdge:") {
let clonedOptions = NetworkUtil._cloneOptions(childEdgesObj[edgeId], 'edge');
let clonedOptions = NetworkUtil.cloneOptions(childEdgesObj[edgeId], 'edge');
childEdgesOptions.push(clonedOptions);
}
}
@ -401,7 +403,7 @@ class ClusterEngine {
}
// give the clusterNode a postion if it does not have one.
// give the clusterNode a position if it does not have one.
let pos = undefined;
if (clusterNodeProperties.x === undefined) {
pos = this._getClusterPosition(childNodesObj);
@ -434,8 +436,10 @@ class ClusterEngine {
if (childEdgesObj.hasOwnProperty(edgeId)) {
if (this.body.edges[edgeId] !== undefined) {
let edge = this.body.edges[edgeId];
// cache the options before changing
this._backupEdgeOptions(edge);
// disable physics and hide the edge
edge.setOptions({physics:false, hidden:true});
edge.hiddenByCluster = true;
}
}
}
@ -457,6 +461,20 @@ class ClusterEngine {
}
}
_backupEdgeOptions(edge) {
if (this.clusteredEdges[edge.id] === undefined) {
this.clusteredEdges[edge.id] = {physics: edge.options.physics, hidden: edge.options.hidden};
}
}
_restoreEdge(edge) {
let originalOptions = this.clusteredEdges[edge.id];
if (originalOptions !== undefined) {
edge.setOptions({physics: originalOptions.physics, hidden: originalOptions.hidden});
delete this.clusteredEdges[edge.id];
}
}
/**
* Check if a node is a cluster.
@ -561,7 +579,7 @@ class ClusterEngine {
containedNode.vx = clusterNode.vx;
containedNode.vy = clusterNode.vy;
// we use these methods to avoid reinstantiating the shape, which happens with setOptions.
// we use these methods to avoid re-instantiating the shape, which happens with setOptions.
containedNode.setOptions({hidden:false, physics:true});
delete this.clusteredNodes[nodeId];
@ -602,7 +620,7 @@ class ClusterEngine {
}
// clone the options and apply the cluster options to them
let clonedOptions = NetworkUtil._cloneOptions(transferEdge, 'edge');
let clonedOptions = NetworkUtil.cloneOptions(transferEdge, 'edge');
util.deepExtend(clonedOptions, otherCluster.clusterEdgeProperties);
// apply the edge specific options to it.
@ -619,8 +637,7 @@ class ClusterEngine {
else {
let replacedEdge = this.body.edges[edge.clusteringEdgeReplacingId];
if (replacedEdge !== undefined) {
replacedEdge.setOptions({physics: true, hidden: false});
replacedEdge.hiddenByCluster = false;
this._restoreEdge(replacedEdge);
}
}
edge.cleanup();
@ -632,10 +649,7 @@ class ClusterEngine {
// handle the releasing of the edges
for (let edgeId in containedEdges) {
if (containedEdges.hasOwnProperty(edgeId)) {
let edge = containedEdges[edgeId];
edge.setOptions({physics: true, hidden: false});
edge.hiddenByCluster = undefined;
delete edge.hiddenByCluster;
this._restoreEdge(containedEdges[edgeId]);
}
}

+ 5
- 5
lib/network/modules/LayoutEngine.js View File

@ -249,8 +249,8 @@ class LayoutEngine {
* @private
*/
_shiftToCenter() {
let range = NetworkUtil._getRangeCore(this.body.nodes, this.body.nodeIndices);
let center = NetworkUtil._findCenter(range);
let range = NetworkUtil.getRangeCore(this.body.nodes, this.body.nodeIndices);
let center = NetworkUtil.findCenter(range);
for (let i = 0; i < this.body.nodeIndices.length; i++) {
this.body.nodes[this.body.nodeIndices[i]].x -= center.x;
this.body.nodes[this.body.nodeIndices[i]].y -= center.y;
@ -501,9 +501,9 @@ class LayoutEngine {
if (levelA === undefined) {this.hierarchicalLevels[nodeA.id] = minLevel;}
let diff = customCallback(
NetworkUtil._cloneOptions(nodeA,'node'),
NetworkUtil._cloneOptions(nodeB,'node'),
NetworkUtil._cloneOptions(edge,'edge')
NetworkUtil.cloneOptions(nodeA,'node'),
NetworkUtil.cloneOptions(nodeB,'node'),
NetworkUtil.cloneOptions(edge,'edge')
);
this.hierarchicalLevels[nodeB.id] = this.hierarchicalLevels[nodeA.id] + diff;

+ 3
- 3
lib/network/modules/View.js View File

@ -60,7 +60,7 @@ class View {
return;
}
range = NetworkUtil._getRange(this.body.nodes, options.nodes);
range = NetworkUtil.getRange(this.body.nodes, options.nodes);
let numberOfNodes = this.body.nodeIndices.length;
zoomLevel = 12.662 / (numberOfNodes + 7.4147) + 0.0964822; // this is obtained from fitting a dataset from 5 points with scale levels that looked good.
@ -71,7 +71,7 @@ class View {
}
else {
this.body.emitter.emit("_resizeNodes");
range = NetworkUtil._getRange(this.body.nodes, options.nodes);
range = NetworkUtil.getRange(this.body.nodes, options.nodes);
let xDistance = Math.abs(range.maxX - range.minX) * 1.1;
let yDistance = Math.abs(range.maxY - range.minY) * 1.1;
@ -89,7 +89,7 @@ class View {
zoomLevel = 1.0;
}
let center = NetworkUtil._findCenter(range);
let center = NetworkUtil.findCenter(range);
let animationOptions = {position: center, scale: zoomLevel, animation: options.animation};
this.moveTo(animationOptions);
}

Loading…
Cancel
Save