Browse Source

consistency in physics

flowchartTest
Alex de Mulder 9 years ago
parent
commit
92180442e5
4 changed files with 4383 additions and 4008 deletions
  1. +1
    -1
      dist/vis.css
  2. +4305
    -3972
      dist/vis.js
  3. +1
    -1
      dist/vis.min.css
  4. +76
    -34
      lib/network/modules/PhysicsEngine.js

+ 1
- 1
dist/vis.css View File

@ -1223,4 +1223,4 @@ div.vis-color-picker input.vis-range-brightness {
div.vis-color-picker input.vis-saturation-range { div.vis-color-picker input.vis-saturation-range {
width: 289px !important; width: 289px !important;
}*/
}*/

+ 4305
- 3972
dist/vis.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/vis.min.css
File diff suppressed because it is too large
View File


+ 76
- 34
lib/network/modules/PhysicsEngine.js View File

@ -69,14 +69,12 @@ class PhysicsEngine {
this.body.emitter.on('restorePhysics', () => { this.body.emitter.on('restorePhysics', () => {
this.setOptions(this.options); this.setOptions(this.options);
if (this.ready === true) { if (this.ready === true) {
this.stabilized = false;
this.runSimulation();
this.startSimulation();
} }
}); });
this.body.emitter.on('startSimulation', () => { this.body.emitter.on('startSimulation', () => {
if (this.ready === true) { if (this.ready === true) {
this.stabilized = false;
this.runSimulation();
this.startSimulation();
} }
}) })
this.body.emitter.on('stopSimulation', () => {this.stopSimulation();}); this.body.emitter.on('stopSimulation', () => {this.stopSimulation();});
@ -122,15 +120,14 @@ class PhysicsEngine {
initPhysics() { initPhysics() {
if (this.physicsEnabled === true) { if (this.physicsEnabled === true) {
this.stabilized = false;
if (this.options.stabilization.enabled === true) { if (this.options.stabilization.enabled === true) {
this.body.emitter.emit('_blockRedrawRequests');
this.stabilize(); this.stabilize();
} }
else { else {
this.stabilized = false;
this.ready = true; this.ready = true;
this.body.emitter.emit('zoomExtent', {duration: 0}, true) this.body.emitter.emit('zoomExtent', {duration: 0}, true)
this.runSimulation();
this.startSimulation();
} }
} }
else { else {
@ -139,17 +136,12 @@ class PhysicsEngine {
} }
} }
stopSimulation() {
this.stabilized = true;
if (this.viewFunction !== undefined) {
this.body.emitter.off('initRedraw', this.viewFunction);
this.viewFunction = undefined;
this.body.emitter.emit('_stopRendering');
}
}
runSimulation() {
/**
* Start the simulation
*/
startSimulation() {
if (this.physicsEnabled === true) { if (this.physicsEnabled === true) {
this.stabilized = false;
if (this.viewFunction === undefined) { if (this.viewFunction === undefined) {
this.viewFunction = this.simulationStep.bind(this); this.viewFunction = this.simulationStep.bind(this);
this.body.emitter.on('initRedraw', this.viewFunction); this.body.emitter.on('initRedraw', this.viewFunction);
@ -161,6 +153,25 @@ class PhysicsEngine {
} }
} }
/**
* Stop the simulation, force stabilization.
*/
stopSimulation() {
this.stabilized = true;
this._emitStabilized();
if (this.viewFunction !== undefined) {
this.body.emitter.off('initRedraw', this.viewFunction);
this.viewFunction = undefined;
this.body.emitter.emit('_stopRendering');
}
}
/**
* The viewFunction inserts this step into each renderloop. It calls the physics tick and handles the cleanup at stabilized.
*
*/
simulationStep() { simulationStep() {
// check if the physics have settled // check if the physics have settled
var startTime = Date.now(); var startTime = Date.now();
@ -181,15 +192,9 @@ class PhysicsEngine {
// The event is triggered on the next tick, to prevent the case that // The event is triggered on the next tick, to prevent the case that
// it is fired while initializing the Network, in which case you would not // it is fired while initializing the Network, in which case you would not
// be able to catch it // be able to catch it
var me = this;
var params = {
iterations: this.stabilizationIterations
};
this.stabilizationIterations = 0; this.stabilizationIterations = 0;
this.startedStabilization = false; this.startedStabilization = false;
setTimeout(function () {
me.body.emitter.emit('stabilized', params);
}, 0);
this._emitStabilized();
} }
else { else {
this.stabilizationIterations = 0; this.stabilizationIterations = 0;
@ -198,6 +203,14 @@ class PhysicsEngine {
} }
} }
_emitStabilized() {
if (this.stabilizationIterations > 1) {
setTimeout(() => {
this.body.emitter.emit('stabilized', {iterations: this.stabilizationIterations});
}, 0);
}
}
/** /**
* A single simulation step (or 'tick') in the physics simulation * A single simulation step (or 'tick') in the physics simulation
* *
@ -225,10 +238,7 @@ class PhysicsEngine {
} }
/** /**
* Smooth curves are created by adding invisible nodes in the center of the edges. These nodes are also
* handled in the calculateForces function. We then use a quadratic curve with the center node as control.
* This function joins the datanodes and invisible (called support) nodes into one object.
* We do this so we do not contaminate this.body.nodes with the support nodes.
* Nodes and edges can have the physics toggles on or off. A collection of indices is created here so we can skip the check all the time.
* *
* @private * @private
*/ */
@ -277,6 +287,9 @@ class PhysicsEngine {
} }
/**
* Revert the simulation one step. This is done so after stabilization, every new start of the simulation will also say stabilized.
*/
revert() { revert() {
var nodeIds = Object.keys(this.previousStates); var nodeIds = Object.keys(this.previousStates);
var nodes = this.body.nodes; var nodes = this.body.nodes;
@ -298,10 +311,14 @@ class PhysicsEngine {
} }
} }
/**
* move the nodes one timestap and check if they are stabilized
* @returns {boolean}
*/
moveNodes() { moveNodes() {
var nodesPresent = false; var nodesPresent = false;
var nodeIndices = this.physicsBody.physicsNodeIndices; var nodeIndices = this.physicsBody.physicsNodeIndices;
var maxVelocity = this.options.maxVelocity === 0 ? 1e9 : this.options.maxVelocity;
var maxVelocity = this.options.maxVelocity ? this.options.maxVelocity : 1e9;
var stabilized = true; var stabilized = true;
var vminCorrected = this.options.minVelocity / Math.max(this.body.view.scale,0.05); var vminCorrected = this.options.minVelocity / Math.max(this.body.view.scale,0.05);
@ -325,6 +342,15 @@ class PhysicsEngine {
return true; return true;
} }
/**
* Perform the actual step
*
* @param nodeId
* @param maxVelocity
* @returns {number}
* @private
*/
_performStep(nodeId,maxVelocity) { _performStep(nodeId,maxVelocity) {
var node = this.body.nodes[nodeId]; var node = this.body.nodes[nodeId];
var timestep = this.options.timestep; var timestep = this.options.timestep;
@ -362,6 +388,10 @@ class PhysicsEngine {
return totalVelocity; return totalVelocity;
} }
/**
* calculate the forces for one physics iteration.
*/
calculateForces() { calculateForces() {
this.gravitySolver.solve(); this.gravitySolver.solve();
this.nodesSolver.solve(); this.nodesSolver.solve();
@ -412,24 +442,36 @@ class PhysicsEngine {
* @private * @private
*/ */
stabilize() { stabilize() {
// stop the render loop
this.stopSimulation();
// set stabilze to false
this.stabilized = false;
// block redraw requests
this.body.emitter.emit('_blockRedrawRequests');
this.body.emitter.emit('startStabilizing');
this.startedStabilization = true;
// start the stabilization
if (this.options.stabilization.onlyDynamicEdges === true) { if (this.options.stabilization.onlyDynamicEdges === true) {
this._freezeNodes(); this._freezeNodes();
} }
this.stabilizationSteps = 0;
this.stabilizationIterations = 0;
setTimeout(this._stabilizationBatch.bind(this),0); setTimeout(this._stabilizationBatch.bind(this),0);
} }
_stabilizationBatch() { _stabilizationBatch() {
var count = 0; var count = 0;
while (this.stabilized === false && count < this.options.stabilization.updateInterval && this.stabilizationSteps < this.options.stabilization.iterations) {
while (this.stabilized === false && count < this.options.stabilization.updateInterval && this.stabilizationIterations < this.options.stabilization.iterations) {
this.physicsTick(); this.physicsTick();
this.stabilizationSteps++;
this.stabilizationIterations++;
count++; count++;
} }
if (this.stabilized === false && this.stabilizationSteps < this.options.stabilization.iterations) {
this.body.emitter.emit('stabilizationProgress', {steps: this.stabilizationSteps, total: this.options.stabilization.iterations});
if (this.stabilized === false && this.stabilizationIterations < this.options.stabilization.iterations) {
this.body.emitter.emit('stabilizationProgress', {iterations: this.stabilizationIterations, total: this.options.stabilization.iterations});
setTimeout(this._stabilizationBatch.bind(this),0); setTimeout(this._stabilizationBatch.bind(this),0);
} }
else { else {

Loading…
Cancel
Save