diff --git a/examples/js/src/neighbourSampling-papaparsing/hybrid.js b/examples/js/src/neighbourSampling-papaparsing/hybrid.js index 58d9a85..89b0ab4 100644 --- a/examples/js/src/neighbourSampling-papaparsing/hybrid.js +++ b/examples/js/src/neighbourSampling-papaparsing/hybrid.js @@ -9,33 +9,37 @@ function startHybridSimulation() { simulation.stop(); p1 = performance.now(); - configuration = { - iteration: ITERATIONS, - neighbourSize: NEIGHBOUR_SIZE, - sampleSize: SAMPLE_SIZE, - distanceRange: SELECTED_DISTANCE, - fullIterations: FULL_ITERATIONS, - fullNeighbourSize: FULL_NEIGHBOUR_SIZE, - fullSampleSize: FULL_SAMPLE_SIZE, - fullDistanceRange: FULL_SELECTED_DISTANCE, - distanceFn: function (s, t) {return distanceFunction(s, t, props, norm);}, - pivots: PIVOTS, - numPivots: NUM_PIVOTS - }; - console.log(configuration); - hybridSimulation = d3.hybridSimulation(nodes, configuration); + function distance (s, t) { + return distanceFunction(s, t, props, norm); + } - let sample = hybridSimulation.sample(); - let remainder = hybridSimulation.remainder(); + let forceSample = d3.forceNeighbourSamplingDistance() + .neighbourSize(NEIGHBOUR_SIZE) + .sampleSize(SAMPLE_SIZE) + .distance(distance) - addNodesToDOM(sample); + let forceFull = d3.forceNeighbourSamplingDistance() + .neighbourSize(FULL_NEIGHBOUR_SIZE) + .sampleSize(FULL_SAMPLE_SIZE) + .distance(distance) - hybridSimulation + let hybridSimulation = d3.hybridSimulation(simulation, forceSample, forceFull) + .sampleIterations(ITERATIONS) + .fullIterations(FULL_ITERATIONS) + .pivots(PIVOTS) + .numPivots(NUM_PIVOTS) + .interpFindTuneIts(INTERP_ENDING_ITS) + .interpDistanceFn(distance) .on("sampleTick", ticked) .on("fullTick", ticked) - .on("startFull", startedFull) + .on("startInterp", startedFull) .on("end", ended); + let sample = hybridSimulation.sample(); + addNodesToDOM(sample); + + hybridSimulation.restart(); + function startedFull() { console.log("startedFull"); d3.selectAll(".nodes").remove(); diff --git a/src/hybridSimulation.js b/src/hybridSimulation.js index 9eb38d4..8861d05 100644 --- a/src/hybridSimulation.js +++ b/src/hybridSimulation.js @@ -2,60 +2,90 @@ import {dispatch} from "d3-dispatch"; import constant from "./constant"; import interpBruteForce from "./interpolation/interpBruteForce"; import interpolationPivots from "./interpolation/interpolationPivots"; -import neighbourSamplingDistance from "./neighbourSamplingDistance"; import {takeSampleFrom} from "./interpolation/helpers"; -export default function (nodes, config) { - var hybrid, - fullSimulation, - SAMPLE_ITERATIONS = readConf(config, "iteration", 300), - neighbourSize = readConf(config, "neighbourSize", 6), - sampleSize = readConf(config, "sampleSize", 3), - distanceRange = readConf(config, "distanceRange", 10), - FULL_ITERATIONS = readConf(config, "fullIterations", 20), - FullneighbourSize = readConf(config, "fullNeighbourSize", neighbourSize), - FullsampleSize = readConf(config, "fullSampleSize", sampleSize), - FulldistanceRange = readConf(config, "fullDistanceRange", distanceRange), - distanceFn = readConf(config, "distanceFn", constant(300)), - PIVOTS = readConf(config, "pivots", false), - NUMPIVOTS = readConf(config, "numPivots", 3), - event = d3.dispatch("sampleTick", "fullTick", "startFull", "end"); +export default function (sim, forceS, forceF) { + var + SAMPLE_ITERATIONS = 300, + FULL_ITERATIONS = 20, + interpDistanceFn, + PIVOTS = false, + NUMPIVOTS = 3, + INTERP_FINE_ITS = 20, + sample = [], + remainder = [], + simulation = sim, + forceSample = forceS, + forceFull = forceF, + event = d3.dispatch("sampleTick", "fullTick", "startInterp", "end"), + toInit = true, + nodes, + alreadyRanIterations, + hybrid; - var sets = takeSampleFrom(nodes, Math.sqrt(nodes.length)); - var sample = sets.sample; - var remainder = sets.remainder; + if(simulation != undefined) initSimulation(); + if(forceS != undefined || forceF != undefined) initForces(); - var sampleSimulation = d3.forceSimulation(sample) - .stop() - .alphaDecay(1 - Math.pow(0.001, 1 / SAMPLE_ITERATIONS)) - .on("tick", function () { - event.call("sampleTick", sampleSimulation); - }) - .on("end", ended); + function initialize() { + toInit = false; + console.log("Initializing Hybrid"); + alreadyRanIterations = 0; + simulation + .on("tick", function () { + event.call("sampleTick"); + console.log("InternalTick"); + alreadyRanIterations++; + if(alreadyRanIterations >= SAMPLE_ITERATIONS){ + ended(); + } + }) + .on("end", ended) + .nodes(sample) + .force("Sample force", forceSample); + console.log("Initialized Hybrid"); + } - sampleSimulation - .force("forces", neighbourSamplingDistance() - .neighbourSize(neighbourSize) - .sampleSize(sampleSize) - .distanceRange(distanceRange) - .distance(distanceFn) - .stableVelocity(0.004) - .stableVeloHandler(function(){sampleSimulation.stop(); ended();}) - ) - .alpha(1).restart(); + function initForces(){ + if (typeof forceSample.stableVelocity == 'function' && + typeof forceSample.stableVeloHandler == 'function') { + forceSample + .stableVelocity(0.000001) + .stableVeloHandler(ended); + } + + if(interpDistanceFn === undefined && + typeof forceFull.distance == 'function') { + interpDistanceFn = forceFull.distance(); + } + } + + function initSimulation(){ + nodes = simulation.nodes(); + simulation + .stop() + .alphaDecay(0) + .alpha(1) + + let sets = takeSampleFrom(nodes, Math.sqrt(nodes.length)); + sample = sets.sample; + remainder = sets.remainder; + } function ended() { - sample.forEach(function (d) { - d.vx = 0; - d.vy = 0; - }); - event.call("startFull"); console.log("Ended sample simulation"); + event.call("startInterp"); + + simulation.stop(); + simulation.force("Sample force", null); + for (let i=sample.size-1; i>=0; i--){ + sample[i].vx=0; + sample[i].vy=0; + } alert('About to interpolate'); if (PIVOTS) { - interpolationPivots(sample, remainder, NUMPIVOTS, distanceFn); + interpolationPivots(sample, remainder, NUMPIVOTS, distanceFn, INTERP_FINE_ITS); } else { - interpBruteForce(sample, remainder, distanceFn); + interpBruteForce(sample, remainder, distanceFn, INTERP_FINE_ITS); } event.call("fullTick"); alert('About to Full run'); @@ -88,17 +118,14 @@ export default function (nodes, config) { } return hybrid = { - distance: function (_) { - return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), hybrid) : distance; + restart: function () { + if(toInit) initialize(); + simulation.restart(); + return hybrid; }, stop: function () { - if (typeof sampleSimulation !== 'undefined') { - sampleSimulation.stop(); - } - if (typeof fullSimulation !== 'undefined') { - fullSimulation.stop(); - } + simulation.stop(); return hybrid; }, @@ -110,10 +137,6 @@ export default function (nodes, config) { return arguments.length ? (NUMPIVOTS = +_, hybrid) : NUMPIVOTS; }, - multiplier: function (_) { - return arguments.length ? (MULTIPLIER = +_, hybrid) : MULTIPLIER; - }, - sampleIterations: function (_) { return arguments.length ? (SAMPLE_ITERATIONS = +_, hybrid) : SAMPLE_ITERATIONS; }, @@ -122,12 +145,12 @@ export default function (nodes, config) { return arguments.length ? (FULL_ITERATIONS = +_, hybrid) : FULL_ITERATIONS; }, - neighbourSize: function (_) { - return arguments.length ? (neighbourSize = +_, hybrid) : neighbourSize; + interpDistanceFn: function (_) { + return arguments.length ? (interpDistanceFn = +_, hybrid) : interpDistanceFn; }, - sampleSize: function (_) { - return arguments.length ? (sampleSize = +_, hybrid) : sampleSize; + interpFindTuneIts: function (_) { + return arguments.length ? (INTERP_FINE_ITS = +_, hybrid) : INTERP_FINE_ITS; }, on: function (name, _) { @@ -142,12 +165,21 @@ export default function (nodes, config) { return arguments.length ? (remainder = _, hybrid) : remainder; }, - stress: function () { - return fullSimulation.force("neighbourSampling").stress(); - } + interpDistanceFn: function (_) { + return arguments.length ? (interpDistanceFn = typeof _ === "function" ? _ : constant(+_), hybrid) : interpDistanceFn; + }, + + simulation: function (_) { + return arguments.length ? (toInit = true, simulation = _, hybrid) : simulation; + }, + + forceSample: function (_) { + return arguments.length ? (forceSample = _, initForces(), hybrid) : forceSample; + }, + + forceFull: function (_) { + return arguments.length ? (forceFull = _, initForces(), hybrid) : forceFull; + }, + }; } - -function readConf(config, prop, def){ - return config.hasOwnProperty(prop) ? config[prop] : def; -}