Merge branch 'review'
* review: Avoid divide by zero and massive forces at small distances Renamed f -> a. f is actually representing acceleration. A few updates based on code review by amcameron add review comments for springyui.js Add some code review comments.
This commit is contained in:
commit
9a196f8673
17
springy.js
17
springy.js
|
@ -310,7 +310,7 @@ Layout.ForceDirected.prototype.applyCoulombsLaw = function() {
|
||||||
if (point1 !== point2)
|
if (point1 !== point2)
|
||||||
{
|
{
|
||||||
var d = point1.p.subtract(point2.p);
|
var d = point1.p.subtract(point2.p);
|
||||||
var distance = d.magnitude() + 1.0;
|
var distance = d.magnitude() + 0.1; // avoid massive forces at small distances (and divide by zero)
|
||||||
var direction = d.normalise();
|
var direction = d.normalise();
|
||||||
|
|
||||||
// apply force to each end point
|
// apply force to each end point
|
||||||
|
@ -343,22 +343,27 @@ Layout.ForceDirected.prototype.attractToCentre = function() {
|
||||||
|
|
||||||
Layout.ForceDirected.prototype.updateVelocity = function(timestep) {
|
Layout.ForceDirected.prototype.updateVelocity = function(timestep) {
|
||||||
this.eachNode(function(node, point) {
|
this.eachNode(function(node, point) {
|
||||||
point.v = point.v.add(point.f.multiply(timestep)).multiply(this.damping);
|
// Is this, along with updatePosition below, the only places that your
|
||||||
point.f = new Vector(0,0);
|
// integration code exist?
|
||||||
|
point.v = point.v.add(point.a.multiply(timestep)).multiply(this.damping);
|
||||||
|
point.a = new Vector(0,0);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Layout.ForceDirected.prototype.updatePosition = function(timestep) {
|
Layout.ForceDirected.prototype.updatePosition = function(timestep) {
|
||||||
this.eachNode(function(node, point) {
|
this.eachNode(function(node, point) {
|
||||||
|
// Same question as above; along with updateVelocity, is this all of
|
||||||
|
// your integration code?
|
||||||
point.p = point.p.add(point.v.multiply(timestep));
|
point.p = point.p.add(point.v.multiply(timestep));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Calculate the total kinetic energy of the system
|
||||||
Layout.ForceDirected.prototype.totalEnergy = function(timestep) {
|
Layout.ForceDirected.prototype.totalEnergy = function(timestep) {
|
||||||
var energy = 0.0;
|
var energy = 0.0;
|
||||||
this.eachNode(function(node, point) {
|
this.eachNode(function(node, point) {
|
||||||
var speed = point.v.magnitude();
|
var speed = point.v.magnitude();
|
||||||
energy += speed * speed;
|
energy += 0.5 * point.m * speed * speed;
|
||||||
});
|
});
|
||||||
|
|
||||||
return energy;
|
return energy;
|
||||||
|
@ -488,11 +493,11 @@ Layout.ForceDirected.Point = function(position, mass) {
|
||||||
this.p = position; // position
|
this.p = position; // position
|
||||||
this.m = mass; // mass
|
this.m = mass; // mass
|
||||||
this.v = new Vector(0, 0); // velocity
|
this.v = new Vector(0, 0); // velocity
|
||||||
this.f = new Vector(0, 0); // force
|
this.a = new Vector(0, 0); // acceleration
|
||||||
};
|
};
|
||||||
|
|
||||||
Layout.ForceDirected.Point.prototype.applyForce = function(force) {
|
Layout.ForceDirected.Point.prototype.applyForce = function(force) {
|
||||||
this.f = this.f.add(force.divide(this.m));
|
this.a = this.a.add(force.divide(this.m));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Spring
|
// Spring
|
||||||
|
|
|
@ -34,6 +34,7 @@ jQuery.fn.springy = function(params) {
|
||||||
|
|
||||||
var canvas = this[0];
|
var canvas = this[0];
|
||||||
var ctx = canvas.getContext("2d");
|
var ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
var layout = this.layout = new Layout.ForceDirected(graph, stiffness, repulsion, damping);
|
var layout = this.layout = new Layout.ForceDirected(graph, stiffness, repulsion, damping);
|
||||||
|
|
||||||
// calculate bounding box of graph layout.. with ease-in
|
// calculate bounding box of graph layout.. with ease-in
|
||||||
|
@ -82,6 +83,8 @@ jQuery.fn.springy = function(params) {
|
||||||
selected = nearest = dragged = layout.nearest(p);
|
selected = nearest = dragged = layout.nearest(p);
|
||||||
|
|
||||||
if (selected.node !== null) {
|
if (selected.node !== null) {
|
||||||
|
// Part of the same bug mentioned later. Store the previous mass
|
||||||
|
// before upscaling it for dragging.
|
||||||
dragged.point.m = 10000.0;
|
dragged.point.m = 10000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +105,9 @@ jQuery.fn.springy = function(params) {
|
||||||
});
|
});
|
||||||
|
|
||||||
jQuery(window).bind('mouseup',function(e) {
|
jQuery(window).bind('mouseup',function(e) {
|
||||||
|
// Bug! Node's mass isn't reset on mouseup. Nodes which have been
|
||||||
|
// dragged don't repulse very well. Store the initial mass in mousedown
|
||||||
|
// and then restore it here.
|
||||||
dragged = null;
|
dragged = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -122,6 +128,7 @@ jQuery.fn.springy = function(params) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Node.prototype.getHeight = function() {
|
Node.prototype.getHeight = function() {
|
||||||
|
// Magic number with no explanation.
|
||||||
return 20;
|
return 20;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user