|
|
@ -12513,7 +12513,7 @@ function Node(properties, imagelist, grouplist, constants) { |
|
|
|
this.vy = 0.0; // velocity y
|
|
|
|
this.minForce = constants.minForce; |
|
|
|
this.damping = 0.9; // damping factor
|
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* (re)setting the clustering variables and objects |
|
|
@ -14096,11 +14096,11 @@ function Graph (container, data, options) { |
|
|
|
background: '#D2E5FF' |
|
|
|
}, |
|
|
|
cluster: { |
|
|
|
border: '#000000', |
|
|
|
background: '#F0F0F0', |
|
|
|
border: '#256a2d', |
|
|
|
background: '#2cd140', |
|
|
|
highlight: { |
|
|
|
border: '#FF0FFF', |
|
|
|
background: '#FF000F' |
|
|
|
border: '#899539', |
|
|
|
background: '#c5dc29' |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
@ -14203,39 +14203,8 @@ function Graph (container, data, options) { |
|
|
|
|
|
|
|
// draw data
|
|
|
|
this.setData(data); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function checks if the zoom action is in or out. |
|
|
|
* If out, check if we can form clusters, if in, check if we can open clusters. |
|
|
|
* This function is only called from _zoom() |
|
|
|
* |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
Graph.prototype._updateClusters = function() { |
|
|
|
var moving_before_clustering = this.moving; |
|
|
|
|
|
|
|
if (this.previous_scale > this.scale) { // zoom out
|
|
|
|
this._formClusters(false); |
|
|
|
} |
|
|
|
else if (this.previous_scale < this.scale) { // zoom out
|
|
|
|
this._openClusters(); |
|
|
|
} |
|
|
|
|
|
|
|
// update node labels
|
|
|
|
for (var nid in this.nodes) { |
|
|
|
var node = this.nodes[nid]; |
|
|
|
node.label = String(node.remaining_edges).concat(":",String(node.cluster_size)); |
|
|
|
} |
|
|
|
|
|
|
|
this.previous_scale = this.scale; |
|
|
|
} |
|
|
|
|
|
|
|
// if the simulation was settled, we restart the simulation if a cluster has been formed or expanded
|
|
|
|
if (this.moving != moving_before_clustering) { |
|
|
|
this.start(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* This function can be called to increase the cluster level. This means that the nodes with only one edge connection will |
|
|
@ -14244,7 +14213,7 @@ Graph.prototype._updateClusters = function() { |
|
|
|
*/ |
|
|
|
Graph.prototype.collapseClusterLevel = function() { |
|
|
|
this._formClusters(true); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* This function can be called to decrease the cluster level. This means that the nodes with only one edge connection will |
|
|
@ -14259,7 +14228,7 @@ Graph.prototype.expandClusterLevel = function() { |
|
|
|
} |
|
|
|
} |
|
|
|
this._updateNodeIndexList(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
@ -14271,7 +14240,8 @@ Graph.prototype.expandClusterLevel = function() { |
|
|
|
Graph.prototype.fullyOpenCluster = function(node) { |
|
|
|
this._expandClusterNode(node,true,true); |
|
|
|
this._updateNodeIndexList(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function can be called to open up a specific cluster. |
|
|
@ -14282,7 +14252,81 @@ Graph.prototype.fullyOpenCluster = function(node) { |
|
|
|
Graph.prototype.openCluster = function(node) { |
|
|
|
this._expandClusterNode(node,false,true); |
|
|
|
this._updateNodeIndexList(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function checks if the zoom action is in or out. |
|
|
|
* If out, check if we can form clusters, if in, check if we can open clusters. |
|
|
|
* This function is only called from _zoom() |
|
|
|
* |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
Graph.prototype._updateClusters = function() { |
|
|
|
var moving_before_clustering = this.moving; |
|
|
|
|
|
|
|
if (this.previous_scale > this.scale) { // zoom out
|
|
|
|
this._formClusters(false); |
|
|
|
} |
|
|
|
else if (this.previous_scale < this.scale) { // zoom out
|
|
|
|
this._openClusters(); |
|
|
|
} |
|
|
|
|
|
|
|
this._updateClusterLabels(); |
|
|
|
this._updateNodeLabels(); |
|
|
|
|
|
|
|
this.previous_scale = this.scale; |
|
|
|
|
|
|
|
// if the simulation was settled, we restart the simulation if a cluster has been formed or expanded
|
|
|
|
if (this.moving != moving_before_clustering) { |
|
|
|
this.start(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* This updates the node labels for all nodes (for debugging purposes) |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
Graph.prototype._updateLabels = function() { |
|
|
|
// update node labels
|
|
|
|
for (var node_id in this.nodes) { |
|
|
|
if (this.nodes.hasOwnProperty(node_id)) { |
|
|
|
var node = this.nodes[node_id]; |
|
|
|
node.label = String(node.remaining_edges).concat(":",String(node.cluster_size)); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* This updates the node labels for all clusters |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
Graph.prototype._updateClusterLabels = function() { |
|
|
|
// update node labels
|
|
|
|
for (var node_id in this.nodes) { |
|
|
|
if (this.nodes.hasOwnProperty(node_id)) { |
|
|
|
var node = this.nodes[node_id]; |
|
|
|
if (node.cluster_size > 1) { |
|
|
|
node.label = "[".concat(String(node.cluster_size),"]"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
/** |
|
|
|
* This updates the node labels for all nodes that are NOT clusters |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
Graph.prototype._updateNodeLabels = function() { |
|
|
|
// update node labels
|
|
|
|
for (var node_id in this.nodes) { |
|
|
|
var node = this.nodes[node_id]; |
|
|
|
if (node.cluster_size == 1) { |
|
|
|
node.label = "[".concat(String(node.cluster_size),"]"); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function loops over all nodes in the node_indices list. For each node it checks if it is a cluster and if it |
|
|
@ -14299,6 +14343,7 @@ Graph.prototype._openClusters = function() { |
|
|
|
this._updateNodeIndexList(); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function checks if a node has to be opened. This is done by checking the zoom level. |
|
|
|
* If the node contains child nodes, this function is recursively called on the child nodes as well. |
|
|
@ -14350,6 +14395,7 @@ Graph.prototype._expandClusterNode = function(node, recursive, force_expand) { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function will expel a child_node from a parent_node. This is to de-cluster the node. This function will remove |
|
|
|
* the child node from the parent contained_node object and put it back into the global nodes object. |
|
|
@ -14394,6 +14440,7 @@ Graph.prototype._expelChildFromParent = function(node, contained_node_id, recurs |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function checks if any nodes at the end of their trees have edges below a threshold length |
|
|
|
* This function is called only from _updateClusters() |
|
|
@ -14464,7 +14511,7 @@ Graph.prototype._formClusters = function(force_level_collapse) { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function adds the childnode to the parentnode, creating a cluster if it is not already. |
|
|
|
* This function adds the child node to the parent node, creating a cluster if it is not already. |
|
|
|
* This function is called only from _updateClusters() |
|
|
|
* |
|
|
|
* @param parent_node | Node object: this is the node that will house the child node |
|
|
@ -14500,6 +14547,7 @@ Graph.prototype._addToCluster = function(parent_node, child_node, edge, edge_id, |
|
|
|
this.moving = true; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* This function will apply the changes made to the remaining_edges during the formation of the clusters. |
|
|
|
* This is a seperate function to allow for level-wise collapsing of the node tree. |
|
|
@ -14528,6 +14576,7 @@ Graph.prototype._updateNodeIndexList = function() { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Set nodes and edges, and optionally options as well. |
|
|
|
* |
|
|
|