Neighbor stop on little velocity changes
This commit is contained in:
@@ -166,7 +166,7 @@ function processData(data, error) {
|
|||||||
.nodes(nodes)
|
.nodes(nodes)
|
||||||
.on("tick", ticked)
|
.on("tick", ticked)
|
||||||
.on("end", ended);
|
.on("end", ended);
|
||||||
|
};
|
||||||
|
|
||||||
function ticked() {
|
function ticked() {
|
||||||
// If rendering is selected, then draw at every iteration.
|
// If rendering is selected, then draw at every iteration.
|
||||||
@@ -209,8 +209,6 @@ function processData(data, error) {
|
|||||||
p2 = 0;
|
p2 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function brushEnded() {
|
function brushEnded() {
|
||||||
var s = d3.event.selection,
|
var s = d3.event.selection,
|
||||||
@@ -281,7 +279,10 @@ function startNeighbourSamplingSimulation() {
|
|||||||
// between nodes.
|
// between nodes.
|
||||||
.distance(function (s, t) {
|
.distance(function (s, t) {
|
||||||
return distanceFunction(s, t, props, norm) * MULTIPLIER;
|
return distanceFunction(s, t, props, norm) * MULTIPLIER;
|
||||||
}));
|
})
|
||||||
|
.stableVelocity(1.2 * MULTIPLIER)
|
||||||
|
.stableVeloHandler( function(){simulation.stop(); ended();} )
|
||||||
|
);
|
||||||
// Restart the simulation.
|
// Restart the simulation.
|
||||||
console.log(simulation.force(forceName).neighbourSize(), simulation.force(forceName).sampleSize());
|
console.log(simulation.force(forceName).neighbourSize(), simulation.force(forceName).sampleSize());
|
||||||
simulation.alpha(1).restart();
|
simulation.alpha(1).restart();
|
||||||
@@ -310,7 +311,7 @@ function startHybridSimulation() {
|
|||||||
pivots: PIVOTS,
|
pivots: PIVOTS,
|
||||||
numPivots: NUM_PIVOTS
|
numPivots: NUM_PIVOTS
|
||||||
};
|
};
|
||||||
.sampleSize(SAMPLE_SIZE);
|
console.log(configuration);
|
||||||
hybridSimulation = d3.hybridSimulation(nodes, configuration);
|
hybridSimulation = d3.hybridSimulation(nodes, configuration);
|
||||||
|
|
||||||
let sample = hybridSimulation.sample();
|
let sample = hybridSimulation.sample();
|
||||||
|
|||||||
@@ -34,13 +34,16 @@ export default function (nodes, config) {
|
|||||||
})
|
})
|
||||||
.on("end", ended);
|
.on("end", ended);
|
||||||
|
|
||||||
sampleSimulation.force("forces", neighbourSamplingDistance()
|
sampleSimulation
|
||||||
|
.force("forces", neighbourSamplingDistance()
|
||||||
.neighbourSize(neighbourSize)
|
.neighbourSize(neighbourSize)
|
||||||
.sampleSize(sampleSize)
|
.sampleSize(sampleSize)
|
||||||
.distanceRange(distanceRange)
|
.distanceRange(distanceRange)
|
||||||
.distance(distanceFn)
|
.distance(distanceFn)
|
||||||
);
|
.stableVelocity(60)
|
||||||
sampleSimulation.alpha(1).restart();
|
.stableVeloHandler(function(){sampleSimulation.stop(); ended();})
|
||||||
|
)
|
||||||
|
.alpha(1).restart();
|
||||||
|
|
||||||
function ended() {
|
function ended() {
|
||||||
event.call("startFull");
|
event.call("startFull");
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ export default function () {
|
|||||||
//freeness = 0.85,
|
//freeness = 0.85,
|
||||||
//springForce = 0.7,
|
//springForce = 0.7,
|
||||||
//dampingFactor = 0.3,
|
//dampingFactor = 0.3,
|
||||||
velocity;
|
velocity,
|
||||||
|
stableVelocity = 0,
|
||||||
|
stableVeloHandler = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the forces at each iteration between the node and the
|
* Calculates the forces at each iteration between the node and the
|
||||||
@@ -39,21 +41,28 @@ export default function () {
|
|||||||
*/
|
*/
|
||||||
function force(alpha) {
|
function force(alpha) {
|
||||||
velocity = 0;
|
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.
|
// Randomize the samples for every node.
|
||||||
samples[i] = randomizeSample(i);
|
samples[i] = randomizeSample(i);
|
||||||
// Calculate the forces between node and its neighbours.
|
// 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);
|
setVelocity(i, keyN, valueN, alpha);
|
||||||
}
|
}
|
||||||
// Calculate the forces between node and its sample set.
|
// 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);
|
setVelocity(i, keyS, valueS, alpha);
|
||||||
}
|
}
|
||||||
// Check if there are a better neighbours in a sample array
|
// Check if there are a better neighbours in a sample array
|
||||||
// for each node.
|
// for each node.
|
||||||
findNewNeighbours(i);
|
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.
|
* @param {number} alpha - controls the speed of simulation.
|
||||||
*/
|
*/
|
||||||
function setVelocity(sourceId, targetId, dist, alpha) {
|
function setVelocity(sourceId, targetId, dist, alpha) {
|
||||||
var source, target, x, y, l;
|
let source, target, x, y, l;
|
||||||
source = nodes[sourceId], target = nodes[targetId];
|
source = nodes[sourceId], target = nodes[targetId];
|
||||||
// If x or y coordinates not defined, add some randomness.
|
// If x or y coordinates not defined, add some randomness.
|
||||||
x = target.x + target.vx - source.x - source.vx || jiggle();
|
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 = Math.sqrt(x * x + y * y);
|
||||||
l = (l - dist) / l * alpha;
|
l = (l - dist) / l * alpha;
|
||||||
x *= l, y *= l;
|
x *= l, y *= l;
|
||||||
velocity += x + y;
|
velocity += Math.abs(x) + Math.abs(y);
|
||||||
// Set the calculated velocites for both nodes.
|
// Set the calculated velocites for both nodes.
|
||||||
target.vx -= x;
|
target.vx -= x*0.5;
|
||||||
target.vy -= y;
|
target.vy -= y*0.5;
|
||||||
source.vx += x;
|
source.vx += x*0.5;
|
||||||
source.vy += y;
|
source.vy += y*0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,11 +98,11 @@ export default function () {
|
|||||||
|
|
||||||
// Initialize for each node a neighbour and sample arrays
|
// Initialize for each node a neighbour and sample arrays
|
||||||
// with random values.
|
// with random values.
|
||||||
for (var i = 0, n = nodes.length; i < n; ++i) {
|
for (let i = 0, n = nodes.length; i < n; ++i) {
|
||||||
var exclude = []; // Array that keeps the indices of nodes to ignore.
|
let exclude = []; // Array that keeps the indices of nodes to ignore.
|
||||||
exclude.push(i);
|
exclude.push(i);
|
||||||
|
|
||||||
var neighbs = createRandomNeighbours(i, exclude, n, neighbourSize);
|
let neighbs = createRandomNeighbours(i, exclude, n, neighbourSize);
|
||||||
// Sort the neighbour set by the distances.
|
// Sort the neighbour set by the distances.
|
||||||
neighbs = new Map([...neighbs.entries()].sort(sortDistances));
|
neighbs = new Map([...neighbs.entries()].sort(sortDistances));
|
||||||
neighbours[i] = neighbs;
|
neighbours[i] = neighbs;
|
||||||
@@ -127,17 +136,17 @@ export default function () {
|
|||||||
* data set.
|
* data set.
|
||||||
*/
|
*/
|
||||||
function createRandomNeighbours(index, exclude, max, size) {
|
function createRandomNeighbours(index, exclude, max, size) {
|
||||||
var randElements = new Map();
|
let randElements = new Map();
|
||||||
var triedElements = 0;
|
let triedElements = 0;
|
||||||
|
|
||||||
while ((randElements.size < size) && (randElements.size + exclude.length + triedElements < nodes.length)) {
|
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
|
// If the rand is already in random list or in exclude list
|
||||||
// ignore it and get a new value.
|
// ignore it and get a new value.
|
||||||
while (randElements.has(rand) || exclude.includes(rand)) {
|
while (randElements.has(rand) || exclude.includes(rand)) {
|
||||||
rand = Math.floor((Math.random() * max));
|
rand = Math.floor((Math.random() * max));
|
||||||
}
|
}
|
||||||
var dist = +distance(nodes[index], nodes[rand]);
|
let dist = +distance(nodes[index], nodes[rand]);
|
||||||
if (dist <= distanceRange) {
|
if (dist <= distanceRange) {
|
||||||
randElements.set(rand, dist);
|
randElements.set(rand, dist);
|
||||||
} else {
|
} else {
|
||||||
@@ -150,14 +159,14 @@ export default function () {
|
|||||||
|
|
||||||
|
|
||||||
function createRandomSample(index, exclude, max, size) {
|
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.
|
// Stop when no new elements can be found.
|
||||||
if (randElements.size + exclude.length >= nodes.length) {
|
if (randElements.size + exclude.length >= nodes.length) {
|
||||||
break;
|
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
|
// If the rand is already in random list or in exclude list
|
||||||
// ignore it and get a new value.
|
// ignore it and get a new value.
|
||||||
while (randElements.has(rand) || exclude.includes(rand)) {
|
while (randElements.has(rand) || exclude.includes(rand)) {
|
||||||
@@ -176,7 +185,7 @@ export default function () {
|
|||||||
*/
|
*/
|
||||||
function randomizeSample(index) {
|
function randomizeSample(index) {
|
||||||
// Ignore the current neighbours of the node and itself.
|
// Ignore the current neighbours of the node and itself.
|
||||||
var exclude = [index];
|
let exclude = [index];
|
||||||
exclude = exclude.concat(Array.from(neighbours[index].keys()));
|
exclude = exclude.concat(Array.from(neighbours[index].keys()));
|
||||||
return createRandomSample(index, exclude, nodes.length, sampleSize);
|
return createRandomSample(index, exclude, nodes.length, sampleSize);
|
||||||
}
|
}
|
||||||
@@ -188,11 +197,11 @@ export default function () {
|
|||||||
* @param {number} index - index of current node.
|
* @param {number} index - index of current node.
|
||||||
*/
|
*/
|
||||||
function findNewNeighbours(index) {
|
function findNewNeighbours(index) {
|
||||||
var sample = samples[index];
|
let sample = samples[index];
|
||||||
|
|
||||||
if (neighbours[index].size > 0) {
|
if (neighbours[index].size > 0) {
|
||||||
for (var [key, value] of sample) {
|
for (let [key, value] of sample) {
|
||||||
var neighbMax = neighbours[index].entries().next().value;
|
let neighbMax = neighbours[index].entries().next().value;
|
||||||
|
|
||||||
// Check if a value from sample could be a better neighbour
|
// Check if a value from sample could be a better neighbour
|
||||||
// if so, replace it.
|
// if so, replace it.
|
||||||
@@ -212,9 +221,9 @@ export default function () {
|
|||||||
* @return {number} - stress of the layout.
|
* @return {number} - stress of the layout.
|
||||||
*/
|
*/
|
||||||
function getStress() {
|
function getStress() {
|
||||||
var totalDiffSq = 0, totalHighDistSq = 0;
|
let totalDiffSq = 0, totalHighDistSq = 0;
|
||||||
for (var i = 0, source, target, realDist, highDist; i < nodes.length; i++) {
|
for (let i = 0, source, target, realDist, highDist; i < nodes.length; i++) {
|
||||||
for (var j = 0; j < nodes.length; j++) {
|
for (let j = 0; j < nodes.length; j++) {
|
||||||
if (i !== j) {
|
if (i !== j) {
|
||||||
source = nodes[i], target = nodes[j];
|
source = nodes[i], target = nodes[j];
|
||||||
realDist = Math.hypot(target.x - source.x, target.y - source.y);
|
realDist = Math.hypot(target.x - source.x, target.y - source.y);
|
||||||
@@ -238,8 +247,8 @@ export default function () {
|
|||||||
|
|
||||||
|
|
||||||
function getDistributionData() {
|
function getDistributionData() {
|
||||||
var d = [];
|
let d = [];
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
d.push({ "index": i, "size": neighbours[i].size });
|
d.push({ "index": i, "size": neighbours[i].size });
|
||||||
}
|
}
|
||||||
return { "maxSize": neighbourSize, "l": nodes.length, "distribution": d };
|
return { "maxSize": neighbourSize, "l": nodes.length, "distribution": d };
|
||||||
@@ -292,5 +301,12 @@ export default function () {
|
|||||||
return getDistributionData();
|
return getDistributionData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
force.stableVeloHandler = function (_) {
|
||||||
|
return arguments.length ? (stableVeloHandler = _, force) : stableVeloHandler;
|
||||||
|
};
|
||||||
|
|
||||||
|
force.stableVelocity = function (_) {
|
||||||
|
return arguments.length ? (stableVelocity = _, force) : stableVelocity;
|
||||||
|
};
|
||||||
return force;
|
return force;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user