New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

graphology-layout-forceatlas2

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphology-layout-forceatlas2 - npm Package Compare versions

Comparing version 0.6.1 to 0.7.0

2

defaults.js

@@ -9,3 +9,3 @@ /**

adjustSizes: false,
edgeWeightInfluence: 0,
edgeWeightInfluence: 1,
scalingRatio: 1,

@@ -12,0 +12,0 @@ strongGravityMode: false,

@@ -11,4 +11,4 @@ /**

*/
var PPN = 10,
PPE = 3;
var PPN = 10;
var PPE = 3;

@@ -22,16 +22,14 @@ /**

*/
exports.assign = function(target) {
exports.assign = function (target) {
target = target || {};
var objects = Array.prototype.slice.call(arguments).slice(1),
i,
k,
l;
i,
k,
l;
for (i = 0, l = objects.length; i < l; i++) {
if (!objects[i])
continue;
if (!objects[i]) continue;
for (k in objects[i])
target[k] = objects[i][k];
for (k in objects[i]) target[k] = objects[i][k];
}

@@ -48,47 +46,65 @@

*/
exports.validateSettings = function(settings) {
if ('linLogMode' in settings &&
typeof settings.linLogMode !== 'boolean')
exports.validateSettings = function (settings) {
if ('linLogMode' in settings && typeof settings.linLogMode !== 'boolean')
return {message: 'the `linLogMode` setting should be a boolean.'};
if ('outboundAttractionDistribution' in settings &&
typeof settings.outboundAttractionDistribution !== 'boolean')
return {message: 'the `outboundAttractionDistribution` setting should be a boolean.'};
if (
'outboundAttractionDistribution' in settings &&
typeof settings.outboundAttractionDistribution !== 'boolean'
)
return {
message:
'the `outboundAttractionDistribution` setting should be a boolean.'
};
if ('adjustSizes' in settings &&
typeof settings.adjustSizes !== 'boolean')
if ('adjustSizes' in settings && typeof settings.adjustSizes !== 'boolean')
return {message: 'the `adjustSizes` setting should be a boolean.'};
if ('edgeWeightInfluence' in settings &&
typeof settings.edgeWeightInfluence !== 'number' &&
settings.edgeWeightInfluence < 0)
return {message: 'the `edgeWeightInfluence` setting should be a number >= 0.'};
if (
'edgeWeightInfluence' in settings &&
typeof settings.edgeWeightInfluence !== 'number' &&
settings.edgeWeightInfluence < 1
)
return {
message: 'the `edgeWeightInfluence` setting should be a number > 0.'
};
if ('scalingRatio' in settings &&
typeof settings.scalingRatio !== 'number' &&
settings.scalingRatio < 0)
if (
'scalingRatio' in settings &&
typeof settings.scalingRatio !== 'number' &&
settings.scalingRatio < 0
)
return {message: 'the `scalingRatio` setting should be a number >= 0.'};
if ('strongGravityMode' in settings &&
typeof settings.strongGravityMode !== 'boolean')
if (
'strongGravityMode' in settings &&
typeof settings.strongGravityMode !== 'boolean'
)
return {message: 'the `strongGravityMode` setting should be a boolean.'};
if ('gravity' in settings &&
typeof settings.gravity !== 'number' &&
settings.gravity < 0)
if (
'gravity' in settings &&
typeof settings.gravity !== 'number' &&
settings.gravity < 0
)
return {message: 'the `gravity` setting should be a number >= 0.'};
if ('slowDown' in settings &&
typeof settings.slowDown !== 'number' &&
settings.slowDown < 0)
if (
'slowDown' in settings &&
typeof settings.slowDown !== 'number' &&
settings.slowDown < 0
)
return {message: 'the `slowDown` setting should be a number >= 0.'};
if ('barnesHutOptimize' in settings &&
typeof settings.barnesHutOptimize !== 'boolean')
if (
'barnesHutOptimize' in settings &&
typeof settings.barnesHutOptimize !== 'boolean'
)
return {message: 'the `barnesHutOptimize` setting should be a boolean.'};
if ('barnesHutTheta' in settings &&
typeof settings.barnesHutTheta !== 'number' &&
settings.barnesHutTheta < 0)
if (
'barnesHutTheta' in settings &&
typeof settings.barnesHutTheta !== 'number' &&
settings.barnesHutTheta < 0
)
return {message: 'the `barnesHutTheta` setting should be a number >= 0.'};

@@ -102,18 +118,18 @@

*
* @param {Graph} graph - Target graph.
* @return {object} - Both matrices.
* @param {Graph} graph - Target graph.
* @param {string|null} weightAttribute - Name of the edge weight attribute.
* @return {object} - Both matrices.
*/
exports.graphToByteArrays = function(graph) {
var order = graph.order,
size = graph.size,
index = {},
j;
exports.graphToByteArrays = function (graph, weightAttribute) {
var order = graph.order;
var size = graph.size;
var index = {};
var j;
var NodeMatrix = new Float32Array(order * PPN),
EdgeMatrix = new Float32Array(size * PPE);
var NodeMatrix = new Float32Array(order * PPN);
var EdgeMatrix = new Float32Array(size * PPE);
// Iterate through nodes
j = 0;
graph.forEachNode(function(node, attr) {
graph.forEachNode(function (node, attr) {
// Node index

@@ -137,9 +153,18 @@ index[node] = j;

// Iterate through edges
var weightGetter = function (attr) {
if (!weightAttribute) return 1;
var w = attr[weightAttribute];
if (typeof w !== 'number' || isNaN(w)) w = 1;
return w;
};
j = 0;
graph.forEachEdge(function(edge, attr, source, target) {
graph.forEachEdge(function (_, attr, source, target) {
// Populating byte array
EdgeMatrix[j] = index[source];
EdgeMatrix[j + 1] = index[target];
EdgeMatrix[j + 2] = attr.weight || 0;
EdgeMatrix[j + 2] = weightGetter(attr);
j += PPE;

@@ -160,13 +185,16 @@ });

*/
exports.assignLayoutChanges = function(graph, NodeMatrix) {
exports.assignLayoutChanges = function (graph, NodeMatrix) {
var i = 0;
graph.updateEachNodeAttributes(function(node, attr) {
attr.x = NodeMatrix[i];
attr.y = NodeMatrix[i + 1];
graph.updateEachNodeAttributes(
function (node, attr) {
attr.x = NodeMatrix[i];
attr.y = NodeMatrix[i + 1];
i += PPN;
i += PPN;
return attr;
}, {attributes: ['x', 'y']});
return attr;
},
{attributes: ['x', 'y']}
);
};

@@ -181,5 +209,5 @@

*/
exports.collectLayoutChanges = function(graph, NodeMatrix) {
exports.collectLayoutChanges = function (graph, NodeMatrix) {
var nodes = graph.nodes(),
positions = {};
positions = {};

@@ -207,3 +235,5 @@ for (var i = 0, j = 0, l = NodeMatrix.length; i < l; i += PPN) {

var code = fn.toString();
var objectUrl = xURL.createObjectURL(new Blob(['(' + code + ').call(this);'], {type: 'text/javascript'}));
var objectUrl = xURL.createObjectURL(
new Blob(['(' + code + ').call(this);'], {type: 'text/javascript'})
);
var worker = new Worker(objectUrl);

@@ -210,0 +240,0 @@ xURL.revokeObjectURL(objectUrl);

import Graph from 'graphology-types';
type LayoutMapping = {[key: string]: {x: number, y: number}};
type LayoutMapping = {[key: string]: {x: number; y: number}};
export type ForceAtlas2Settings = {
linLogMode?: boolean,
outboundAttractionDistribution?: boolean,
adjustSizes?: boolean,
edgeWeightInfluence?: number,
scalingRatio?: number,
strongGravityMode?: boolean,
gravity?: number,
slowDown?: number,
barnesHutOptimize?: boolean,
barnesHutTheta?: number
linLogMode?: boolean;
outboundAttractionDistribution?: boolean;
adjustSizes?: boolean;
edgeWeightInfluence?: number;
scalingRatio?: number;
strongGravityMode?: boolean;
gravity?: number;
slowDown?: number;
barnesHutOptimize?: boolean;
barnesHutTheta?: number;
};
export type ForceAtlas2LayoutOptions = {
iterations: number,
settings?: ForceAtlas2Settings
attributes?: {
weight?: string;
};
iterations: number;
settings?: ForceAtlas2Settings;
weighted: boolean;
};

@@ -22,0 +26,0 @@

@@ -8,4 +8,4 @@ /**

var isGraph = require('graphology-utils/is-graph'),
iterate = require('./iterate.js'),
helpers = require('./helpers.js');
iterate = require('./iterate.js'),
helpers = require('./helpers.js');

@@ -20,2 +20,5 @@ var DEFAULT_SETTINGS = require('./defaults.js');

* @param {object|number} params - If number, params.iterations, else:
* @param {object} attributes - Attribute names:
* @param {string} weight - Name of the edge weight attribute.
* @param {boolean} weighted - Whether to take edge weights into account.
* @param {number} iterations - Number of iterations.

@@ -27,6 +30,7 @@ * @param {object} [settings] - Settings.

if (!isGraph(graph))
throw new Error('graphology-layout-forceatlas2: the given graph is not a valid graphology instance.');
throw new Error(
'graphology-layout-forceatlas2: the given graph is not a valid graphology instance.'
);
if (typeof params === 'number')
params = {iterations: params};
if (typeof params === 'number') params = {iterations: params};

@@ -36,18 +40,28 @@ var iterations = params.iterations;

if (typeof iterations !== 'number')
throw new Error('graphology-layout-forceatlas2: invalid number of iterations.');
throw new Error(
'graphology-layout-forceatlas2: invalid number of iterations.'
);
if (iterations <= 0)
throw new Error('graphology-layout-forceatlas2: you should provide a positive number of iterations.');
throw new Error(
'graphology-layout-forceatlas2: you should provide a positive number of iterations.'
);
var attributes = params.attributes || {};
var weightAttribute = params.weighted ? attributes.weight || 'weight' : null;
// Validating settings
var settings = helpers.assign({}, DEFAULT_SETTINGS, params.settings),
validationError = helpers.validateSettings(settings);
var settings = helpers.assign({}, DEFAULT_SETTINGS, params.settings);
var validationError = helpers.validateSettings(settings);
if (validationError)
throw new Error('graphology-layout-forceatlas2: ' + validationError.message);
throw new Error(
'graphology-layout-forceatlas2: ' + validationError.message
);
// Building matrices
var matrices = helpers.graphToByteArrays(graph),
i;
var matrices = helpers.graphToByteArrays(graph, weightAttribute);
var i;
// Iterating

@@ -54,0 +68,0 @@ for (i = 0; i < iterations; i++)

@@ -12,26 +12,26 @@ /* eslint no-constant-condition: 0 */

*/
var NODE_X = 0,
NODE_Y = 1,
NODE_DX = 2,
NODE_DY = 3,
NODE_OLD_DX = 4,
NODE_OLD_DY = 5,
NODE_MASS = 6,
NODE_CONVERGENCE = 7,
NODE_SIZE = 8,
NODE_FIXED = 9;
var NODE_X = 0;
var NODE_Y = 1;
var NODE_DX = 2;
var NODE_DY = 3;
var NODE_OLD_DX = 4;
var NODE_OLD_DY = 5;
var NODE_MASS = 6;
var NODE_CONVERGENCE = 7;
var NODE_SIZE = 8;
var NODE_FIXED = 9;
var EDGE_SOURCE = 0,
EDGE_TARGET = 1,
EDGE_WEIGHT = 2;
var EDGE_SOURCE = 0;
var EDGE_TARGET = 1;
var EDGE_WEIGHT = 2;
var REGION_NODE = 0,
REGION_CENTER_X = 1,
REGION_CENTER_Y = 2,
REGION_SIZE = 3,
REGION_NEXT_SIBLING = 4,
REGION_FIRST_CHILD = 5,
REGION_MASS = 6,
REGION_MASS_CENTER_X = 7,
REGION_MASS_CENTER_Y = 8;
var REGION_NODE = 0;
var REGION_CENTER_X = 1;
var REGION_CENTER_Y = 2;
var REGION_SIZE = 3;
var REGION_NEXT_SIBLING = 4;
var REGION_FIRST_CHILD = 5;
var REGION_MASS = 6;
var REGION_MASS_CENTER_X = 7;
var REGION_MASS_CENTER_Y = 8;

@@ -43,5 +43,5 @@ var SUBDIVISION_ATTEMPTS = 3;

*/
var PPN = 10,
PPE = 3,
PPR = 9;
var PPN = 10;
var PPE = 3;
var PPR = 9;

@@ -59,3 +59,2 @@ var MAX_FORCE = 10;

module.exports = function iterate(options, NodeMatrix, EdgeMatrix) {
// Initializing variables

@@ -65,3 +64,3 @@ var l, r, n, n1, n2, rn, e, w, g, s;

var order = NodeMatrix.length,
size = EdgeMatrix.length;
size = EdgeMatrix.length;

@@ -72,9 +71,3 @@ var adjustSizes = options.adjustSizes;

var outboundAttCompensation,
coefficient,
xDist,
yDist,
ewc,
distance,
factor;
var outboundAttCompensation, coefficient, xDist, yDist, ewc, distance, factor;

@@ -101,6 +94,5 @@ var RegionMatrix = [];

outboundAttCompensation /= (order / PPN);
outboundAttCompensation /= order / PPN;
}
// 1.bis) Barnes-Hut computation

@@ -110,9 +102,10 @@ //------------------------------

if (options.barnesHutOptimize) {
// Setting up
var minX = Infinity,
maxX = -Infinity,
minY = Infinity,
maxY = -Infinity,
q, q2, subdivisionAttempts;
maxX = -Infinity,
minY = Infinity,
maxY = -Infinity,
q,
q2,
subdivisionAttempts;

@@ -128,8 +121,8 @@ // Computing min and max values

// squarify bounds, it's a quadtree
var dx = maxX - minX, dy = maxY - minY;
var dx = maxX - minX,
dy = maxY - minY;
if (dx > dy) {
minY -= (dx - dy) / 2;
maxY = minY + dx;
}
else {
} else {
minX -= (dy - dx) / 2;

@@ -153,3 +146,2 @@ maxX = minX + dy;

for (n = 0; n < order; n += PPN) {
// Current region, starting with root

@@ -164,3 +156,2 @@ r = 0;

if (RegionMatrix[r + REGION_FIRST_CHILD] >= 0) {
// There are sub-regions

@@ -174,22 +165,14 @@

if (NodeMatrix[n + NODE_X] < RegionMatrix[r + REGION_CENTER_X]) {
if (NodeMatrix[n + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
// Top Left quarter
q = RegionMatrix[r + REGION_FIRST_CHILD];
}
else {
} else {
// Bottom Left quarter
q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR;
}
}
else {
} else {
if (NodeMatrix[n + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
// Top Right quarter
q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 2;
}
else {
} else {
// Bottom Right quarter

@@ -202,9 +185,11 @@ q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 3;

RegionMatrix[r + REGION_MASS_CENTER_X] =
(RegionMatrix[r + REGION_MASS_CENTER_X] * RegionMatrix[r + REGION_MASS] +
NodeMatrix[n + NODE_X] * NodeMatrix[n + NODE_MASS]) /
(RegionMatrix[r + REGION_MASS_CENTER_X] *
RegionMatrix[r + REGION_MASS] +
NodeMatrix[n + NODE_X] * NodeMatrix[n + NODE_MASS]) /
(RegionMatrix[r + REGION_MASS] + NodeMatrix[n + NODE_MASS]);
RegionMatrix[r + REGION_MASS_CENTER_Y] =
(RegionMatrix[r + REGION_MASS_CENTER_Y] * RegionMatrix[r + REGION_MASS] +
NodeMatrix[n + NODE_Y] * NodeMatrix[n + NODE_MASS]) /
(RegionMatrix[r + REGION_MASS_CENTER_Y] *
RegionMatrix[r + REGION_MASS] +
NodeMatrix[n + NODE_Y] * NodeMatrix[n + NODE_MASS]) /
(RegionMatrix[r + REGION_MASS] + NodeMatrix[n + NODE_MASS]);

@@ -217,5 +202,3 @@

continue;
}
else {
} else {
// There are no sub-regions: we are in a "leaf"

@@ -225,3 +208,2 @@

if (RegionMatrix[r + REGION_NODE] < 0) {
// There is no node in region:

@@ -231,5 +213,3 @@ // we record node n and go on

break;
}
else {
} else {
// There is a node in this region

@@ -253,4 +233,6 @@

RegionMatrix[g + REGION_NODE] = -1;
RegionMatrix[g + REGION_CENTER_X] = RegionMatrix[r + REGION_CENTER_X] - w;
RegionMatrix[g + REGION_CENTER_Y] = RegionMatrix[r + REGION_CENTER_Y] - w;
RegionMatrix[g + REGION_CENTER_X] =
RegionMatrix[r + REGION_CENTER_X] - w;
RegionMatrix[g + REGION_CENTER_Y] =
RegionMatrix[r + REGION_CENTER_Y] - w;
RegionMatrix[g + REGION_SIZE] = w;

@@ -266,4 +248,6 @@ RegionMatrix[g + REGION_NEXT_SIBLING] = g + PPR;

RegionMatrix[g + REGION_NODE] = -1;
RegionMatrix[g + REGION_CENTER_X] = RegionMatrix[r + REGION_CENTER_X] - w;
RegionMatrix[g + REGION_CENTER_Y] = RegionMatrix[r + REGION_CENTER_Y] + w;
RegionMatrix[g + REGION_CENTER_X] =
RegionMatrix[r + REGION_CENTER_X] - w;
RegionMatrix[g + REGION_CENTER_Y] =
RegionMatrix[r + REGION_CENTER_Y] + w;
RegionMatrix[g + REGION_SIZE] = w;

@@ -279,4 +263,6 @@ RegionMatrix[g + REGION_NEXT_SIBLING] = g + PPR;

RegionMatrix[g + REGION_NODE] = -1;
RegionMatrix[g + REGION_CENTER_X] = RegionMatrix[r + REGION_CENTER_X] + w;
RegionMatrix[g + REGION_CENTER_Y] = RegionMatrix[r + REGION_CENTER_Y] - w;
RegionMatrix[g + REGION_CENTER_X] =
RegionMatrix[r + REGION_CENTER_X] + w;
RegionMatrix[g + REGION_CENTER_Y] =
RegionMatrix[r + REGION_CENTER_Y] - w;
RegionMatrix[g + REGION_SIZE] = w;

@@ -292,6 +278,9 @@ RegionMatrix[g + REGION_NEXT_SIBLING] = g + PPR;

RegionMatrix[g + REGION_NODE] = -1;
RegionMatrix[g + REGION_CENTER_X] = RegionMatrix[r + REGION_CENTER_X] + w;
RegionMatrix[g + REGION_CENTER_Y] = RegionMatrix[r + REGION_CENTER_Y] + w;
RegionMatrix[g + REGION_CENTER_X] =
RegionMatrix[r + REGION_CENTER_X] + w;
RegionMatrix[g + REGION_CENTER_Y] =
RegionMatrix[r + REGION_CENTER_Y] + w;
RegionMatrix[g + REGION_SIZE] = w;
RegionMatrix[g + REGION_NEXT_SIBLING] = RegionMatrix[r + REGION_NEXT_SIBLING];
RegionMatrix[g + REGION_NEXT_SIBLING] =
RegionMatrix[r + REGION_NEXT_SIBLING];
RegionMatrix[g + REGION_FIRST_CHILD] = -1;

@@ -309,22 +298,24 @@ RegionMatrix[g + REGION_MASS] = 0;

// Find the quadrant of the old node
if (NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_X] < RegionMatrix[r + REGION_CENTER_X]) {
if (NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
if (
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_X] <
RegionMatrix[r + REGION_CENTER_X]
) {
if (
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y] <
RegionMatrix[r + REGION_CENTER_Y]
) {
// Top Left quarter
q = RegionMatrix[r + REGION_FIRST_CHILD];
}
else {
} else {
// Bottom Left quarter
q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR;
}
}
else {
if (NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
} else {
if (
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y] <
RegionMatrix[r + REGION_CENTER_Y]
) {
// Top Right quarter
q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 2;
}
else {
} else {
// Bottom Right quarter

@@ -336,5 +327,8 @@ q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 3;

// We remove r[0] from the region r, add its mass to r and record it in q
RegionMatrix[r + REGION_MASS] = NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_MASS];
RegionMatrix[r + REGION_MASS_CENTER_X] = NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_X];
RegionMatrix[r + REGION_MASS_CENTER_Y] = NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y];
RegionMatrix[r + REGION_MASS] =
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_MASS];
RegionMatrix[r + REGION_MASS_CENTER_X] =
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_X];
RegionMatrix[r + REGION_MASS_CENTER_Y] =
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y];

@@ -347,19 +341,13 @@ RegionMatrix[q + REGION_NODE] = RegionMatrix[r + REGION_NODE];

if (NodeMatrix[n + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
// Top Left quarter
q2 = RegionMatrix[r + REGION_FIRST_CHILD];
}
else {
} else {
// Bottom Left quarter
q2 = RegionMatrix[r + REGION_FIRST_CHILD] + PPR;
}
}
else {
} else {
if (NodeMatrix[n + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
// Top Right quarter
q2 = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 2;
}
else {
} else {
// Bottom Right quarter

@@ -371,3 +359,2 @@ q2 = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 3;

if (q === q2) {
// If both nodes are in the same quadrant,

@@ -378,4 +365,3 @@ // we have to try it again on this quadrant

continue; // while
}
else {
} else {
// we are out of precision here, and we cannot subdivide anymore

@@ -386,3 +372,2 @@ // but we have to break the loop anyway

}
}

@@ -400,3 +385,2 @@

// 2) Repulsion

@@ -411,3 +395,2 @@ //--------------

for (n = 0; n < order; n += PPN) {
// Computing leaf quad nodes iteration

@@ -417,12 +400,15 @@

while (true) {
if (RegionMatrix[r + REGION_FIRST_CHILD] >= 0) {
// The region has sub-regions
// We run the Barnes Hut test to see if we are at the right distance
distance = (
(Math.pow(NodeMatrix[n + NODE_X] - RegionMatrix[r + REGION_MASS_CENTER_X], 2)) +
(Math.pow(NodeMatrix[n + NODE_Y] - RegionMatrix[r + REGION_MASS_CENTER_Y], 2))
);
distance =
Math.pow(
NodeMatrix[n + NODE_X] - RegionMatrix[r + REGION_MASS_CENTER_X],
2
) +
Math.pow(
NodeMatrix[n + NODE_Y] - RegionMatrix[r + REGION_MASS_CENTER_Y],
2
);

@@ -432,21 +418,26 @@ s = RegionMatrix[r + REGION_SIZE];

if ((4 * s * s) / distance < thetaSquared) {
// We treat the region as a single body, and we repulse
xDist = NodeMatrix[n + NODE_X] - RegionMatrix[r + REGION_MASS_CENTER_X];
yDist = NodeMatrix[n + NODE_Y] - RegionMatrix[r + REGION_MASS_CENTER_Y];
xDist =
NodeMatrix[n + NODE_X] - RegionMatrix[r + REGION_MASS_CENTER_X];
yDist =
NodeMatrix[n + NODE_Y] - RegionMatrix[r + REGION_MASS_CENTER_Y];
if (adjustSizes === true) {
//-- Linear Anti-collision Repulsion
if (distance > 0) {
factor = coefficient * NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS] / distance;
factor =
(coefficient *
NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS]) /
distance;
NodeMatrix[n + NODE_DX] += xDist * factor;
NodeMatrix[n + NODE_DY] += yDist * factor;
}
else if (distance < 0) {
factor = -coefficient * NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS] / Math.sqrt(distance);
} else if (distance < 0) {
factor =
(-coefficient *
NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS]) /
Math.sqrt(distance);

@@ -456,9 +447,10 @@ NodeMatrix[n + NODE_DX] += xDist * factor;

}
}
else {
} else {
//-- Linear Repulsion
if (distance > 0) {
factor = coefficient * NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS] / distance;
factor =
(coefficient *
NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS]) /
distance;

@@ -472,9 +464,6 @@ NodeMatrix[n + NODE_DX] += xDist * factor;

r = RegionMatrix[r + REGION_NEXT_SIBLING];
if (r < 0)
break; // No next sibling: we have finished the tree
if (r < 0) break; // No next sibling: we have finished the tree
continue;
}
else {
} else {
// The region is too close and we have to look at sub-regions

@@ -484,6 +473,3 @@ r = RegionMatrix[r + REGION_FIRST_CHILD];

}
}
else {
} else {
// The region has no sub-region

@@ -500,14 +486,18 @@ // If there is a node r[0] and it is not n, then repulse

if (adjustSizes === true) {
//-- Linear Anti-collision Repulsion
if (distance > 0) {
factor = coefficient * NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS] / distance;
factor =
(coefficient *
NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS]) /
distance;
NodeMatrix[n + NODE_DX] += xDist * factor;
NodeMatrix[n + NODE_DY] += yDist * factor;
}
else if (distance < 0) {
factor = -coefficient * NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS] / Math.sqrt(distance);
} else if (distance < 0) {
factor =
(-coefficient *
NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS]) /
Math.sqrt(distance);

@@ -517,9 +507,10 @@ NodeMatrix[n + NODE_DX] += xDist * factor;

}
}
else {
} else {
//-- Linear Repulsion
if (distance > 0) {
factor = coefficient * NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS] / distance;
factor =
(coefficient *
NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS]) /
distance;

@@ -530,3 +521,2 @@ NodeMatrix[n + NODE_DX] += xDist * factor;

}
}

@@ -537,4 +527,3 @@

if (r < 0)
break; // No next sibling: we have finished the tree
if (r < 0) break; // No next sibling: we have finished the tree

@@ -545,4 +534,3 @@ continue;

}
}
else {
} else {
coefficient = options.scalingRatio;

@@ -553,3 +541,2 @@

for (n2 = 0; n2 < n1; n2 += PPN) {
// Common to both methods

@@ -560,5 +547,5 @@ xDist = NodeMatrix[n1 + NODE_X] - NodeMatrix[n2 + NODE_X];

if (adjustSizes === true) {
//-- Anticollision Linear Repulsion
distance = Math.sqrt(xDist * xDist + yDist * yDist) -
distance =
Math.sqrt(xDist * xDist + yDist * yDist) -
NodeMatrix[n1 + NODE_SIZE] -

@@ -568,6 +555,8 @@ NodeMatrix[n2 + NODE_SIZE];

if (distance > 0) {
factor = coefficient *
NodeMatrix[n1 + NODE_MASS] *
NodeMatrix[n2 + NODE_MASS] /
distance / distance;
factor =
(coefficient *
NodeMatrix[n1 + NODE_MASS] *
NodeMatrix[n2 + NODE_MASS]) /
distance /
distance;

@@ -580,5 +569,6 @@ // Updating nodes' dx and dy

NodeMatrix[n2 + NODE_DY] += yDist * factor;
}
else if (distance < 0) {
factor = 100 * coefficient *
} else if (distance < 0) {
factor =
100 *
coefficient *
NodeMatrix[n1 + NODE_MASS] *

@@ -594,5 +584,3 @@ NodeMatrix[n2 + NODE_MASS];

}
}
else {
} else {
//-- Linear Repulsion

@@ -602,6 +590,8 @@ distance = Math.sqrt(xDist * xDist + yDist * yDist);

if (distance > 0) {
factor = coefficient *
NodeMatrix[n1 + NODE_MASS] *
NodeMatrix[n2 + NODE_MASS] /
distance / distance;
factor =
(coefficient *
NodeMatrix[n1 + NODE_MASS] *
NodeMatrix[n2 + NODE_MASS]) /
distance /
distance;

@@ -620,3 +610,2 @@ // Updating nodes' dx and dy

// 3) Gravity

@@ -632,17 +621,11 @@ //------------

yDist = NodeMatrix[n + NODE_Y];
distance = Math.sqrt(
Math.pow(xDist, 2) + Math.pow(yDist, 2)
);
distance = Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
if (options.strongGravityMode) {
//-- Strong gravity
if (distance > 0)
factor = coefficient * NodeMatrix[n + NODE_MASS] * g;
}
else {
if (distance > 0) factor = coefficient * NodeMatrix[n + NODE_MASS] * g;
} else {
//-- Linear Anti-collision Repulsion n
if (distance > 0)
factor = coefficient * NodeMatrix[n + NODE_MASS] * g / distance;
factor = (coefficient * NodeMatrix[n + NODE_MASS] * g) / distance;
}

@@ -657,6 +640,4 @@

//---------------
coefficient = 1 *
(options.outboundAttractionDistribution ?
outboundAttCompensation :
1);
coefficient =
1 * (options.outboundAttractionDistribution ? outboundAttCompensation : 1);

@@ -679,7 +660,7 @@ // TODO: simplify distance

if (adjustSizes === true) {
distance = Math.sqrt(
(Math.pow(xDist, 2) + Math.pow(yDist, 2)) -
NodeMatrix[n1 + NODE_SIZE] -
NodeMatrix[n2 + NODE_SIZE]
Math.pow(xDist, 2) +
Math.pow(yDist, 2) -
NodeMatrix[n1 + NODE_SIZE] -
NodeMatrix[n2 + NODE_SIZE]
);

@@ -689,28 +670,22 @@

if (options.outboundAttractionDistribution) {
//-- LinLog Degree Distributed Anti-collision Attraction
if (distance > 0) {
factor = -coefficient * ewc * Math.log(1 + distance) /
distance /
NodeMatrix[n1 + NODE_MASS];
factor =
(-coefficient * ewc * Math.log(1 + distance)) /
distance /
NodeMatrix[n1 + NODE_MASS];
}
}
else {
} else {
//-- LinLog Anti-collision Attraction
if (distance > 0) {
factor = -coefficient * ewc * Math.log(1 + distance) / distance;
factor = (-coefficient * ewc * Math.log(1 + distance)) / distance;
}
}
}
else {
} else {
if (options.outboundAttractionDistribution) {
//-- Linear Degree Distributed Anti-collision Attraction
if (distance > 0) {
factor = -coefficient * ewc / NodeMatrix[n1 + NODE_MASS];
factor = (-coefficient * ewc) / NodeMatrix[n1 + NODE_MASS];
}
}
else {
} else {
//-- Linear Anti-collision Attraction

@@ -722,36 +697,26 @@ if (distance > 0) {

}
}
else {
} else {
distance = Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
distance = Math.sqrt(
Math.pow(xDist, 2) + Math.pow(yDist, 2)
);
if (options.linLogMode) {
if (options.outboundAttractionDistribution) {
//-- LinLog Degree Distributed Attraction
if (distance > 0) {
factor = -coefficient * ewc * Math.log(1 + distance) /
factor =
(-coefficient * ewc * Math.log(1 + distance)) /
distance /
NodeMatrix[n1 + NODE_MASS];
}
}
else {
} else {
//-- LinLog Attraction
if (distance > 0)
factor = -coefficient * ewc * Math.log(1 + distance) / distance;
factor = (-coefficient * ewc * Math.log(1 + distance)) / distance;
}
}
else {
} else {
if (options.outboundAttractionDistribution) {
//-- Linear Attraction Mass Distributed
// NOTE: Distance is set to 1 to override next condition
distance = 1;
factor = -coefficient * ewc / NodeMatrix[n1 + NODE_MASS];
}
else {
factor = (-coefficient * ewc) / NodeMatrix[n1 + NODE_MASS];
} else {
//-- Linear Attraction

@@ -768,3 +733,2 @@ // NOTE: Distance is set to 1 to override next condition

if (distance > 0) {
// Updating nodes' dx and dy

@@ -779,15 +743,8 @@ NodeMatrix[n1 + NODE_DX] += xDist * factor;

// 5) Apply Forces
//-----------------
var force,
swinging,
traction,
nodespeed,
newX,
newY;
var force, swinging, traction, nodespeed, newX, newY;
// MATH: sqrt and square distances
if (adjustSizes === true) {
for (n = 0; n < order; n += PPN) {

@@ -797,3 +754,3 @@ if (NodeMatrix[n + NODE_FIXED] !== 1) {

Math.pow(NodeMatrix[n + NODE_DX], 2) +
Math.pow(NodeMatrix[n + NODE_DY], 2)
Math.pow(NodeMatrix[n + NODE_DY], 2)
);

@@ -803,75 +760,82 @@

NodeMatrix[n + NODE_DX] =
NodeMatrix[n + NODE_DX] * MAX_FORCE / force;
(NodeMatrix[n + NODE_DX] * MAX_FORCE) / force;
NodeMatrix[n + NODE_DY] =
NodeMatrix[n + NODE_DY] * MAX_FORCE / force;
(NodeMatrix[n + NODE_DY] * MAX_FORCE) / force;
}
swinging = NodeMatrix[n + NODE_MASS] *
swinging =
NodeMatrix[n + NODE_MASS] *
Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY])
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY])
);
traction = Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])
) / 2;
traction =
Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])
) / 2;
nodespeed =
0.1 * Math.log(1 + traction) / (1 + Math.sqrt(swinging));
nodespeed = (0.1 * Math.log(1 + traction)) / (1 + Math.sqrt(swinging));
// Updating node's positon
newX = NodeMatrix[n + NODE_X] + NodeMatrix[n + NODE_DX] *
(nodespeed / options.slowDown);
newX =
NodeMatrix[n + NODE_X] +
NodeMatrix[n + NODE_DX] * (nodespeed / options.slowDown);
NodeMatrix[n + NODE_X] = newX;
newY = NodeMatrix[n + NODE_Y] + NodeMatrix[n + NODE_DY] *
(nodespeed / options.slowDown);
newY =
NodeMatrix[n + NODE_Y] +
NodeMatrix[n + NODE_DY] * (nodespeed / options.slowDown);
NodeMatrix[n + NODE_Y] = newY;
}
}
}
else {
} else {
for (n = 0; n < order; n += PPN) {
if (NodeMatrix[n + NODE_FIXED] !== 1) {
swinging = NodeMatrix[n + NODE_MASS] *
swinging =
NodeMatrix[n + NODE_MASS] *
Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY])
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY])
);
traction = Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])
) / 2;
traction =
Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])
) / 2;
nodespeed = NodeMatrix[n + NODE_CONVERGENCE] *
Math.log(1 + traction) / (1 + Math.sqrt(swinging));
nodespeed =
(NodeMatrix[n + NODE_CONVERGENCE] * Math.log(1 + traction)) /
(1 + Math.sqrt(swinging));
// Updating node convergence
NodeMatrix[n + NODE_CONVERGENCE] =
Math.min(1, Math.sqrt(
nodespeed *
(Math.pow(NodeMatrix[n + NODE_DX], 2) +
Math.pow(NodeMatrix[n + NODE_DY], 2)) /
(1 + Math.sqrt(swinging))
));
NodeMatrix[n + NODE_CONVERGENCE] = Math.min(
1,
Math.sqrt(
(nodespeed *
(Math.pow(NodeMatrix[n + NODE_DX], 2) +
Math.pow(NodeMatrix[n + NODE_DY], 2))) /
(1 + Math.sqrt(swinging))
)
);
// Updating node's positon
newX = NodeMatrix[n + NODE_X] + NodeMatrix[n + NODE_DX] *
(nodespeed / options.slowDown);
newX =
NodeMatrix[n + NODE_X] +
NodeMatrix[n + NODE_DX] * (nodespeed / options.slowDown);
NodeMatrix[n + NODE_X] = newX;
newY = NodeMatrix[n + NODE_Y] + NodeMatrix[n + NODE_DY] *
(nodespeed / options.slowDown);
newY =
NodeMatrix[n + NODE_Y] +
NodeMatrix[n + NODE_DY] * (nodespeed / options.slowDown);
NodeMatrix[n + NODE_Y] = newY;

@@ -878,0 +842,0 @@ }

The MIT License (MIT)
Copyright (c) 2016-2017 Guillaume Plique (Yomguithereal)
Copyright (c) 2016-2021 Guillaume Plique (Yomguithereal)

@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

{
"name": "graphology-layout-forceatlas2",
"version": "0.6.1",
"version": "0.7.0",
"description": "ForceAtlas 2 layout algorithm for graphology.",

@@ -18,5 +18,3 @@ "main": "index.js",

"clean": "rimraf webworker.js",
"lint": "eslint '*.js'",
"prepublish": "npm run clean && npm test && npm run lint && npm run template",
"prepublishOnly": "npm run prepublish",
"prepublishOnly": "npm run clean && npm test && npm run template",
"template": "node ./scripts/template-webworker.js > webworker.js",

@@ -27,3 +25,3 @@ "test": "mocha test.js"

"type": "git",
"url": "git+https://github.com/graphology/graphology-layout-forceatlas2.git"
"url": "git+https://github.com/graphology/graphology.git"
},

@@ -42,22 +40,5 @@ "keywords": [

"bugs": {
"url": "https://github.com/graphology/graphology-layout-forceatlas2/issues"
"url": "https://github.com/graphology/graphology/issues"
},
"homepage": "https://github.com/graphology/graphology-layout-forceatlas2#readme",
"devDependencies": {
"@yomguithereal/eslint-config": "^4.0.0",
"eslint": "^7.28.0",
"graphology": "0.19.3",
"graphology-generators": "^0.11.0",
"graphology-layout": "^0.4.0",
"graphology-types": "^0.19.2",
"mocha": "^8.4.0",
"rimraf": "^3.0.2",
"seedrandom": "^3.0.5"
},
"eslintConfig": {
"extends": "@yomguithereal/eslint-config",
"globals": {
"Float32Array": true
}
},
"homepage": "https://github.com/graphology/graphology#readme",
"peerDependencies": {

@@ -64,0 +45,0 @@ "graphology-types": ">=0.19.0"

@@ -1,3 +0,1 @@

[![Build Status](https://travis-ci.org/graphology/graphology-layout-forceatlas2.svg)](https://travis-ci.org/graphology/graphology-layout-forceatlas2)
# Graphology ForceAtlas2

@@ -19,7 +17,7 @@

* [Pre-requisite](#pre-requisite)
* [Settings](#settings)
* [Synchronous layout](#synchronous-layout)
* [Webworker](#webworker)
* [#.inferSettings](#infersettings)
- [Pre-requisite](#pre-requisite)
- [Settings](#settings)
- [Synchronous layout](#synchronous-layout)
- [Webworker](#webworker)
- [#.inferSettings](#infersettings)

@@ -34,12 +32,12 @@ ### Pre-requisites

* **adjustSizes** *?boolean* [`false`]: should the node's sizes be taken into account?
* **barnesHutOptimize** *?boolean* [`false`]: whether to use the Barnes-Hut approximation to compute repulsion in `O(n*log(n))` rather than default `O(n^2)`, `n` being the number of nodes.
* **barnesHutTheta** *?number* [`0.5`]: Barnes-Hut approximation theta parameter.
* **edgeWeightInfluence** *?number* [`0`]: influence of the edge's weights on the layout.
* **gravity** *?number* [`1`]: strength of the layout's gravity.
* **linLogMode** *?boolean* [`false`]: whether to use Noack's LinLog model.
* **outboundAttractionDistribution** *?boolean* [`false`]
* **scalingRatio** *?number* [`1`]
* **slowDown** *?number* [`1`]
* **strongGravityMode** *?boolean* [`false`]
- **adjustSizes** _?boolean_ [`false`]: should the node's sizes be taken into account?
- **barnesHutOptimize** _?boolean_ [`false`]: whether to use the Barnes-Hut approximation to compute repulsion in `O(n*log(n))` rather than default `O(n^2)`, `n` being the number of nodes.
- **barnesHutTheta** _?number_ [`0.5`]: Barnes-Hut approximation theta parameter.
- **edgeWeightInfluence** _?number_ [`1`]: influence of the edge's weights on the layout. To consider edge weight, don't forget to pass `weighted` as `true` when applying the [synchronous layout](#synchronous-layout) or when instantiating the [worker](#webworker).
- **gravity** _?number_ [`1`]: strength of the layout's gravity.
- **linLogMode** _?boolean_ [`false`]: whether to use Noack's LinLog model.
- **outboundAttractionDistribution** _?boolean_ [`false`]
- **scalingRatio** _?number_ [`1`]
- **slowDown** _?number_ [`1`]
- **strongGravityMode** _?boolean_ [`false`]

@@ -65,8 +63,11 @@ ### Synchronous layout

*Arguments*
_Arguments_
* **graph** *Graph*: target graph.
* **options** *object*: options:
- **iterations** *number*: number of iterations to perform.
- **settings** *?object*: the layout's settings (see [#settings](#settings)).
- **graph** _Graph_: target graph.
- **options** _object_: options:
- **iterations** _number_: number of iterations to perform.
- **attributes** _?object_: an object containing custom attribute name mapping:
- **weight** _?string_ [`weight`]: name of the edge weight attribute.
- **weighted** _?boolean_ [`false`]: whether to consider edge weight.
- **settings** _?object_: the layout's settings (see [#settings](#settings)).

@@ -77,3 +78,3 @@ ### Webworker

*Example*
_Example_

@@ -83,6 +84,7 @@ ```js

const layout = new FA2Layout(graph);
// The parameters are the same as for the synchronous version, minus `iterations` of course
const layout = new FA2Layout(graph, {settings: {gravity: 1}, weighted: true});
// To start the layout
layout.start({settings: {gravity: 1}});
layout.start();

@@ -106,3 +108,6 @@ // To stop the layout

const sensibleSettings = forceAtlas2.inferSettings(graph);
const positions = forceAtlas2(graph, {iterations: 50, settings: sensibleSettings});
const positions = forceAtlas2(graph, {
iterations: 50,
settings: sensibleSettings
});

@@ -109,0 +114,0 @@ // Alternatively using the graph's order instead of a graph instance

@@ -8,8 +8,7 @@ /**

module.exports = function worker() {
var NODES,
EDGES;
var NODES, EDGES;
var moduleShim = {};
(function() {
(function () {
/* eslint no-constant-condition: 0 */

@@ -26,26 +25,26 @@ /**

*/
var NODE_X = 0,
NODE_Y = 1,
NODE_DX = 2,
NODE_DY = 3,
NODE_OLD_DX = 4,
NODE_OLD_DY = 5,
NODE_MASS = 6,
NODE_CONVERGENCE = 7,
NODE_SIZE = 8,
NODE_FIXED = 9;
var NODE_X = 0;
var NODE_Y = 1;
var NODE_DX = 2;
var NODE_DY = 3;
var NODE_OLD_DX = 4;
var NODE_OLD_DY = 5;
var NODE_MASS = 6;
var NODE_CONVERGENCE = 7;
var NODE_SIZE = 8;
var NODE_FIXED = 9;
var EDGE_SOURCE = 0,
EDGE_TARGET = 1,
EDGE_WEIGHT = 2;
var EDGE_SOURCE = 0;
var EDGE_TARGET = 1;
var EDGE_WEIGHT = 2;
var REGION_NODE = 0,
REGION_CENTER_X = 1,
REGION_CENTER_Y = 2,
REGION_SIZE = 3,
REGION_NEXT_SIBLING = 4,
REGION_FIRST_CHILD = 5,
REGION_MASS = 6,
REGION_MASS_CENTER_X = 7,
REGION_MASS_CENTER_Y = 8;
var REGION_NODE = 0;
var REGION_CENTER_X = 1;
var REGION_CENTER_Y = 2;
var REGION_SIZE = 3;
var REGION_NEXT_SIBLING = 4;
var REGION_FIRST_CHILD = 5;
var REGION_MASS = 6;
var REGION_MASS_CENTER_X = 7;
var REGION_MASS_CENTER_Y = 8;

@@ -57,5 +56,5 @@ var SUBDIVISION_ATTEMPTS = 3;

*/
var PPN = 10,
PPE = 3,
PPR = 9;
var PPN = 10;
var PPE = 3;
var PPR = 9;

@@ -73,3 +72,2 @@ var MAX_FORCE = 10;

moduleShim.exports = function iterate(options, NodeMatrix, EdgeMatrix) {
// Initializing variables

@@ -79,3 +77,3 @@ var l, r, n, n1, n2, rn, e, w, g, s;

var order = NodeMatrix.length,
size = EdgeMatrix.length;
size = EdgeMatrix.length;

@@ -86,9 +84,3 @@ var adjustSizes = options.adjustSizes;

var outboundAttCompensation,
coefficient,
xDist,
yDist,
ewc,
distance,
factor;
var outboundAttCompensation, coefficient, xDist, yDist, ewc, distance, factor;

@@ -115,6 +107,5 @@ var RegionMatrix = [];

outboundAttCompensation /= (order / PPN);
outboundAttCompensation /= order / PPN;
}
// 1.bis) Barnes-Hut computation

@@ -124,9 +115,10 @@ //------------------------------

if (options.barnesHutOptimize) {
// Setting up
var minX = Infinity,
maxX = -Infinity,
minY = Infinity,
maxY = -Infinity,
q, q2, subdivisionAttempts;
maxX = -Infinity,
minY = Infinity,
maxY = -Infinity,
q,
q2,
subdivisionAttempts;

@@ -142,8 +134,8 @@ // Computing min and max values

// squarify bounds, it's a quadtree
var dx = maxX - minX, dy = maxY - minY;
var dx = maxX - minX,
dy = maxY - minY;
if (dx > dy) {
minY -= (dx - dy) / 2;
maxY = minY + dx;
}
else {
} else {
minX -= (dy - dx) / 2;

@@ -167,3 +159,2 @@ maxX = minX + dy;

for (n = 0; n < order; n += PPN) {
// Current region, starting with root

@@ -178,3 +169,2 @@ r = 0;

if (RegionMatrix[r + REGION_FIRST_CHILD] >= 0) {
// There are sub-regions

@@ -188,22 +178,14 @@

if (NodeMatrix[n + NODE_X] < RegionMatrix[r + REGION_CENTER_X]) {
if (NodeMatrix[n + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
// Top Left quarter
q = RegionMatrix[r + REGION_FIRST_CHILD];
}
else {
} else {
// Bottom Left quarter
q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR;
}
}
else {
} else {
if (NodeMatrix[n + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
// Top Right quarter
q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 2;
}
else {
} else {
// Bottom Right quarter

@@ -216,9 +198,11 @@ q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 3;

RegionMatrix[r + REGION_MASS_CENTER_X] =
(RegionMatrix[r + REGION_MASS_CENTER_X] * RegionMatrix[r + REGION_MASS] +
NodeMatrix[n + NODE_X] * NodeMatrix[n + NODE_MASS]) /
(RegionMatrix[r + REGION_MASS_CENTER_X] *
RegionMatrix[r + REGION_MASS] +
NodeMatrix[n + NODE_X] * NodeMatrix[n + NODE_MASS]) /
(RegionMatrix[r + REGION_MASS] + NodeMatrix[n + NODE_MASS]);
RegionMatrix[r + REGION_MASS_CENTER_Y] =
(RegionMatrix[r + REGION_MASS_CENTER_Y] * RegionMatrix[r + REGION_MASS] +
NodeMatrix[n + NODE_Y] * NodeMatrix[n + NODE_MASS]) /
(RegionMatrix[r + REGION_MASS_CENTER_Y] *
RegionMatrix[r + REGION_MASS] +
NodeMatrix[n + NODE_Y] * NodeMatrix[n + NODE_MASS]) /
(RegionMatrix[r + REGION_MASS] + NodeMatrix[n + NODE_MASS]);

@@ -231,5 +215,3 @@

continue;
}
else {
} else {
// There are no sub-regions: we are in a "leaf"

@@ -239,3 +221,2 @@

if (RegionMatrix[r + REGION_NODE] < 0) {
// There is no node in region:

@@ -245,5 +226,3 @@ // we record node n and go on

break;
}
else {
} else {
// There is a node in this region

@@ -267,4 +246,6 @@

RegionMatrix[g + REGION_NODE] = -1;
RegionMatrix[g + REGION_CENTER_X] = RegionMatrix[r + REGION_CENTER_X] - w;
RegionMatrix[g + REGION_CENTER_Y] = RegionMatrix[r + REGION_CENTER_Y] - w;
RegionMatrix[g + REGION_CENTER_X] =
RegionMatrix[r + REGION_CENTER_X] - w;
RegionMatrix[g + REGION_CENTER_Y] =
RegionMatrix[r + REGION_CENTER_Y] - w;
RegionMatrix[g + REGION_SIZE] = w;

@@ -280,4 +261,6 @@ RegionMatrix[g + REGION_NEXT_SIBLING] = g + PPR;

RegionMatrix[g + REGION_NODE] = -1;
RegionMatrix[g + REGION_CENTER_X] = RegionMatrix[r + REGION_CENTER_X] - w;
RegionMatrix[g + REGION_CENTER_Y] = RegionMatrix[r + REGION_CENTER_Y] + w;
RegionMatrix[g + REGION_CENTER_X] =
RegionMatrix[r + REGION_CENTER_X] - w;
RegionMatrix[g + REGION_CENTER_Y] =
RegionMatrix[r + REGION_CENTER_Y] + w;
RegionMatrix[g + REGION_SIZE] = w;

@@ -293,4 +276,6 @@ RegionMatrix[g + REGION_NEXT_SIBLING] = g + PPR;

RegionMatrix[g + REGION_NODE] = -1;
RegionMatrix[g + REGION_CENTER_X] = RegionMatrix[r + REGION_CENTER_X] + w;
RegionMatrix[g + REGION_CENTER_Y] = RegionMatrix[r + REGION_CENTER_Y] - w;
RegionMatrix[g + REGION_CENTER_X] =
RegionMatrix[r + REGION_CENTER_X] + w;
RegionMatrix[g + REGION_CENTER_Y] =
RegionMatrix[r + REGION_CENTER_Y] - w;
RegionMatrix[g + REGION_SIZE] = w;

@@ -306,6 +291,9 @@ RegionMatrix[g + REGION_NEXT_SIBLING] = g + PPR;

RegionMatrix[g + REGION_NODE] = -1;
RegionMatrix[g + REGION_CENTER_X] = RegionMatrix[r + REGION_CENTER_X] + w;
RegionMatrix[g + REGION_CENTER_Y] = RegionMatrix[r + REGION_CENTER_Y] + w;
RegionMatrix[g + REGION_CENTER_X] =
RegionMatrix[r + REGION_CENTER_X] + w;
RegionMatrix[g + REGION_CENTER_Y] =
RegionMatrix[r + REGION_CENTER_Y] + w;
RegionMatrix[g + REGION_SIZE] = w;
RegionMatrix[g + REGION_NEXT_SIBLING] = RegionMatrix[r + REGION_NEXT_SIBLING];
RegionMatrix[g + REGION_NEXT_SIBLING] =
RegionMatrix[r + REGION_NEXT_SIBLING];
RegionMatrix[g + REGION_FIRST_CHILD] = -1;

@@ -323,22 +311,24 @@ RegionMatrix[g + REGION_MASS] = 0;

// Find the quadrant of the old node
if (NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_X] < RegionMatrix[r + REGION_CENTER_X]) {
if (NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
if (
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_X] <
RegionMatrix[r + REGION_CENTER_X]
) {
if (
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y] <
RegionMatrix[r + REGION_CENTER_Y]
) {
// Top Left quarter
q = RegionMatrix[r + REGION_FIRST_CHILD];
}
else {
} else {
// Bottom Left quarter
q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR;
}
}
else {
if (NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
} else {
if (
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y] <
RegionMatrix[r + REGION_CENTER_Y]
) {
// Top Right quarter
q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 2;
}
else {
} else {
// Bottom Right quarter

@@ -350,5 +340,8 @@ q = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 3;

// We remove r[0] from the region r, add its mass to r and record it in q
RegionMatrix[r + REGION_MASS] = NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_MASS];
RegionMatrix[r + REGION_MASS_CENTER_X] = NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_X];
RegionMatrix[r + REGION_MASS_CENTER_Y] = NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y];
RegionMatrix[r + REGION_MASS] =
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_MASS];
RegionMatrix[r + REGION_MASS_CENTER_X] =
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_X];
RegionMatrix[r + REGION_MASS_CENTER_Y] =
NodeMatrix[RegionMatrix[r + REGION_NODE] + NODE_Y];

@@ -361,19 +354,13 @@ RegionMatrix[q + REGION_NODE] = RegionMatrix[r + REGION_NODE];

if (NodeMatrix[n + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
// Top Left quarter
q2 = RegionMatrix[r + REGION_FIRST_CHILD];
}
else {
} else {
// Bottom Left quarter
q2 = RegionMatrix[r + REGION_FIRST_CHILD] + PPR;
}
}
else {
} else {
if (NodeMatrix[n + NODE_Y] < RegionMatrix[r + REGION_CENTER_Y]) {
// Top Right quarter
q2 = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 2;
}
else {
} else {
// Bottom Right quarter

@@ -385,3 +372,2 @@ q2 = RegionMatrix[r + REGION_FIRST_CHILD] + PPR * 3;

if (q === q2) {
// If both nodes are in the same quadrant,

@@ -392,4 +378,3 @@ // we have to try it again on this quadrant

continue; // while
}
else {
} else {
// we are out of precision here, and we cannot subdivide anymore

@@ -400,3 +385,2 @@ // but we have to break the loop anyway

}
}

@@ -414,3 +398,2 @@

// 2) Repulsion

@@ -425,3 +408,2 @@ //--------------

for (n = 0; n < order; n += PPN) {
// Computing leaf quad nodes iteration

@@ -431,12 +413,15 @@

while (true) {
if (RegionMatrix[r + REGION_FIRST_CHILD] >= 0) {
// The region has sub-regions
// We run the Barnes Hut test to see if we are at the right distance
distance = (
(Math.pow(NodeMatrix[n + NODE_X] - RegionMatrix[r + REGION_MASS_CENTER_X], 2)) +
(Math.pow(NodeMatrix[n + NODE_Y] - RegionMatrix[r + REGION_MASS_CENTER_Y], 2))
);
distance =
Math.pow(
NodeMatrix[n + NODE_X] - RegionMatrix[r + REGION_MASS_CENTER_X],
2
) +
Math.pow(
NodeMatrix[n + NODE_Y] - RegionMatrix[r + REGION_MASS_CENTER_Y],
2
);

@@ -446,21 +431,26 @@ s = RegionMatrix[r + REGION_SIZE];

if ((4 * s * s) / distance < thetaSquared) {
// We treat the region as a single body, and we repulse
xDist = NodeMatrix[n + NODE_X] - RegionMatrix[r + REGION_MASS_CENTER_X];
yDist = NodeMatrix[n + NODE_Y] - RegionMatrix[r + REGION_MASS_CENTER_Y];
xDist =
NodeMatrix[n + NODE_X] - RegionMatrix[r + REGION_MASS_CENTER_X];
yDist =
NodeMatrix[n + NODE_Y] - RegionMatrix[r + REGION_MASS_CENTER_Y];
if (adjustSizes === true) {
//-- Linear Anti-collision Repulsion
if (distance > 0) {
factor = coefficient * NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS] / distance;
factor =
(coefficient *
NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS]) /
distance;
NodeMatrix[n + NODE_DX] += xDist * factor;
NodeMatrix[n + NODE_DY] += yDist * factor;
}
else if (distance < 0) {
factor = -coefficient * NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS] / Math.sqrt(distance);
} else if (distance < 0) {
factor =
(-coefficient *
NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS]) /
Math.sqrt(distance);

@@ -470,9 +460,10 @@ NodeMatrix[n + NODE_DX] += xDist * factor;

}
}
else {
} else {
//-- Linear Repulsion
if (distance > 0) {
factor = coefficient * NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS] / distance;
factor =
(coefficient *
NodeMatrix[n + NODE_MASS] *
RegionMatrix[r + REGION_MASS]) /
distance;

@@ -486,9 +477,6 @@ NodeMatrix[n + NODE_DX] += xDist * factor;

r = RegionMatrix[r + REGION_NEXT_SIBLING];
if (r < 0)
break; // No next sibling: we have finished the tree
if (r < 0) break; // No next sibling: we have finished the tree
continue;
}
else {
} else {
// The region is too close and we have to look at sub-regions

@@ -498,6 +486,3 @@ r = RegionMatrix[r + REGION_FIRST_CHILD];

}
}
else {
} else {
// The region has no sub-region

@@ -514,14 +499,18 @@ // If there is a node r[0] and it is not n, then repulse

if (adjustSizes === true) {
//-- Linear Anti-collision Repulsion
if (distance > 0) {
factor = coefficient * NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS] / distance;
factor =
(coefficient *
NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS]) /
distance;
NodeMatrix[n + NODE_DX] += xDist * factor;
NodeMatrix[n + NODE_DY] += yDist * factor;
}
else if (distance < 0) {
factor = -coefficient * NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS] / Math.sqrt(distance);
} else if (distance < 0) {
factor =
(-coefficient *
NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS]) /
Math.sqrt(distance);

@@ -531,9 +520,10 @@ NodeMatrix[n + NODE_DX] += xDist * factor;

}
}
else {
} else {
//-- Linear Repulsion
if (distance > 0) {
factor = coefficient * NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS] / distance;
factor =
(coefficient *
NodeMatrix[n + NODE_MASS] *
NodeMatrix[rn + NODE_MASS]) /
distance;

@@ -544,3 +534,2 @@ NodeMatrix[n + NODE_DX] += xDist * factor;

}
}

@@ -551,4 +540,3 @@

if (r < 0)
break; // No next sibling: we have finished the tree
if (r < 0) break; // No next sibling: we have finished the tree

@@ -559,4 +547,3 @@ continue;

}
}
else {
} else {
coefficient = options.scalingRatio;

@@ -567,3 +554,2 @@

for (n2 = 0; n2 < n1; n2 += PPN) {
// Common to both methods

@@ -574,5 +560,5 @@ xDist = NodeMatrix[n1 + NODE_X] - NodeMatrix[n2 + NODE_X];

if (adjustSizes === true) {
//-- Anticollision Linear Repulsion
distance = Math.sqrt(xDist * xDist + yDist * yDist) -
distance =
Math.sqrt(xDist * xDist + yDist * yDist) -
NodeMatrix[n1 + NODE_SIZE] -

@@ -582,6 +568,8 @@ NodeMatrix[n2 + NODE_SIZE];

if (distance > 0) {
factor = coefficient *
NodeMatrix[n1 + NODE_MASS] *
NodeMatrix[n2 + NODE_MASS] /
distance / distance;
factor =
(coefficient *
NodeMatrix[n1 + NODE_MASS] *
NodeMatrix[n2 + NODE_MASS]) /
distance /
distance;

@@ -594,5 +582,6 @@ // Updating nodes' dx and dy

NodeMatrix[n2 + NODE_DY] += yDist * factor;
}
else if (distance < 0) {
factor = 100 * coefficient *
} else if (distance < 0) {
factor =
100 *
coefficient *
NodeMatrix[n1 + NODE_MASS] *

@@ -608,5 +597,3 @@ NodeMatrix[n2 + NODE_MASS];

}
}
else {
} else {
//-- Linear Repulsion

@@ -616,6 +603,8 @@ distance = Math.sqrt(xDist * xDist + yDist * yDist);

if (distance > 0) {
factor = coefficient *
NodeMatrix[n1 + NODE_MASS] *
NodeMatrix[n2 + NODE_MASS] /
distance / distance;
factor =
(coefficient *
NodeMatrix[n1 + NODE_MASS] *
NodeMatrix[n2 + NODE_MASS]) /
distance /
distance;

@@ -634,3 +623,2 @@ // Updating nodes' dx and dy

// 3) Gravity

@@ -646,17 +634,11 @@ //------------

yDist = NodeMatrix[n + NODE_Y];
distance = Math.sqrt(
Math.pow(xDist, 2) + Math.pow(yDist, 2)
);
distance = Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
if (options.strongGravityMode) {
//-- Strong gravity
if (distance > 0)
factor = coefficient * NodeMatrix[n + NODE_MASS] * g;
}
else {
if (distance > 0) factor = coefficient * NodeMatrix[n + NODE_MASS] * g;
} else {
//-- Linear Anti-collision Repulsion n
if (distance > 0)
factor = coefficient * NodeMatrix[n + NODE_MASS] * g / distance;
factor = (coefficient * NodeMatrix[n + NODE_MASS] * g) / distance;
}

@@ -671,6 +653,4 @@

//---------------
coefficient = 1 *
(options.outboundAttractionDistribution ?
outboundAttCompensation :
1);
coefficient =
1 * (options.outboundAttractionDistribution ? outboundAttCompensation : 1);

@@ -693,7 +673,7 @@ // TODO: simplify distance

if (adjustSizes === true) {
distance = Math.sqrt(
(Math.pow(xDist, 2) + Math.pow(yDist, 2)) -
NodeMatrix[n1 + NODE_SIZE] -
NodeMatrix[n2 + NODE_SIZE]
Math.pow(xDist, 2) +
Math.pow(yDist, 2) -
NodeMatrix[n1 + NODE_SIZE] -
NodeMatrix[n2 + NODE_SIZE]
);

@@ -703,28 +683,22 @@

if (options.outboundAttractionDistribution) {
//-- LinLog Degree Distributed Anti-collision Attraction
if (distance > 0) {
factor = -coefficient * ewc * Math.log(1 + distance) /
distance /
NodeMatrix[n1 + NODE_MASS];
factor =
(-coefficient * ewc * Math.log(1 + distance)) /
distance /
NodeMatrix[n1 + NODE_MASS];
}
}
else {
} else {
//-- LinLog Anti-collision Attraction
if (distance > 0) {
factor = -coefficient * ewc * Math.log(1 + distance) / distance;
factor = (-coefficient * ewc * Math.log(1 + distance)) / distance;
}
}
}
else {
} else {
if (options.outboundAttractionDistribution) {
//-- Linear Degree Distributed Anti-collision Attraction
if (distance > 0) {
factor = -coefficient * ewc / NodeMatrix[n1 + NODE_MASS];
factor = (-coefficient * ewc) / NodeMatrix[n1 + NODE_MASS];
}
}
else {
} else {
//-- Linear Anti-collision Attraction

@@ -736,36 +710,26 @@ if (distance > 0) {

}
}
else {
} else {
distance = Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2));
distance = Math.sqrt(
Math.pow(xDist, 2) + Math.pow(yDist, 2)
);
if (options.linLogMode) {
if (options.outboundAttractionDistribution) {
//-- LinLog Degree Distributed Attraction
if (distance > 0) {
factor = -coefficient * ewc * Math.log(1 + distance) /
factor =
(-coefficient * ewc * Math.log(1 + distance)) /
distance /
NodeMatrix[n1 + NODE_MASS];
}
}
else {
} else {
//-- LinLog Attraction
if (distance > 0)
factor = -coefficient * ewc * Math.log(1 + distance) / distance;
factor = (-coefficient * ewc * Math.log(1 + distance)) / distance;
}
}
else {
} else {
if (options.outboundAttractionDistribution) {
//-- Linear Attraction Mass Distributed
// NOTE: Distance is set to 1 to override next condition
distance = 1;
factor = -coefficient * ewc / NodeMatrix[n1 + NODE_MASS];
}
else {
factor = (-coefficient * ewc) / NodeMatrix[n1 + NODE_MASS];
} else {
//-- Linear Attraction

@@ -782,3 +746,2 @@ // NOTE: Distance is set to 1 to override next condition

if (distance > 0) {
// Updating nodes' dx and dy

@@ -793,15 +756,8 @@ NodeMatrix[n1 + NODE_DX] += xDist * factor;

// 5) Apply Forces
//-----------------
var force,
swinging,
traction,
nodespeed,
newX,
newY;
var force, swinging, traction, nodespeed, newX, newY;
// MATH: sqrt and square distances
if (adjustSizes === true) {
for (n = 0; n < order; n += PPN) {

@@ -811,3 +767,3 @@ if (NodeMatrix[n + NODE_FIXED] !== 1) {

Math.pow(NodeMatrix[n + NODE_DX], 2) +
Math.pow(NodeMatrix[n + NODE_DY], 2)
Math.pow(NodeMatrix[n + NODE_DY], 2)
);

@@ -817,75 +773,82 @@

NodeMatrix[n + NODE_DX] =
NodeMatrix[n + NODE_DX] * MAX_FORCE / force;
(NodeMatrix[n + NODE_DX] * MAX_FORCE) / force;
NodeMatrix[n + NODE_DY] =
NodeMatrix[n + NODE_DY] * MAX_FORCE / force;
(NodeMatrix[n + NODE_DY] * MAX_FORCE) / force;
}
swinging = NodeMatrix[n + NODE_MASS] *
swinging =
NodeMatrix[n + NODE_MASS] *
Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY])
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY])
);
traction = Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])
) / 2;
traction =
Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])
) / 2;
nodespeed =
0.1 * Math.log(1 + traction) / (1 + Math.sqrt(swinging));
nodespeed = (0.1 * Math.log(1 + traction)) / (1 + Math.sqrt(swinging));
// Updating node's positon
newX = NodeMatrix[n + NODE_X] + NodeMatrix[n + NODE_DX] *
(nodespeed / options.slowDown);
newX =
NodeMatrix[n + NODE_X] +
NodeMatrix[n + NODE_DX] * (nodespeed / options.slowDown);
NodeMatrix[n + NODE_X] = newX;
newY = NodeMatrix[n + NODE_Y] + NodeMatrix[n + NODE_DY] *
(nodespeed / options.slowDown);
newY =
NodeMatrix[n + NODE_Y] +
NodeMatrix[n + NODE_DY] * (nodespeed / options.slowDown);
NodeMatrix[n + NODE_Y] = newY;
}
}
}
else {
} else {
for (n = 0; n < order; n += PPN) {
if (NodeMatrix[n + NODE_FIXED] !== 1) {
swinging = NodeMatrix[n + NODE_MASS] *
swinging =
NodeMatrix[n + NODE_MASS] *
Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY])
(NodeMatrix[n + NODE_OLD_DX] - NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] - NodeMatrix[n + NODE_DY])
);
traction = Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])
) / 2;
traction =
Math.sqrt(
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) *
(NodeMatrix[n + NODE_OLD_DX] + NodeMatrix[n + NODE_DX]) +
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY]) *
(NodeMatrix[n + NODE_OLD_DY] + NodeMatrix[n + NODE_DY])
) / 2;
nodespeed = NodeMatrix[n + NODE_CONVERGENCE] *
Math.log(1 + traction) / (1 + Math.sqrt(swinging));
nodespeed =
(NodeMatrix[n + NODE_CONVERGENCE] * Math.log(1 + traction)) /
(1 + Math.sqrt(swinging));
// Updating node convergence
NodeMatrix[n + NODE_CONVERGENCE] =
Math.min(1, Math.sqrt(
nodespeed *
(Math.pow(NodeMatrix[n + NODE_DX], 2) +
Math.pow(NodeMatrix[n + NODE_DY], 2)) /
(1 + Math.sqrt(swinging))
));
NodeMatrix[n + NODE_CONVERGENCE] = Math.min(
1,
Math.sqrt(
(nodespeed *
(Math.pow(NodeMatrix[n + NODE_DX], 2) +
Math.pow(NodeMatrix[n + NODE_DY], 2))) /
(1 + Math.sqrt(swinging))
)
);
// Updating node's positon
newX = NodeMatrix[n + NODE_X] + NodeMatrix[n + NODE_DX] *
(nodespeed / options.slowDown);
newX =
NodeMatrix[n + NODE_X] +
NodeMatrix[n + NODE_DX] * (nodespeed / options.slowDown);
NodeMatrix[n + NODE_X] = newX;
newY = NodeMatrix[n + NODE_Y] + NodeMatrix[n + NODE_DY] *
(nodespeed / options.slowDown);
newY =
NodeMatrix[n + NODE_Y] +
NodeMatrix[n + NODE_DY] * (nodespeed / options.slowDown);
NodeMatrix[n + NODE_Y] = newY;

@@ -904,3 +867,3 @@ }

self.addEventListener('message', function(event) {
self.addEventListener('message', function (event) {
var data = event.data;

@@ -910,18 +873,16 @@

if (data.edges)
EDGES = new Float32Array(data.edges);
if (data.edges) EDGES = new Float32Array(data.edges);
// Running the iteration
iterate(
data.settings,
NODES,
EDGES
);
iterate(data.settings, NODES, EDGES);
// Sending result to supervisor
self.postMessage({
nodes: NODES.buffer
}, [NODES.buffer]);
self.postMessage(
{
nodes: NODES.buffer
},
[NODES.buffer]
);
});
};

@@ -5,3 +5,7 @@ import Graph from 'graphology-types';

export type FA2LayoutSupervisorParameters = {
settings?: ForceAtlas2Settings
attributes?: {
weight?: string;
};
settings?: ForceAtlas2Settings;
weighted: boolean;
};

@@ -8,0 +12,0 @@

@@ -9,4 +9,4 @@ /**

var workerFunction = require('./webworker.js'),
isGraph = require('graphology-utils/is-graph'),
helpers = require('./helpers.js');
isGraph = require('graphology-utils/is-graph'),
helpers = require('./helpers.js');

@@ -28,10 +28,17 @@ var DEFAULT_SETTINGS = require('./defaults.js');

if (!isGraph(graph))
throw new Error('graphology-layout-forceatlas2/worker: the given graph is not a valid graphology instance.');
throw new Error(
'graphology-layout-forceatlas2/worker: the given graph is not a valid graphology instance.'
);
var attributes = params.attributes || {};
var weightAttribute = params.weighted ? attributes.weight || 'weight' : null;
// Validating settings
var settings = helpers.assign({}, DEFAULT_SETTINGS, params.settings),
validationError = helpers.validateSettings(settings);
var settings = helpers.assign({}, DEFAULT_SETTINGS, params.settings);
var validationError = helpers.validateSettings(settings);
if (validationError)
throw new Error('graphology-layout-forceatlas2/worker: ' + validationError.message);
throw new Error(
'graphology-layout-forceatlas2/worker: ' + validationError.message
);

@@ -42,2 +49,3 @@ // Properties

this.settings = settings;
this.weightAttribute = weightAttribute;
this.matrices = null;

@@ -53,10 +61,8 @@ this.running = false;

this.handleGraphUpdate = function() {
if (self.worker)
self.worker.terminate();
this.handleGraphUpdate = function () {
if (self.worker) self.worker.terminate();
if (respawnFrame)
clearTimeout(respawnFrame);
if (respawnFrame) clearTimeout(respawnFrame);
respawnFrame = setTimeout(function() {
respawnFrame = setTimeout(function () {
respawnFrame = undefined;

@@ -79,5 +85,4 @@ self.spawnWorker();

*/
FA2LayoutSupervisor.prototype.spawnWorker = function() {
if (this.worker)
this.worker.terminate();
FA2LayoutSupervisor.prototype.spawnWorker = function () {
if (this.worker) this.worker.terminate();

@@ -98,5 +103,4 @@ this.worker = helpers.createWorker(workerFunction);

*/
FA2LayoutSupervisor.prototype.handleMessage = function(event) {
if (!this.running)
return;
FA2LayoutSupervisor.prototype.handleMessage = function (event) {
if (!this.running) return;

@@ -118,3 +122,3 @@ var matrix = new Float32Array(event.data.nodes);

*/
FA2LayoutSupervisor.prototype.askForIterations = function(withEdges) {
FA2LayoutSupervisor.prototype.askForIterations = function (withEdges) {
var matrices = this.matrices;

@@ -144,11 +148,12 @@

*/
FA2LayoutSupervisor.prototype.start = function() {
FA2LayoutSupervisor.prototype.start = function () {
if (this.killed)
throw new Error('graphology-layout-forceatlas2/worker.start: layout was killed.');
throw new Error(
'graphology-layout-forceatlas2/worker.start: layout was killed.'
);
if (this.running)
return this;
if (this.running) return this;
// Building matrices
this.matrices = helpers.graphToByteArrays(this.graph);
this.matrices = helpers.graphToByteArrays(this.graph, this.weightAttribute);

@@ -166,3 +171,3 @@ this.running = true;

*/
FA2LayoutSupervisor.prototype.stop = function() {
FA2LayoutSupervisor.prototype.stop = function () {
this.running = false;

@@ -178,5 +183,4 @@

*/
FA2LayoutSupervisor.prototype.kill = function() {
if (this.killed)
return this;
FA2LayoutSupervisor.prototype.kill = function () {
if (this.killed) return this;

@@ -183,0 +187,0 @@ this.running = false;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc