Init from given files
This commit is contained in:
154
src/hybridSimulation.js
Normal file
154
src/hybridSimulation.js
Normal file
@@ -0,0 +1,154 @@
|
||||
import { dispatch } from "d3-dispatch";
|
||||
import constant from "./constant";
|
||||
import interpolation from "./interpolation";
|
||||
import interpolationPivots from "./interpolationPivots";
|
||||
|
||||
export default function (nodes) {
|
||||
|
||||
var hybrid,
|
||||
fullSimulation,
|
||||
distance = constant(300),
|
||||
MULTIPLIER = 50,
|
||||
PIVOTS = false,
|
||||
NUMPIVOTS = 3,
|
||||
SAMPLE_ITERATIONS = 300,
|
||||
FULL_ITERATIONS = 20,
|
||||
neighbourSize = 6,
|
||||
sampleSize = 3,
|
||||
event = d3Dispatch.dispatch("sampleTick", "fullTick", "startFull", "end");
|
||||
|
||||
var sets = sampleFromNodes(nodes, nodes.length, Math.sqrt(nodes.length));
|
||||
var sample = sets.sample;
|
||||
var remainder = sets.remainder;
|
||||
var interpSubset = sampleFromNodes(sample, sample.length, Math.sqrt(sample.length)).sample;
|
||||
|
||||
var sampleSimulation = d3.forceSimulation()
|
||||
.alphaDecay(1 - Math.pow(0.001, 1 / SAMPLE_ITERATIONS));
|
||||
|
||||
sampleSimulation
|
||||
.force("neighbourSampling", d3.forceNeighbourSampling()
|
||||
.distance(function (s, t) {
|
||||
return distance(s, t, props, norm) * MULTIPLIER;
|
||||
})
|
||||
.neighbourSize(neighbourSize)
|
||||
.sampleSize(sampleSize))
|
||||
.nodes(sample)
|
||||
.on("tick", function () {
|
||||
event.call("sampleTick", sampleSimulation);
|
||||
})
|
||||
.on("end", ended);
|
||||
|
||||
|
||||
function ended() {
|
||||
if (PIVOTS) {
|
||||
interpolationPivots(sample, remainder, interpSubset, NUMPIVOTS, distance);
|
||||
} else {
|
||||
interpolation(sample, remainder, interpSubset, distance);
|
||||
}
|
||||
|
||||
fullSimulation = d3.forceSimulation()
|
||||
.alphaDecay(1 - Math.pow(0.001, 1 / FULL_ITERATIONS));
|
||||
|
||||
event.call("startFull", fullSimulation);
|
||||
|
||||
fullSimulation
|
||||
.force("neighbourSampling", d3.forceNeighbourSampling()
|
||||
.distance(function (s, t) {
|
||||
return distance(s, t, props, norm) * MULTIPLIER;
|
||||
})
|
||||
.neighbourSize(neighbourSize)
|
||||
.sampleSize(sampleSize))
|
||||
.nodes(nodes)
|
||||
.on("tick", function () {
|
||||
event.call("fullTick", fullSimulation);
|
||||
})
|
||||
.on("end", function () {
|
||||
event.call("end", fullSimulation);
|
||||
});
|
||||
}
|
||||
|
||||
return hybrid = {
|
||||
distance: function (_) {
|
||||
return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), hybrid) : distance;
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
if (typeof sampleSimulation !== 'undefined') {
|
||||
sampleSimulation.stop();
|
||||
}
|
||||
if (typeof fullSimulation !== 'undefined') {
|
||||
fullSimulation.stop();
|
||||
}
|
||||
return hybrid;
|
||||
},
|
||||
|
||||
pivots: function (_) {
|
||||
return arguments.length ? (PIVOTS = _, hybrid) : PIVOTS;
|
||||
},
|
||||
|
||||
numPivots: function (_) {
|
||||
return arguments.length ? (NUMPIVOTS = +_, hybrid) : NUMPIVOTS;
|
||||
},
|
||||
|
||||
multiplier: function (_) {
|
||||
return arguments.length ? (MULTIPLIER = +_, hybrid) : MULTIPLIER;
|
||||
},
|
||||
|
||||
sampleIterations: function (_) {
|
||||
return arguments.length ? (SAMPLE_ITERATIONS = +_, hybrid) : SAMPLE_ITERATIONS;
|
||||
},
|
||||
|
||||
fullIterations: function (_) {
|
||||
return arguments.length ? (FULL_ITERATIONS = +_, hybrid) : FULL_ITERATIONS;
|
||||
},
|
||||
|
||||
neighbourSize: function (_) {
|
||||
return arguments.length ? (neighbourSize = +_, hybrid) : neighbourSize;
|
||||
},
|
||||
|
||||
sampleSize: function (_) {
|
||||
return arguments.length ? (sampleSize = +_, hybrid) : sampleSize;
|
||||
},
|
||||
|
||||
on: function (name, _) {
|
||||
return arguments.length > 1 ? (event.on(name, _), hybrid) : event.on(name);
|
||||
},
|
||||
|
||||
sample: function (_) {
|
||||
return arguments.length ? (sample = _, hybrid) : sample;
|
||||
},
|
||||
|
||||
remainder: function (_) {
|
||||
return arguments.length ? (remainder = _, hybrid) : remainder;
|
||||
},
|
||||
|
||||
stress: function () {
|
||||
return fullSimulation.force("neighbourSampling").stress();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
function sampleFromNodes(nodes, max, size) {
|
||||
var randElements = [];
|
||||
|
||||
for (var i = 0; i < size; ++i) {
|
||||
var rand = nodes[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.includes(rand)) {
|
||||
rand = nodes[Math.floor((Math.random() * max))];
|
||||
}
|
||||
randElements.push(rand);
|
||||
}
|
||||
|
||||
var remainder = nodes.filter(function (node) {
|
||||
return !randElements.includes(node);
|
||||
});
|
||||
|
||||
return {
|
||||
sample: randElements,
|
||||
remainder: remainder
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user