ngraph.forcelayout3d
Version:
Force directed graph layout in 3d
98 lines (85 loc) • 2.55 kB
JavaScript
module.exports = function (bodies, settings) {
var random = require('ngraph.random').random(42);
var boundingBox = { x1: 0, y1: 0, z1: 0, x2: 0, y2: 0, z2: 0 };
return {
box: boundingBox,
update: updateBoundingBox,
reset : function () {
boundingBox.x1 = boundingBox.y1 = 0;
boundingBox.x2 = boundingBox.y2 = 0;
boundingBox.z1 = boundingBox.z2 = 0;
},
getBestNewPosition: function (neighbors) {
var graphRect = boundingBox;
var baseX = 0, baseY = 0, baseZ = 0;
if (neighbors.length) {
for (var i = 0; i < neighbors.length; ++i) {
baseX += neighbors[i].pos.x;
baseY += neighbors[i].pos.y;
baseZ += neighbors[i].pos.z;
}
baseX /= neighbors.length;
baseY /= neighbors.length;
baseZ /= neighbors.length;
} else {
baseX = (graphRect.x1 + graphRect.x2) / 2;
baseY = (graphRect.y1 + graphRect.y2) / 2;
baseZ = (graphRect.z1 + graphRect.z2) / 2;
}
var springLength = settings.springLength;
return {
x: baseX + random.next(springLength) - springLength / 2,
y: baseY + random.next(springLength) - springLength / 2,
z: baseZ + random.next(springLength) - springLength / 2
};
}
};
function updateBoundingBox() {
var i = bodies.length;
if (i === 0) { return; } // don't have to wory here.
var x1 = Number.MAX_VALUE,
y1 = Number.MAX_VALUE,
z1 = Number.MAX_VALUE,
x2 = Number.MIN_VALUE,
y2 = Number.MIN_VALUE,
z2 = Number.MIN_VALUE;
while(i--) {
// this is O(n), could it be done faster with quadtree?
// how about pinned nodes?
var body = bodies[i];
if (body.isPinned) {
body.pos.x = body.prevPos.x;
body.pos.y = body.prevPos.y;
body.pos.z = body.prevPos.z;
} else {
body.prevPos.x = body.pos.x;
body.prevPos.y = body.pos.y;
body.prevPos.z = body.pos.z;
}
if (body.pos.x < x1) {
x1 = body.pos.x;
}
if (body.pos.x > x2) {
x2 = body.pos.x;
}
if (body.pos.y < y1) {
y1 = body.pos.y;
}
if (body.pos.y > y2) {
y2 = body.pos.y;
}
if (body.pos.z < z1) {
z1 = body.pos.z;
}
if (body.pos.z > z2) {
z2 = body.pos.z;
}
}
boundingBox.x1 = x1;
boundingBox.x2 = x2;
boundingBox.y1 = y1;
boundingBox.y2 = y2;
boundingBox.z1 = z1;
boundingBox.z2 = z2;
}
};