@ -33,8 +33,6 @@ function Node(properties, imagelist, grouplist, networkConstants) {
this . hover = false ;
this . edges = [ ] ; // all edges connected to this node
this . dynamicEdges = [ ] ;
this . reroutedEdges = { } ;
// set defaults for the properties
this . id = undefined ;
@ -56,10 +54,6 @@ function Node(properties, imagelist, grouplist, networkConstants) {
this . grouplist = grouplist ;
// physics properties
this . fx = 0.0 ; // external force x
this . fy = 0.0 ; // external force y
this . vx = 0.0 ; // velocity x
this . vy = 0.0 ; // velocity y
this . x = null ;
this . y = null ;
this . predefinedPosition = false ; // used to check if initial zoomExtent should just take the range or approximate
@ -67,52 +61,19 @@ function Node(properties, imagelist, grouplist, networkConstants) {
// used for reverting to previous position on stabilization
this . previousState = { vx : 0 , vy : 0 , x : 0 , y : 0 } ;
this . damping = networkConstants . physics . damping ; // written every time gravity is calculated
this . fixedData = { x : null , y : null } ;
this . setProperties ( properties , constants ) ;
// creating the variables for clustering
this . resetCluster ( ) ;
this . clusterSession = 0 ;
this . clusterSizeWidthFactor = networkConstants . clustering . nodeScaling . width ;
this . clusterSizeHeightFactor = networkConstants . clustering . nodeScaling . height ;
this . clusterSizeRadiusFactor = networkConstants . clustering . nodeScaling . radius ;
this . maxNodeSizeIncrements = networkConstants . clustering . maxNodeSizeIncrements ;
this . growthIndicator = 0 ;
// variables to tell the node about the network.
this . networkScaleInv = 1 ;
this . networkScale = 1 ;
this . canvasTopLeft = { "x" : - 300 , "y" : - 300 } ;
this . canvasBottomRight = { "x" : 300 , "y" : 300 } ;
this . canvasTopLeft = { x : - 300 , y : - 300 } ;
this . canvasBottomRight = { x : 300 , y : 300 } ;
this . parentEdgeId = null ;
}
/ * *
* Revert the position and velocity of the previous step .
* /
Node . prototype . revertPosition = function ( ) {
this . x = this . previousState . x ;
this . y = this . previousState . y ;
this . vx = this . previousState . vx ;
this . vy = this . previousState . vy ;
}
/ * *
* ( re ) setting the clustering variables and objects
* /
Node . prototype . resetCluster = function ( ) {
// clustering variables
this . formationScale = undefined ; // this is used to determine when to open the cluster
this . clusterSize = 1 ; // this signifies the total amount of nodes in this cluster
this . containedNodes = { } ;
this . containedEdges = { } ;
this . clusterSessions = [ ] ;
} ;
/ * *
* Attach a edge to the node
* @ param { Edge } edge
@ -121,9 +82,6 @@ Node.prototype.attachEdge = function(edge) {
if ( this . edges . indexOf ( edge ) == - 1 ) {
this . edges . push ( edge ) ;
}
if ( this . dynamicEdges . indexOf ( edge ) == - 1 ) {
this . dynamicEdges . push ( edge ) ;
}
} ;
/ * *
@ -135,10 +93,6 @@ Node.prototype.detachEdge = function(edge) {
if ( index != - 1 ) {
this . edges . splice ( index , 1 ) ;
}
index = this . dynamicEdges . indexOf ( edge ) ;
if ( index != - 1 ) {
this . dynamicEdges . splice ( index , 1 ) ;
}
} ;
@ -151,10 +105,12 @@ Node.prototype.setProperties = function(properties, constants) {
if ( ! properties ) {
return ;
}
this . properties = properties ;
var fields = [ 'borderWidth' , 'borderWidthSelected' , 'shape' , 'image' , 'brokenImage' , 'radius' , 'fontColor' ,
'fontSize' , 'fontFace' , 'fontFill' , 'fontStrokeWidth' , 'fontStrokeColor' , 'group' , 'mass' , 'fontDrawThreshold' ,
'scaleFontWithValue' , 'fontSizeMaxVisible' , 'customScalingFunction' , 'iconFontFace' , 'icon' , 'iconColor' , 'iconSize'
var fields = [ 'borderWidth' , 'borderWidthSelected' , 'shape' , 'image' , 'brokenImage' , 'radius' , 'fontColor' ,
'fontSize' , 'fontFace' , 'fontFill' , 'fontStrokeWidth' , 'fontStrokeColor' , 'group' , 'mass' , 'fontDrawThreshold' ,
'scaleFontWithValue' , 'fontSizeMaxVisible' , 'customScalingFunction' , 'iconFontFace' , 'icon' , 'iconColor' , 'iconSize' ,
'value'
] ;
util . selectiveDeepExtend ( fields , this . options , properties ) ;
@ -332,99 +288,6 @@ Node.prototype.distanceToBorder = function (ctx, angle) {
// TODO: implement calculation of distance to border for all shapes
} ;
/ * *
* Set forces acting on the node
* @ param { number } fx Force in horizontal direction
* @ param { number } fy Force in vertical direction
* /
Node . prototype . _setForce = function ( fx , fy ) {
this . fx = fx ;
this . fy = fy ;
} ;
/ * *
* Add forces acting on the node
* @ param { number } fx Force in horizontal direction
* @ param { number } fy Force in vertical direction
* @ private
* /
Node . prototype . _addForce = function ( fx , fy ) {
this . fx += fx ;
this . fy += fy ;
} ;
/ * *
* Store the state before the next step
* /
Node . prototype . storeState = function ( ) {
this . previousState . x = this . x ;
this . previousState . y = this . y ;
this . previousState . vx = this . vx ;
this . previousState . vy = this . vy ;
}
/ * *
* Perform one discrete step for the node
* @ param { number } interval Time interval in seconds
* /
Node . prototype . discreteStep = function ( interval ) {
this . storeState ( ) ;
if ( ! this . xFixed ) {
var dx = this . damping * this . vx ; // damping force
var ax = ( this . fx - dx ) / this . options . mass ; // acceleration
this . vx += ax * interval ; // velocity
this . x += this . vx * interval ; // position
}
else {
this . fx = 0 ;
this . vx = 0 ;
}
if ( ! this . yFixed ) {
var dy = this . damping * this . vy ; // damping force
var ay = ( this . fy - dy ) / this . options . mass ; // acceleration
this . vy += ay * interval ; // velocity
this . y += this . vy * interval ; // position
}
else {
this . fy = 0 ;
this . vy = 0 ;
}
} ;
/ * *
* Perform one discrete step for the node
* @ param { number } interval Time interval in seconds
* @ param { number } maxVelocity The speed limit imposed on the velocity
* /
Node . prototype . discreteStepLimited = function ( interval , maxVelocity ) {
this . storeState ( ) ;
if ( ! this . xFixed ) {
var dx = this . damping * this . vx ; // damping force
var ax = ( this . fx - dx ) / this . options . mass ; // acceleration
this . vx += ax * interval ; // velocity
this . vx = ( Math . abs ( this . vx ) > maxVelocity ) ? ( ( this . vx > 0 ) ? maxVelocity : - maxVelocity ) : this . vx ;
this . x += this . vx * interval ; // position
}
else {
this . fx = 0 ;
this . vx = 0 ;
}
if ( ! this . yFixed ) {
var dy = this . damping * this . vy ; // damping force
var ay = ( this . fy - dy ) / this . options . mass ; // acceleration
this . vy += ay * interval ; // velocity
this . vy = ( Math . abs ( this . vy ) > maxVelocity ) ? ( ( this . vy > 0 ) ? maxVelocity : - maxVelocity ) : this . vy ;
this . y += this . vy * interval ; // position
}
else {
this . fy = 0 ;
this . vy = 0 ;
}
} ;
/ * *
* Check if this node has a fixed x and y position
@ -434,17 +297,6 @@ Node.prototype.isFixed = function() {
return ( this . xFixed && this . yFixed ) ;
} ;
/ * *
* Check if this node is moving
* @ param { number } vmin the minimum velocity considered as "moving"
* @ return { boolean } true if moving , false if it has no velocity
* /
Node . prototype . isMoving = function ( vmin ) {
var velocity = Math . sqrt ( Math . pow ( this . vx , 2 ) + Math . pow ( this . vy , 2 ) ) ;
// this.velocity = Math.sqrt(Math.pow(this.vx,2) + Math.pow(this.vy,2))
return ( velocity > vmin ) ;
} ;
/ * *
* check if this node is selecte
* @ return { boolean } selected True if node is selected , else false
@ -547,29 +399,11 @@ Node.prototype._resizeImage = function (ctx) {
}
this . width = width ;
this . height = height ;
this . growthIndicator = 0 ;
if ( this . width > 0 && this . height > 0 ) {
this . width += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeWidthFactor ;
this . height += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeHeightFactor ;
this . options . radius += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeRadiusFactor ;
this . growthIndicator = this . width - width ;
}
}
} ;
Node . prototype . _drawImageAtPosition = function ( ctx ) {
if ( this . imageObj . width != 0 ) {
// draw the shade
if ( this . clusterSize > 1 ) {
var lineWidth = ( ( this . clusterSize > 1 ) ? 10 : 0.0 ) ;
lineWidth *= this . networkScaleInv ;
lineWidth = Math . min ( 0.2 * this . width , lineWidth ) ;
ctx . globalAlpha = 0.5 ;
ctx . drawImage ( this . imageObj , this . left - lineWidth , this . top - lineWidth , this . width + 2 * lineWidth , this . height + 2 * lineWidth ) ;
}
// draw the image
ctx . globalAlpha = 1.0 ;
ctx . drawImage ( this . imageObj , this . left , this . top , this . width , this . height ) ;
@ -619,12 +453,6 @@ Node.prototype._resizeCircularImage = function (ctx) {
var diameter = this . options . radius * 2 ;
this . width = diameter ;
this . height = diameter ;
// scaling used for clustering
//this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor;
//this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor;
this . options . radius += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * 0.5 * this . clusterSizeRadiusFactor ;
this . growthIndicator = this . options . radius - 0.5 * diameter ;
this . _swapToImageResizeWhenImageLoaded = true ;
}
}
@ -678,12 +506,6 @@ Node.prototype._resizeBox = function (ctx) {
var textSize = this . getTextSize ( ctx ) ;
this . width = textSize . width + 2 * margin ;
this . height = textSize . height + 2 * margin ;
this . width += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * 0.5 * this . clusterSizeWidthFactor ;
this . height += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * 0.5 * this . clusterSizeHeightFactor ;
this . growthIndicator = this . width - ( textSize . width + 2 * margin ) ;
// this.options.radius+= Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeRadiusFactor;
}
} ;
@ -693,22 +515,11 @@ Node.prototype._drawBox = function (ctx) {
this . left = this . x - this . width / 2 ;
this . top = this . y - this . height / 2 ;
var clusterLineWidth = 2.5 ;
var borderWidth = this . options . borderWidth ;
var selectionLineWidth = this . options . borderWidthSelected || 2 * this . options . borderWidth ;
ctx . strokeStyle = this . selected ? this . options . color . highlight . border : this . hover ? this . options . color . hover . border : this . options . color . border ;
// draw the outer border
if ( this . clusterSize > 1 ) {
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
ctx . roundRect ( this . left - 2 * ctx . lineWidth , this . top - 2 * ctx . lineWidth , this . width + 4 * ctx . lineWidth , this . height + 4 * ctx . lineWidth , this . options . radius ) ;
ctx . stroke ( ) ;
}
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
@ -734,12 +545,6 @@ Node.prototype._resizeDatabase = function (ctx) {
var size = textSize . width + 2 * margin ;
this . width = size ;
this . height = size ;
// scaling used for clustering
this . width += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeWidthFactor ;
this . height += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeHeightFactor ;
this . options . radius += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeRadiusFactor ;
this . growthIndicator = this . width - size ;
}
} ;
@ -748,22 +553,11 @@ Node.prototype._drawDatabase = function (ctx) {
this . left = this . x - this . width / 2 ;
this . top = this . y - this . height / 2 ;
var clusterLineWidth = 2.5 ;
var borderWidth = this . options . borderWidth ;
var selectionLineWidth = this . options . borderWidthSelected || 2 * this . options . borderWidth ;
ctx . strokeStyle = this . selected ? this . options . color . highlight . border : this . hover ? this . options . color . hover . border : this . options . color . border ;
// draw the outer border
if ( this . clusterSize > 1 ) {
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
ctx . database ( this . x - this . width / 2 - 2 * ctx . lineWidth , this . y - this . height * 0.5 - 2 * ctx . lineWidth , this . width + 4 * ctx . lineWidth , this . height + 4 * ctx . lineWidth ) ;
ctx . stroke ( ) ;
}
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
@ -790,32 +584,16 @@ Node.prototype._resizeCircle = function (ctx) {
this . width = diameter ;
this . height = diameter ;
// scaling used for clustering
// this.width += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeWidthFactor;
// this.height += Math.min(this.clusterSize - 1, this.maxNodeSizeIncrements) * 0.5 * this.clusterSizeHeightFactor;
this . options . radius += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * 0.5 * this . clusterSizeRadiusFactor ;
this . growthIndicator = this . options . radius - 0.5 * diameter ;
}
} ;
Node . prototype . _drawRawCircle = function ( ctx , x , y , radius ) {
var clusterLineWidth = 2.5 ;
var borderWidth = this . options . borderWidth ;
var selectionLineWidth = this . options . borderWidthSelected || 2 * this . options . borderWidth ;
ctx . strokeStyle = this . selected ? this . options . color . highlight . border : this . hover ? this . options . color . hover . border : this . options . color . border ;
// draw the outer border
if ( this . clusterSize > 1 ) {
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
ctx . circle ( x , y , radius + 2 * ctx . lineWidth ) ;
ctx . stroke ( ) ;
}
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
@ -850,12 +628,6 @@ Node.prototype._resizeEllipse = function (ctx) {
this . width = this . height ;
}
var defaultSize = this . width ;
// scaling used for clustering
this . width += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeWidthFactor ;
this . height += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeHeightFactor ;
this . options . radius += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeRadiusFactor ;
this . growthIndicator = this . width - defaultSize ;
}
} ;
@ -864,22 +636,12 @@ Node.prototype._drawEllipse = function (ctx) {
this . left = this . x - this . width / 2 ;
this . top = this . y - this . height / 2 ;
var clusterLineWidth = 2.5 ;
var borderWidth = this . options . borderWidth ;
var selectionLineWidth = this . options . borderWidthSelected || 2 * this . options . borderWidth ;
ctx . strokeStyle = this . selected ? this . options . color . highlight . border : this . hover ? this . options . color . hover . border : this . options . color . border ;
// draw the outer border
if ( this . clusterSize > 1 ) {
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
ctx . ellipse ( this . left - 2 * ctx . lineWidth , this . top - 2 * ctx . lineWidth , this . width + 4 * ctx . lineWidth , this . height + 4 * ctx . lineWidth ) ;
ctx . stroke ( ) ;
}
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
@ -923,12 +685,6 @@ Node.prototype._resizeShape = function (ctx) {
var size = 2 * this . options . radius ;
this . width = size ;
this . height = size ;
// scaling used for clustering
this . width += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeWidthFactor ;
this . height += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeHeightFactor ;
this . options . radius += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * 0.5 * this . clusterSizeRadiusFactor ;
this . growthIndicator = this . width - size ;
}
} ;
@ -938,7 +694,6 @@ Node.prototype._drawShape = function (ctx, shape) {
this . left = this . x - this . width / 2 ;
this . top = this . y - this . height / 2 ;
var clusterLineWidth = 2.5 ;
var borderWidth = this . options . borderWidth ;
var selectionLineWidth = this . options . borderWidthSelected || 2 * this . options . borderWidth ;
var radiusMultiplier = 2 ;
@ -953,16 +708,7 @@ Node.prototype._drawShape = function (ctx, shape) {
}
ctx . strokeStyle = this . selected ? this . options . color . highlight . border : this . hover ? this . options . color . hover . border : this . options . color . border ;
// draw the outer border
if ( this . clusterSize > 1 ) {
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
ctx [ shape ] ( this . x , this . y , this . options . radius + radiusMultiplier * ctx . lineWidth ) ;
ctx . stroke ( ) ;
}
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) + ( ( this . clusterSize > 1 ) ? clusterLineWidth : 0.0 ) ;
ctx . lineWidth = ( this . selected ? selectionLineWidth : borderWidth ) ;
ctx . lineWidth *= this . networkScaleInv ;
ctx . lineWidth = Math . min ( this . width , ctx . lineWidth ) ;
@ -990,12 +736,6 @@ Node.prototype._resizeText = function (ctx) {
var textSize = this . getTextSize ( ctx ) ;
this . width = textSize . width + 2 * margin ;
this . height = textSize . height + 2 * margin ;
// scaling used for clustering
this . width += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeWidthFactor ;
this . height += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeHeightFactor ;
this . options . radius += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeRadiusFactor ;
this . growthIndicator = this . width - ( textSize . width + 2 * margin ) ;
}
} ;
@ -1022,12 +762,6 @@ Node.prototype._resizeIcon = function (ctx) {
} ;
this . width = iconSize . width + 2 * margin ;
this . height = iconSize . height + 2 * margin ;
// scaling used for clustering
this . width += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeWidthFactor ;
this . height += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeHeightFactor ;
this . options . radius += Math . min ( this . clusterSize - 1 , this . maxNodeSizeIncrements ) * this . clusterSizeRadiusFactor ;
this . growthIndicator = this . width - ( iconSize . width + 2 * margin ) ;
}
} ;
@ -1160,13 +894,14 @@ Node.prototype.getTextSize = function(ctx) {
width = Math . max ( width , ctx . measureText ( lines [ i ] ) . width ) ;
}
return { "width" : width , "height" : height , lineCount : lines . length } ;
return { width : width , height : height , lineCount : lines . length } ;
}
else {
return { "width" : 0 , "height" : 0 , lineCount : 0 } ;
return { width : 0 , height : 0 , lineCount : 0 } ;
}
} ;
/ * *
* this is used to determine if a node is visible at all . this is used to determine when it needs to be drawn .
* there is a safety margin of 0.3 * width ;
@ -1185,16 +920,6 @@ Node.prototype.inArea = function() {
}
} ;
/ * *
* checks if the core of the node is in the display area , this is used for opening clusters around zoom
* @ returns { boolean }
* /
Node . prototype . inView = function ( ) {
return ( this . x >= this . canvasTopLeft . x &&
this . x < this . canvasBottomRight . x &&
this . y >= this . canvasTopLeft . y &&
this . y < this . canvasBottomRight . y ) ;
} ;
/ * *
* This allows the zoom level of the network to influence the rendering