ngraph.forcelayout
Version:
Force directed graph drawing layout
72 lines (54 loc) • 2.16 kB
JavaScript
module.exports = generateBoundsFunction;
module.exports.generateFunctionBody = generateBoundsFunctionBody;
const createPatternBuilder = require('./createPatternBuilder');
function generateBoundsFunction(dimension) {
let code = generateBoundsFunctionBody(dimension);
return new Function('bodies', 'settings', 'random', code);
}
function generateBoundsFunctionBody(dimension) {
let pattern = createPatternBuilder(dimension);
let code = `
var boundingBox = {
${pattern('min_{var}: 0, max_{var}: 0,', {indent: 4})}
};
return {
box: boundingBox,
update: updateBoundingBox,
reset: resetBoundingBox,
getBestNewPosition: function (neighbors) {
var ${pattern('base_{var} = 0', {join: ', '})};
if (neighbors.length) {
for (var i = 0; i < neighbors.length; ++i) {
let neighborPos = neighbors[i].pos;
${pattern('base_{var} += neighborPos.{var};', {indent: 10})}
}
${pattern('base_{var} /= neighbors.length;', {indent: 8})}
} else {
${pattern('base_{var} = (boundingBox.min_{var} + boundingBox.max_{var}) / 2;', {indent: 8})}
}
var springLength = settings.springLength;
return {
${pattern('{var}: base_{var} + (random.nextDouble() - 0.5) * springLength,', {indent: 8})}
};
}
};
function updateBoundingBox() {
var i = bodies.length;
if (i === 0) return; // No bodies - no borders.
${pattern('var max_{var} = -Infinity;', {indent: 4})}
${pattern('var min_{var} = Infinity;', {indent: 4})}
while(i--) {
// this is O(n), it could be done faster with quadtree, if we check the root node bounds
var bodyPos = bodies[i].pos;
${pattern('if (bodyPos.{var} < min_{var}) min_{var} = bodyPos.{var};', {indent: 6})}
${pattern('if (bodyPos.{var} > max_{var}) max_{var} = bodyPos.{var};', {indent: 6})}
}
${pattern('boundingBox.min_{var} = min_{var};', {indent: 4})}
${pattern('boundingBox.max_{var} = max_{var};', {indent: 4})}
}
function resetBoundingBox() {
${pattern('boundingBox.min_{var} = boundingBox.max_{var} = 0;', {indent: 4})}
}
`;
return code;
}