Neighbor stop on little velocity changes

This commit is contained in:
Pitchaya Boonsarngsuk
2018-01-17 09:55:43 +00:00
parent 7b6b5e46c6
commit 5ece153651
3 changed files with 97 additions and 77 deletions

View File

@@ -34,13 +34,16 @@ export default function (nodes, config) {
})
.on("end", ended);
sampleSimulation.force("forces", neighbourSamplingDistance()
sampleSimulation
.force("forces", neighbourSamplingDistance()
.neighbourSize(neighbourSize)
.sampleSize(sampleSize)
.distanceRange(distanceRange)
.distance(distanceFn)
);
sampleSimulation.alpha(1).restart();
.stableVelocity(60)
.stableVeloHandler(function(){sampleSimulation.stop(); ended();})
)
.alpha(1).restart();
function ended() {
event.call("startFull");

View File

@@ -29,7 +29,9 @@ export default function () {
//freeness = 0.85,
//springForce = 0.7,
//dampingFactor = 0.3,
velocity;
velocity,
stableVelocity = 0,
stableVeloHandler = null;
/**
* Calculates the forces at each iteration between the node and the
@@ -39,21 +41,28 @@ export default function () {
*/
function force(alpha) {
velocity = 0;
for (var i = 0, n = nodes.length; i < n; ++i) {
for (let i = 0, n = nodes.length; i < n; ++i) {
// Randomize the samples for every node.
samples[i] = randomizeSample(i);
// Calculate the forces between node and its neighbours.
for (var [keyN, valueN] of neighbours[i]) {
for (let [keyN, valueN] of neighbours[i]) {
setVelocity(i, keyN, valueN, alpha);
}
// Calculate the forces between node and its sample set.
for (var [keyS, valueS] of samples[i]) {
for (let [keyS, valueS] of samples[i]) {
setVelocity(i, keyS, valueS, alpha);
}
// Check if there are a better neighbours in a sample array
// for each node.
findNewNeighbours(i);
}
velocity /= nodes.length*alpha;
// Now total velocity change per node, alpha not considered
if(Math.abs(velocity)<stableVelocity && stableVeloHandler!== null){
console.log("Neighbour sampling is now", velocity, ", calling stableVeloHandler().")
stableVeloHandler();
}
//else console.log(velocity);
}
/**
@@ -65,7 +74,7 @@ export default function () {
* @param {number} alpha - controls the speed of simulation.
*/
function setVelocity(sourceId, targetId, dist, alpha) {
var source, target, x, y, l;
let source, target, x, y, l;
source = nodes[sourceId], target = nodes[targetId];
// If x or y coordinates not defined, add some randomness.
x = target.x + target.vx - source.x - source.vx || jiggle();
@@ -73,12 +82,12 @@ export default function () {
l = Math.sqrt(x * x + y * y);
l = (l - dist) / l * alpha;
x *= l, y *= l;
velocity += x + y;
velocity += Math.abs(x) + Math.abs(y);
// Set the calculated velocites for both nodes.
target.vx -= x;
target.vy -= y;
source.vx += x;
source.vy += y;
target.vx -= x*0.5;
target.vy -= y*0.5;
source.vx += x*0.5;
source.vy += y*0.5;
}
/**
@@ -89,11 +98,11 @@ export default function () {
// Initialize for each node a neighbour and sample arrays
// with random values.
for (var i = 0, n = nodes.length; i < n; ++i) {
var exclude = []; // Array that keeps the indices of nodes to ignore.
for (let i = 0, n = nodes.length; i < n; ++i) {
let exclude = []; // Array that keeps the indices of nodes to ignore.
exclude.push(i);
var neighbs = createRandomNeighbours(i, exclude, n, neighbourSize);
let neighbs = createRandomNeighbours(i, exclude, n, neighbourSize);
// Sort the neighbour set by the distances.
neighbs = new Map([...neighbs.entries()].sort(sortDistances));
neighbours[i] = neighbs;
@@ -127,17 +136,17 @@ export default function () {
* data set.
*/
function createRandomNeighbours(index, exclude, max, size) {
var randElements = new Map();
var triedElements = 0;
let randElements = new Map();
let triedElements = 0;
while ((randElements.size < size) && (randElements.size + exclude.length + triedElements < nodes.length)) {
var rand = Math.floor((Math.random() * max));
let rand = Math.floor((Math.random() * max));
// If the rand is already in random list or in exclude list
// ignore it and get a new value.
while (randElements.has(rand) || exclude.includes(rand)) {
rand = Math.floor((Math.random() * max));
}
var dist = +distance(nodes[index], nodes[rand]);
let dist = +distance(nodes[index], nodes[rand]);
if (dist <= distanceRange) {
randElements.set(rand, dist);
} else {
@@ -150,14 +159,14 @@ export default function () {
function createRandomSample(index, exclude, max, size) {
var randElements = new Map();
let randElements = new Map();
for (var i = 0; i < size; ++i) {
for (let i = 0; i < size; ++i) {
// Stop when no new elements can be found.
if (randElements.size + exclude.length >= nodes.length) {
break;
}
var rand = Math.floor((Math.random() * max));
let rand = Math.floor((Math.random() * max));
// If the rand is already in random list or in exclude list
// ignore it and get a new value.
while (randElements.has(rand) || exclude.includes(rand)) {
@@ -176,7 +185,7 @@ export default function () {
*/
function randomizeSample(index) {
// Ignore the current neighbours of the node and itself.
var exclude = [index];
let exclude = [index];
exclude = exclude.concat(Array.from(neighbours[index].keys()));
return createRandomSample(index, exclude, nodes.length, sampleSize);
}
@@ -188,11 +197,11 @@ export default function () {
* @param {number} index - index of current node.
*/
function findNewNeighbours(index) {
var sample = samples[index];
let sample = samples[index];
if (neighbours[index].size > 0) {
for (var [key, value] of sample) {
var neighbMax = neighbours[index].entries().next().value;
for (let [key, value] of sample) {
let neighbMax = neighbours[index].entries().next().value;
// Check if a value from sample could be a better neighbour
// if so, replace it.
@@ -212,9 +221,9 @@ export default function () {
* @return {number} - stress of the layout.
*/
function getStress() {
var totalDiffSq = 0, totalHighDistSq = 0;
for (var i = 0, source, target, realDist, highDist; i < nodes.length; i++) {
for (var j = 0; j < nodes.length; j++) {
let totalDiffSq = 0, totalHighDistSq = 0;
for (let i = 0, source, target, realDist, highDist; i < nodes.length; i++) {
for (let j = 0; j < nodes.length; j++) {
if (i !== j) {
source = nodes[i], target = nodes[j];
realDist = Math.hypot(target.x - source.x, target.y - source.y);
@@ -238,8 +247,8 @@ export default function () {
function getDistributionData() {
var d = [];
for (var i = 0; i < nodes.length; i++) {
let d = [];
for (let i = 0; i < nodes.length; i++) {
d.push({ "index": i, "size": neighbours[i].size });
}
return { "maxSize": neighbourSize, "l": nodes.length, "distribution": d };
@@ -292,5 +301,12 @@ export default function () {
return getDistributionData();
};
force.stableVeloHandler = function (_) {
return arguments.length ? (stableVeloHandler = _, force) : stableVeloHandler;
};
force.stableVelocity = function (_) {
return arguments.length ? (stableVelocity = _, force) : stableVelocity;
};
return force;
}