|
var LGraphObject = require('./LGraphObject'); |
|
var Integer = require('./util/Integer'); |
|
var RectangleD = require('./util/RectangleD'); |
|
var LayoutConstants = require('./LayoutConstants'); |
|
var RandomSeed = require('./util/RandomSeed'); |
|
var PointD = require('./util/PointD'); |
|
|
|
function LNode(gm, loc, size, vNode) { |
|
|
|
if (size == null && vNode == null) { |
|
vNode = loc; |
|
} |
|
|
|
LGraphObject.call(this, vNode); |
|
|
|
|
|
if (gm.graphManager != null) |
|
gm = gm.graphManager; |
|
|
|
this.estimatedSize = Integer.MIN_VALUE; |
|
this.inclusionTreeDepth = Integer.MAX_VALUE; |
|
this.vGraphObject = vNode; |
|
this.edges = []; |
|
this.graphManager = gm; |
|
|
|
if (size != null && loc != null) |
|
this.rect = new RectangleD(loc.x, loc.y, size.width, size.height); |
|
else |
|
this.rect = new RectangleD(); |
|
} |
|
|
|
LNode.prototype = Object.create(LGraphObject.prototype); |
|
for (var prop in LGraphObject) { |
|
LNode[prop] = LGraphObject[prop]; |
|
} |
|
|
|
LNode.prototype.getEdges = function () |
|
{ |
|
return this.edges; |
|
}; |
|
|
|
LNode.prototype.getChild = function () |
|
{ |
|
return this.child; |
|
}; |
|
|
|
LNode.prototype.getOwner = function () |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
return this.owner; |
|
}; |
|
|
|
LNode.prototype.getWidth = function () |
|
{ |
|
return this.rect.width; |
|
}; |
|
|
|
LNode.prototype.setWidth = function (width) |
|
{ |
|
this.rect.width = width; |
|
}; |
|
|
|
LNode.prototype.getHeight = function () |
|
{ |
|
return this.rect.height; |
|
}; |
|
|
|
LNode.prototype.setHeight = function (height) |
|
{ |
|
this.rect.height = height; |
|
}; |
|
|
|
LNode.prototype.getCenterX = function () |
|
{ |
|
return this.rect.x + this.rect.width / 2; |
|
}; |
|
|
|
LNode.prototype.getCenterY = function () |
|
{ |
|
return this.rect.y + this.rect.height / 2; |
|
}; |
|
|
|
LNode.prototype.getCenter = function () |
|
{ |
|
return new PointD(this.rect.x + this.rect.width / 2, |
|
this.rect.y + this.rect.height / 2); |
|
}; |
|
|
|
LNode.prototype.getLocation = function () |
|
{ |
|
return new PointD(this.rect.x, this.rect.y); |
|
}; |
|
|
|
LNode.prototype.getRect = function () |
|
{ |
|
return this.rect; |
|
}; |
|
|
|
LNode.prototype.getDiagonal = function () |
|
{ |
|
return Math.sqrt(this.rect.width * this.rect.width + |
|
this.rect.height * this.rect.height); |
|
}; |
|
|
|
|
|
|
|
|
|
LNode.prototype.getHalfTheDiagonal = function () { |
|
return Math.sqrt(this.rect.height * this.rect.height + |
|
this.rect.width * this.rect.width) / 2; |
|
}; |
|
|
|
LNode.prototype.setRect = function (upperLeft, dimension) |
|
{ |
|
this.rect.x = upperLeft.x; |
|
this.rect.y = upperLeft.y; |
|
this.rect.width = dimension.width; |
|
this.rect.height = dimension.height; |
|
}; |
|
|
|
LNode.prototype.setCenter = function (cx, cy) |
|
{ |
|
this.rect.x = cx - this.rect.width / 2; |
|
this.rect.y = cy - this.rect.height / 2; |
|
}; |
|
|
|
LNode.prototype.setLocation = function (x, y) |
|
{ |
|
this.rect.x = x; |
|
this.rect.y = y; |
|
}; |
|
|
|
LNode.prototype.moveBy = function (dx, dy) |
|
{ |
|
this.rect.x += dx; |
|
this.rect.y += dy; |
|
}; |
|
|
|
LNode.prototype.getEdgeListToNode = function (to) |
|
{ |
|
var edgeList = []; |
|
var edge; |
|
var self = this; |
|
|
|
self.edges.forEach(function(edge) { |
|
|
|
if (edge.target == to) |
|
{ |
|
if (edge.source != self) |
|
throw "Incorrect edge source!"; |
|
|
|
edgeList.push(edge); |
|
} |
|
}); |
|
|
|
return edgeList; |
|
}; |
|
|
|
LNode.prototype.getEdgesBetween = function (other) |
|
{ |
|
var edgeList = []; |
|
var edge; |
|
|
|
var self = this; |
|
self.edges.forEach(function(edge) { |
|
|
|
if (!(edge.source == self || edge.target == self)) |
|
throw "Incorrect edge source and/or target"; |
|
|
|
if ((edge.target == other) || (edge.source == other)) |
|
{ |
|
edgeList.push(edge); |
|
} |
|
}); |
|
|
|
return edgeList; |
|
}; |
|
|
|
LNode.prototype.getNeighborsList = function () |
|
{ |
|
var neighbors = new Set(); |
|
|
|
var self = this; |
|
self.edges.forEach(function(edge) { |
|
|
|
if (edge.source == self) |
|
{ |
|
neighbors.add(edge.target); |
|
} |
|
else |
|
{ |
|
if (edge.target != self) { |
|
throw "Incorrect incidency!"; |
|
} |
|
|
|
neighbors.add(edge.source); |
|
} |
|
}); |
|
|
|
return neighbors; |
|
}; |
|
|
|
LNode.prototype.withChildren = function () |
|
{ |
|
var withNeighborsList = new Set(); |
|
var childNode; |
|
var children; |
|
|
|
withNeighborsList.add(this); |
|
|
|
if (this.child != null) |
|
{ |
|
var nodes = this.child.getNodes(); |
|
for (var i = 0; i < nodes.length; i++) |
|
{ |
|
childNode = nodes[i]; |
|
children = childNode.withChildren(); |
|
children.forEach(function(node) { |
|
withNeighborsList.add(node); |
|
}); |
|
} |
|
} |
|
|
|
return withNeighborsList; |
|
}; |
|
|
|
LNode.prototype.getNoOfChildren = function () |
|
{ |
|
var noOfChildren = 0; |
|
var childNode; |
|
|
|
if(this.child == null){ |
|
noOfChildren = 1; |
|
} |
|
else |
|
{ |
|
var nodes = this.child.getNodes(); |
|
for (var i = 0; i < nodes.length; i++) |
|
{ |
|
childNode = nodes[i]; |
|
|
|
noOfChildren += childNode.getNoOfChildren(); |
|
} |
|
} |
|
|
|
if(noOfChildren == 0){ |
|
noOfChildren = 1; |
|
} |
|
return noOfChildren; |
|
}; |
|
|
|
LNode.prototype.getEstimatedSize = function () { |
|
if (this.estimatedSize == Integer.MIN_VALUE) { |
|
throw "assert failed"; |
|
} |
|
return this.estimatedSize; |
|
}; |
|
|
|
LNode.prototype.calcEstimatedSize = function () { |
|
if (this.child == null) |
|
{ |
|
return this.estimatedSize = (this.rect.width + this.rect.height) / 2; |
|
} |
|
else |
|
{ |
|
this.estimatedSize = this.child.calcEstimatedSize(); |
|
this.rect.width = this.estimatedSize; |
|
this.rect.height = this.estimatedSize; |
|
|
|
return this.estimatedSize; |
|
} |
|
}; |
|
|
|
LNode.prototype.scatter = function () { |
|
var randomCenterX; |
|
var randomCenterY; |
|
|
|
var minX = -LayoutConstants.INITIAL_WORLD_BOUNDARY; |
|
var maxX = LayoutConstants.INITIAL_WORLD_BOUNDARY; |
|
randomCenterX = LayoutConstants.WORLD_CENTER_X + |
|
(RandomSeed.nextDouble() * (maxX - minX)) + minX; |
|
|
|
var minY = -LayoutConstants.INITIAL_WORLD_BOUNDARY; |
|
var maxY = LayoutConstants.INITIAL_WORLD_BOUNDARY; |
|
randomCenterY = LayoutConstants.WORLD_CENTER_Y + |
|
(RandomSeed.nextDouble() * (maxY - minY)) + minY; |
|
|
|
this.rect.x = randomCenterX; |
|
this.rect.y = randomCenterY |
|
}; |
|
|
|
LNode.prototype.updateBounds = function () { |
|
if (this.getChild() == null) { |
|
throw "assert failed"; |
|
} |
|
if (this.getChild().getNodes().length != 0) |
|
{ |
|
|
|
var childGraph = this.getChild(); |
|
childGraph.updateBounds(true); |
|
|
|
this.rect.x = childGraph.getLeft(); |
|
this.rect.y = childGraph.getTop(); |
|
|
|
this.setWidth(childGraph.getRight() - childGraph.getLeft()); |
|
this.setHeight(childGraph.getBottom() - childGraph.getTop()); |
|
|
|
|
|
if(LayoutConstants.NODE_DIMENSIONS_INCLUDE_LABELS){ |
|
|
|
var width = childGraph.getRight() - childGraph.getLeft(); |
|
var height = childGraph.getBottom() - childGraph.getTop(); |
|
|
|
if(this.labelWidth > width){ |
|
this.rect.x -= (this.labelWidth - width) / 2; |
|
this.setWidth(this.labelWidth); |
|
} |
|
|
|
if(this.labelHeight > height){ |
|
if(this.labelPos == "center"){ |
|
this.rect.y -= (this.labelHeight - height) / 2; |
|
} |
|
else if(this.labelPos == "top"){ |
|
this.rect.y -= (this.labelHeight - height); |
|
} |
|
this.setHeight(this.labelHeight); |
|
} |
|
} |
|
} |
|
}; |
|
|
|
LNode.prototype.getInclusionTreeDepth = function () |
|
{ |
|
if (this.inclusionTreeDepth == Integer.MAX_VALUE) { |
|
throw "assert failed"; |
|
} |
|
return this.inclusionTreeDepth; |
|
}; |
|
|
|
LNode.prototype.transform = function (trans) |
|
{ |
|
var left = this.rect.x; |
|
|
|
if (left > LayoutConstants.WORLD_BOUNDARY) |
|
{ |
|
left = LayoutConstants.WORLD_BOUNDARY; |
|
} |
|
else if (left < -LayoutConstants.WORLD_BOUNDARY) |
|
{ |
|
left = -LayoutConstants.WORLD_BOUNDARY; |
|
} |
|
|
|
var top = this.rect.y; |
|
|
|
if (top > LayoutConstants.WORLD_BOUNDARY) |
|
{ |
|
top = LayoutConstants.WORLD_BOUNDARY; |
|
} |
|
else if (top < -LayoutConstants.WORLD_BOUNDARY) |
|
{ |
|
top = -LayoutConstants.WORLD_BOUNDARY; |
|
} |
|
|
|
var leftTop = new PointD(left, top); |
|
var vLeftTop = trans.inverseTransformPoint(leftTop); |
|
|
|
this.setLocation(vLeftTop.x, vLeftTop.y); |
|
}; |
|
|
|
LNode.prototype.getLeft = function () |
|
{ |
|
return this.rect.x; |
|
}; |
|
|
|
LNode.prototype.getRight = function () |
|
{ |
|
return this.rect.x + this.rect.width; |
|
}; |
|
|
|
LNode.prototype.getTop = function () |
|
{ |
|
return this.rect.y; |
|
}; |
|
|
|
LNode.prototype.getBottom = function () |
|
{ |
|
return this.rect.y + this.rect.height; |
|
}; |
|
|
|
LNode.prototype.getParent = function () |
|
{ |
|
if (this.owner == null) |
|
{ |
|
return null; |
|
} |
|
|
|
return this.owner.getParent(); |
|
}; |
|
|
|
module.exports = LNode; |
|
|