@ -32,22 +32,24 @@ exports.startWithClustering = function() {
exports . clusterToFit = function ( maxNumberOfNodes , reposition ) {
exports . clusterToFit = function ( maxNumberOfNodes , reposition ) {
var numberOfNodes = this . nodeIndices . length ;
var numberOfNodes = this . nodeIndices . length ;
var maxLevels = 50 ;
var maxLevels = 2 ;
var level = 0 ;
var level = 0 ;
// we first cluster the hubs, then we pull in the outliers, repeat
// we first cluster the hubs, then we pull in the outliers, repeat
while ( numberOfNodes > maxNumberOfNodes && level < maxLevels ) {
while ( numberOfNodes > maxNumberOfNodes && level < maxLevels ) {
if ( level % 3 == 0 ) {
this . forceAggregateHubs ( true ) ;
this . normalizeClusterLevels ( ) ;
console . log ( "Performing clustering:" , level , numberOfNodes , this . clusterSession ) ;
if ( level % 3 == 0.0 ) {
//this.forceAggregateHubs(true);
//this.normalizeClusterLevels();
}
}
else {
else {
this . increaseClusterLevel ( ) ; // this also includes a cluster normalization
//this.increaseClusterLevel(); // this also includes a cluster normalization
}
}
//this.forceAggregateHubs(true);
numberOfNodes = this . nodeIndices . length ;
numberOfNodes = this . nodeIndices . length ;
level += 1 ;
level += 1 ;
}
}
console . log ( "finished" )
// after the clustering we reposition the nodes to reduce the initial chaos
// after the clustering we reposition the nodes to reduce the initial chaos
if ( level > 0 && reposition == true ) {
if ( level > 0 && reposition == true ) {
@ -98,7 +100,7 @@ exports.openCluster = function(node) {
* This calls the updateClustes with default arguments
* This calls the updateClustes with default arguments
* /
* /
exports . updateClustersDefault = function ( ) {
exports . updateClustersDefault = function ( ) {
if ( this . constants . clustering . enabled == true ) {
if ( this . constants . clustering . enabled == true && this . constants . clustering . clusterByZoom == true ) {
this . updateClusters ( 0 , false , false ) ;
this . updateClusters ( 0 , false , false ) ;
}
}
} ;
} ;
@ -224,7 +226,7 @@ exports._aggregateHubs = function(force) {
/ * *
/ * *
* This function is fired by keypress . It forces hubs to form .
* This function forces hubs to form .
*
*
* /
* /
exports . forceAggregateHubs = function ( doNotStart ) {
exports . forceAggregateHubs = function ( doNotStart ) {
@ -235,6 +237,7 @@ exports.forceAggregateHubs = function(doNotStart) {
// update the index list, dynamic edges and labels
// update the index list, dynamic edges and labels
this . _updateNodeIndexList ( ) ;
this . _updateNodeIndexList ( ) ;
this . _updateCalculationNodes ( ) ;
this . _updateDynamicEdges ( ) ;
this . _updateDynamicEdges ( ) ;
this . updateLabels ( ) ;
this . updateLabels ( ) ;
@ -347,7 +350,7 @@ exports._expandClusterNode = function(parentNode, recursive, force, openAll) {
* @ private
* @ private
* /
* /
exports . _expelChildFromParent = function ( parentNode , containedNodeId , recursive , force , openAll ) {
exports . _expelChildFromParent = function ( parentNode , containedNodeId , recursive , force , openAll ) {
var childNode = parentNode . containedNodes [ containedNodeId ] ;
var childNode = parentNode . containedNodes [ containedNodeId ]
// if child node has been added on smaller scale than current, kick out
// if child node has been added on smaller scale than current, kick out
if ( childNode . formationScale < this . scale || force == true ) {
if ( childNode . formationScale < this . scale || force == true ) {
@ -502,10 +505,10 @@ exports._forceClustersByZoom = function() {
var childNode = this . nodes [ nodeId ] ;
var childNode = this . nodes [ nodeId ] ;
// the edges can be swallowed by another decrease
// the edges can be swallowed by another decrease
if ( childNode . dynamicEdgesLength == 1 && childNode . dynamicEdges . length != 0 ) {
if ( childNode . dynamicEdgesLength == 1 && childNode . dynamicEdges . length != 0 ) {
var edge = childNode . dynamicEdges [ 0 ] ;
var edge = childNode . dynamicEdges [ 0 ] ;
var parentNode = ( edge . toId == childNode . id ) ? this . nodes [ edge . fromId ] : this . nodes [ edge . toId ] ;
var parentNode = ( edge . toId == childNode . id ) ? this . nodes [ edge . fromId ] : this . nodes [ edge . toId ] ;
// group to the largest node
// group to the largest node
if ( childNode . id != parentNode . id ) {
if ( childNode . id != parentNode . id ) {
if ( parentNode . options . mass > childNode . options . mass ) {
if ( parentNode . options . mass > childNode . options . mass ) {
@ -585,9 +588,14 @@ exports._formClusterFromHub = function(hubNode, force, onlyEqual, absorptionSize
if ( absorptionSizeOffset === undefined ) {
if ( absorptionSizeOffset === undefined ) {
absorptionSizeOffset = 0 ;
absorptionSizeOffset = 0 ;
}
}
if ( hubNode . dynamicEdgesLength < 0 ) {
console . error ( hubNode . dynamicEdgesLength , this . hubThreshold , onlyEqual )
}
// we decide if the node is a hub
// we decide if the node is a hub
if ( ( hubNode . dynamicEdgesLength >= this . hubThreshold && onlyEqual == false ) ||
if ( ( hubNode . dynamicEdgesLength >= this . hubThreshold && onlyEqual == false ) ||
( hubNode . dynamicEdgesLength == this . hubThreshold && onlyEqual == true ) ) {
( hubNode . dynamicEdgesLength == this . hubThreshold && onlyEqual == true ) ) {
// initialize variables
// initialize variables
var dx , dy , length ;
var dx , dy , length ;
var minLength = this . constants . clustering . clusterEdgeThreshold / this . scale ;
var minLength = this . constants . clustering . clusterEdgeThreshold / this . scale ;
@ -600,7 +608,7 @@ exports._formClusterFromHub = function(hubNode, force, onlyEqual, absorptionSize
edgesIdarray . push ( hubNode . dynamicEdges [ j ] . id ) ;
edgesIdarray . push ( hubNode . dynamicEdges [ j ] . id ) ;
}
}
// if the hub clustering is not forces , we check if one of the edges connected
// if the hub clustering is not forced , we check if one of the edges connected
// to a cluster is small enough based on the constants.clustering.clusterEdgeThreshold
// to a cluster is small enough based on the constants.clustering.clusterEdgeThreshold
if ( force == false ) {
if ( force == false ) {
allowCluster = false ;
allowCluster = false ;
@ -625,17 +633,24 @@ exports._formClusterFromHub = function(hubNode, force, onlyEqual, absorptionSize
// start the clustering if allowed
// start the clustering if allowed
if ( ( ! force && allowCluster ) || force ) {
if ( ( ! force && allowCluster ) || force ) {
// we loop over all edges INITIALLY connected to this hub
var children = [ ] ;
var childrenIds = { } ;
// we loop over all edges INITIALLY connected to this hub to get a list of the childNodes
for ( j = 0 ; j < amountOfInitialEdges ; j ++ ) {
for ( j = 0 ; j < amountOfInitialEdges ; j ++ ) {
edge = this . edges [ edgesIdarray [ j ] ] ;
edge = this . edges [ edgesIdarray [ j ] ] ;
// the edge can be clustered by this function in a previous loop
if ( edge !== undefined ) {
var childNode = this . nodes [ ( edge . fromId == hubNode . id ) ? edge . toId : edge . fromId ] ;
// we do not want hubs to merge with other hubs nor do we want to cluster itself.
if ( ( childNode . dynamicEdges . length <= ( this . hubThreshold + absorptionSizeOffset ) ) &&
( childNode . id != hubNode . id ) ) {
this . _addToCluster ( hubNode , childNode , force ) ;
}
var childNode = this . nodes [ ( edge . fromId == hubNode . id ) ? edge . toId : edge . fromId ] ;
if ( childrenIds [ childNode . id ] === undefined ) {
childrenIds [ childNode . id ] = true ;
children . push ( childNode ) ;
}
}
for ( j = 0 ; j < children . length ; j ++ ) {
var childNode = children [ j ] ;
// we do not want hubs to merge with other hubs nor do we want to cluster itself.
if ( ( childNode . dynamicEdges . length <= ( this . hubThreshold + absorptionSizeOffset ) ) &&
( childNode . id != hubNode . id ) ) {
this . _addToCluster ( hubNode , childNode , force ) ;
}
}
}
}
}
}
@ -655,14 +670,16 @@ exports._formClusterFromHub = function(hubNode, force, onlyEqual, absorptionSize
exports . _addToCluster = function ( parentNode , childNode , force ) {
exports . _addToCluster = function ( parentNode , childNode , force ) {
// join child node in the parent node
// join child node in the parent node
parentNode . containedNodes [ childNode . id ] = childNode ;
parentNode . containedNodes [ childNode . id ] = childNode ;
//console.log(parentNode.id, childNode.id)
// manage all the edges connected to the child and parent nodes
// manage all the edges connected to the child and parent nodes
for ( var i = 0 ; i < childNode . dynamicEdges . length ; i ++ ) {
for ( var i = 0 ; i < childNode . dynamicEdges . length ; i ++ ) {
var edge = childNode . dynamicEdges [ i ] ;
var edge = childNode . dynamicEdges [ i ] ;
if ( edge . toId == parentNode . id || edge . fromId == parentNode . id ) { // edge connected to parentNode
if ( edge . toId == parentNode . id || edge . fromId == parentNode . id ) { // edge connected to parentNode
//console.log("COLLECT",parentNode.id, childNode.id, edge.toId, edge.fromId)
this . _addToContainedEdges ( parentNode , childNode , edge ) ;
this . _addToContainedEdges ( parentNode , childNode , edge ) ;
}
}
else {
else {
//console.log("REWIRE",parentNode.id, childNode.id, edge.toId, edge.fromId)
this . _connectEdgeToCluster ( parentNode , childNode , edge ) ;
this . _connectEdgeToCluster ( parentNode , childNode , edge ) ;
}
}
}
}
@ -690,7 +707,6 @@ exports._addToCluster = function(parentNode, childNode, force) {
// forced clusters only open from screen size and double tap
// forced clusters only open from screen size and double tap
if ( force == true ) {
if ( force == true ) {
// parentNode.formationScale = Math.pow(1 - (1.0/11.0),this.clusterSession+3);
parentNode . formationScale = 0 ;
parentNode . formationScale = 0 ;
}
}
else {
else {
@ -739,6 +755,10 @@ exports._updateDynamicEdges = function() {
}
}
}
}
}
}
if ( node . dynamicEdgesLength < correction ) {
console . error ( "overshoot" , node . dynamicEdgesLength , correction )
}
node . dynamicEdgesLength -= correction ;
node . dynamicEdgesLength -= correction ;
}
}
} ;
} ;
@ -894,12 +914,14 @@ exports._connectEdgeBackToChild = function(parentNode, childNode) {
* @ private
* @ private
* /
* /
exports . _validateEdges = function ( parentNode ) {
exports . _validateEdges = function ( parentNode ) {
var dynamicEdges = [ ]
for ( var i = 0 ; i < parentNode . dynamicEdges . length ; i ++ ) {
for ( var i = 0 ; i < parentNode . dynamicEdges . length ; i ++ ) {
var edge = parentNode . dynamicEdges [ i ] ;
var edge = parentNode . dynamicEdges [ i ] ;
if ( parentNode . id ! = edge . toId && parentNode . id ! = edge . fromId ) {
parentNode . dynamicEdges . splice ( i , 1 ) ;
if ( parentNode . id = = edge . toId || parentNode . id = = edge . fromId ) {
dynamicEdges . push ( edge ) ;
}
}
}
}
parentNode . dynamicEdges = dynamicEdges ;
} ;
} ;