From 8f80f46653f3f0f461eacb1a1ea4a70dc0fe08a1 Mon Sep 17 00:00:00 2001 From: Pitchaya Boonsarngsuk <2285135b@student.gla.ac.uk> Date: Mon, 5 Feb 2018 20:07:11 +0000 Subject: [PATCH] Update readme --- README.md | 140 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 4848e0a..f847074 100644 --- a/README.md +++ b/README.md @@ -75,37 +75,25 @@ function distance() { } ``` -The distance accessor is invoked for each pair of node, being passed the two nodes as two arguments as follow: +The distance accessor is invoked for each pair of node. If it is a function, the two nodes will be passed as the two arguments as follow: + ```js function distance(nodeA, nodeB) { return NumberDistanceBetweenAandB; } ``` + The resulting number is then stored internally, such that the distance of each link is only recomputed when the force is initialized or when this method is called with a new *distance*, and not on every application of the force. # *springLink*.**iterations**([*iterations*]) If *iterations* is specified, sets the number of iterations per application to the specified number and returns this force. If *iterations* is not specified, returns the current iteration count which defaults to 1. Increasing the number of iterations greatly increases the rigidity of the constraint, but also increases the runtime cost to evaluate the force. -### Neighbour and Sampling - TO REWRITE +### Neighbour and Sampling -The Neighbour and Sampling algorithm tries to group the nodes based on the distance between them. If the nodes have a low distance, then the force attracts them to each other. If the nodes have a high distance, then the repulsive force pushes them further apart from each other. - -In order for it to work properly, a distance function should be specified. +The neighbour and sampling algorithm simplifies the model by only calculating the spring force of each node against several nearby and random nodes, at the cost of providing less accurate layout. In order for it to work properly, a distance function should be specified. # d3.**forceNeighbourSampling**() [<>](src/neighbourSampling.js "Source") -Initializes the Neighbour and Sampling algorithm with default parameters. - -# *neighbourSampling*.**id**([*id*]) - -If *id* is specified, sets the node id accessor to the specified function and returns this force. If *id* is not specified, returns the current node id accessor, which defaults to the numeric *node*.index: - -```js -function id(d) { - return d.index; -} -``` - -The id accessor is invoked for each node whenever the force is initialized, as when the nodes change, being passed the node and its zero-based index. +Initializes the Neighbour and Sampling force with default parameters. # *neighbourSampling*.**distance**([*distance*]) [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L230 "Source") @@ -117,27 +105,125 @@ function distance() { } ``` -# *neighbourSampling*.**neighbourSize**([*neighbourSize*]) [<>](src/neighbourSampling.js#L222 "Source") +The distance accessor is invoked for each pair of node. If it is a function, the two nodes will be passed as the two arguments as follow: -If *neighbourSize* is specified, sets the neighbour set size to the specified number and returns this force. If *neighbourSize* is not specified, returns the current value, which defaults to 6. +```js +function distance(nodeA, nodeB) { return NumberDistanceBetweenAandB; } +``` -# *neighbourSampling*.**sampleSize**([*sampleSize*]) [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L226 "Source") +# *neighbourSampling*.**neighbourSize**([*neighbourSize*]) -If *sampleSize* is specified, sets the sample set size to the specified number and returns this force. If *sampleSize* is not specified, returns the current value, which defaults to 3. +If *neighbourSize* is specified, sets the neighbour set size to the specified number and returns this force. If *neighbourSize* is not specified, returns the current value, which defaults to 10. -# *neighbourSampling*.**stress**() [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L234 "Source") +# *neighbourSampling*.**sampleSize**([*sampleSize*]) -Returns the stress of the layout. +If *sampleSize* is specified, sets the sample set size to the specified number and returns this force. If *sampleSize* is not specified, returns the current value, which defaults to 10. -# *neighbourSampling*.**velocity**() [<>](https://github.com/sReeper/d3-neighbour-sampling/blob/master/src/neighbourSampling.js#L238 "Source") +# *neighbourSampling*.**latestAccel**() -Returns the average velocity of the iteration. +Returns the average velocity changes of the latest iteration. -### Hybrid Layout +# *neighbourSampling*.**stableVelocity**([*threshold*]) +If *threshold* is specified, sets a threshold and returns this force. When the average velocity changes of the system goes below the threshold, the function [onStableVelo's handler](#neighbourSampling_latestForce) will be called. Set it to a number less than 0 or remove the [handler](#neighbourSampling_latestForce) to disable the threshold checking. If *threshold* is not specified, returns the current value, which defaults to 0. + +# *neighbourSampling*.**onStableVelo**([*handler*]) + +If *handler* is specified, sets the handler function which will be called at the end of each iteration if the average velocity changes of the system goes below the [threshold](#neighbourSampling_stableVelocity). To remove the handler, change it to null. If *threshold* is not specified, returns the current value, which defaults to null. + +### Hybrid Layout Simulation - TO WRITE + +The hybrid layout algorithm reduces the computation power usage even further by performing neighbour and sampling algorithm on only $\sqrt{n}$ sample subset of the data, and interpolating the rest in. Neighbour and sampling algorithm may also be ran again over the full dataset after the interpolation to refine the layout. This algorithm is only recommended for visualizing larger dataset. + +# d3.**hybridSimulation**(*simulation*, *forceSample*, [*forceFull*]) [<>](src/hybridSimulation.js "Source") + +Creates a new hybrid layout simulation default parameters. The simulation will takeover control of [d3.forceSimulation](https://github.com/d3/d3-force#forceSimulation) provided (*simulation* parameter). *forceSample* and *forceFull* are pre-configured [d3.forceNeighbourSampling](#forceNeighbourSampling) forces to be run over the $\sqrt{n}$ samples and full dataset respectively. While unsupported, other D3 forces such as [d3.forceLinkFullyConnected](forceLinkFullyConnected) may also work. + +*forceSample* may have [stableVelocity](neighbourSampling_stableVelocity) configured to end the simulation and begin the interpolation phase early, but any [handler](neighbourSampling_onStableVelo) functions will be replaced be hybridSimulation's own internal function. + +*forceSample* may be absent, null, or undefined to skip the final refinement. + +*simulation* should have already been loaded with nodes. If there are any changes in the list of nodes, the simulation have to be re-set using the [.simulation](#hybrid_simulation) method. + +# *hybrid*.**simulation**([*simulation*]) + +If *simulation* is specified, sets the [d3.forceSimulation](https://github.com/d3/d3-force#forceSimulation) to the given object and returns this layout simulation. Node list will be refreshed. If *simulation* is not specified, returns the current value, which defaults to 20. + +# *hybrid*.**subSet**() + +Returns the list of nodes in the $\sqrt{n}$ sample set. This is randomly selected on initialization or the nodes list have been refreshed by [.simulation](#hybrid_simulation) method. These nodes will be placed on 2D space from the beginning. + +# *hybrid*.**nonSubSet**() + +Returns the list of nodes outside of the $\sqrt{n}$ sample set. This is randomly selected on initialization or the nodes list have been refreshed by [.simulation](#hybrid_simulation) method. These nodes will be interpolated onto 2D space later on. + +# *hybrid*.**forceSample**([*force*]) + +If *force* is specified, sets the neighbour and sampling force to run on the $\sqrt{n}$ samples before interpolation and returns this layout simulation. The same limitation applies: [stableVelocity](neighbourSampling_stableVelocity) may be configured to end the simulation and begin the interpolation phase early, but any [handler](neighbourSampling_onStableVelo) functions will be replaced be hybridSimulation's own internal function. If *force* is not specified, returns the current force object. + +# *hybrid*.**forceFull**([*force*]) + +If *force* is specified, sets the neighbour and sampling force to run on the whole dataset after interpolation and returns this layout simulation. If set to null, the process will be skipped. If *force* is not specified, returns the current force object. + +# *hybrid*.**sampleIterations**([*iterations*]) + +If *iterations* is specified, sets the number of iterations to run neighbour and sampling on the $\sqrt{n}$ samples before interpolation and returns this layout simulation. If *iterations* is not specified, returns the current value, which defaults to 300. + +# *hybrid*.**fullIterations**([*iterations*]) + +If *iterations* is specified, sets the number of iterations to run neighbour and sampling on the whole dataset after interpolation and returns this layout simulation. If set to a number less than 1, the process will be skipped. If *iterations* is not specified, returns the current value, which defaults to 20. + +# *hybrid*.**numPivots**([*number*]) + +If *number* is specified, sets the number of pivots used to find parents during the interpolation process and returns this layout simulation. If *number* is less than 1, brute-force method will be used instead. If *number* is not specified, returns the current value, which defaults to 0 (brute-force method). + +# *hybrid*.**interpDistanceFn**([*distance*]) + +If *distance* is specified, sets the distance accessor used during the interpolation process to the specified number or function and returns this layout simulation. If *distance* is not specified, returns the current distance accessor, which defaults to the one provided by the force for full dataset or + +```js +function distance() { + return 300; +} +``` + +If *distance* is a function, two nodes will be passed as the two arguments as follow: + +```js +function distance(nodeA, nodeB) { return NumberDistanceBetweenAandB; } +``` +# *hybrid*.**interpFindTuneIts**([*number*]) + +During the interpolation, each node will find a "parent", a near sample node whose 2D location is known. The parent will be used to find an initial location for the node. After that, spring forces are applied to the node against $\sqrt{\sqrt{n}}$ samples to fine-tune the location for a *number* of iterations. This is not to be confused with the neighbour and sampling refinement after the entire interpolation process is completed. + +If *number* is specified, sets the number of refinement during the interpolation process and returns this layout simulation. If *number* is not specified, returns the current value, which defaults to 20. + +# hybrid.on(*typenames*, [*listener*]) + +If *listener* is specified, sets the event *listener* for the specified *typenames* and returns this layout simulation. If an event listener was already registered for the same type and name, the existing listener is removed before the new listener is added. If *listener* is null, removes the current event listeners for the specified *typenames*, if any. If *listener* is not specified, returns the first currently-assigned listener matching the specified *typenames*, if any. When a specified event is dispatched, each *listener* will be invoked with the `this` context as the simulation. + +The *typenames* is a string containing one or more *typename* separated by whitespace. Each *typename* is a *type*, optionally followed by a period (`.`) and a *name*, such as `tick.foo` and `tick.bar`; the name allows multiple listeners to be registered for the same *type*. The *type* must be one of the following: + +* `sampleTick` - after each update of the simulation on the $\sqrt{n}$ subset. +* `fullTick` - after each update of the simulation on the full dataset. +* `startInterp` - just before the interpolation process +* `end` - after the hybrid sumulation ends. + +Note that *tick* events are not dispatched when [*simulation*.tick](#simulation_tick) is called manually; events are only dispatched by the internal timer and are intended for interactive rendering of the simulation. To affect the simulation, register [forces](#simulation_force) instead of modifying nodes’ positions or velocities inside a tick event listener. + +See [*dispatch*.on](https://github.com/d3/d3-dispatch#dispatch_on) for details. + +# *hybrid*.**restart**() + +Start or continue the simulation where it was left off and returns this layout simulation. + +# *hybrid*.**stop**() + +Stops the simulation, if it is running, and returns this layout simulation. If the it has already stopped, this method does nothing. ### Miscellaneous # d3.**calculateStress**(*nodes*, *distance*) [<>](src/stress.js "Source") + Calculate stress of a whole system, based on sum-of-squared errors of inter-object distances. *nodes* is the array of all nodes in the system and *distance* is the function to calculate the desired distance between two node objects. *distance* is expected to have the same prototype as the one in [springLink](#springLink_distance).