/**
|
|
* Created by Alex on 2/23/2015.
|
|
*/
|
|
|
|
class SpringSolver {
|
|
constructor(body, options) {
|
|
this.body = body;
|
|
this.options = options;
|
|
}
|
|
|
|
solve() {
|
|
if (this.options.smoothCurves.enabled == true && this.options.smoothCurves.dynamic == true) {
|
|
this._calculateSpringForcesWithSupport();
|
|
}
|
|
else {
|
|
this._calculateSpringForces();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* this function calculates the effects of the springs in the case of unsmooth curves.
|
|
*
|
|
* @private
|
|
*/
|
|
_calculateSpringForces() {
|
|
var edgeLength, edge, edgeId;
|
|
var edges = this.edges;
|
|
|
|
// forces caused by the edges, modelled as springs
|
|
for (edgeId in edges) {
|
|
if (edges.hasOwnProperty(edgeId)) {
|
|
edge = edges[edgeId];
|
|
if (edge.connected === true) {
|
|
// only calculate forces if nodes are in the same sector
|
|
if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) {
|
|
edgeLength = edge.physics.springLength;
|
|
|
|
this._calculateSpringForce(edge.from, edge.to, edgeLength);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* This function calculates the springforces on the nodes, accounting for the support nodes.
|
|
*
|
|
* @private
|
|
*/
|
|
_calculateSpringForcesWithSupport() {
|
|
var edgeLength, edge, edgeId;
|
|
var edges = this.edges;
|
|
|
|
// forces caused by the edges, modelled as springs
|
|
for (edgeId in edges) {
|
|
if (edges.hasOwnProperty(edgeId)) {
|
|
edge = edges[edgeId];
|
|
if (edge.connected === true) {
|
|
// only calculate forces if nodes are in the same sector
|
|
if (this.nodes.hasOwnProperty(edge.toId) && this.nodes.hasOwnProperty(edge.fromId)) {
|
|
if (edge.via != null) {
|
|
var node1 = edge.to;
|
|
var node2 = edge.via;
|
|
var node3 = edge.from;
|
|
|
|
edgeLength = edge.physics.springLength;
|
|
|
|
this._calculateSpringForce(node1, node2, 0.5 * edgeLength);
|
|
this._calculateSpringForce(node2, node3, 0.5 * edgeLength);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* This is the code actually performing the calculation for the function above. It is split out to avoid repetition.
|
|
*
|
|
* @param node1
|
|
* @param node2
|
|
* @param edgeLength
|
|
* @private
|
|
*/
|
|
_calculateSpringForce(node1, node2, edgeLength) {
|
|
var dx, dy, fx, fy, springForce, distance;
|
|
|
|
dx = (node1.x - node2.x);
|
|
dy = (node1.y - node2.y);
|
|
distance = Math.sqrt(dx * dx + dy * dy);
|
|
distance = distance == 0 ? 0.01 : distance;
|
|
|
|
// the 1/distance is so the fx and fy can be calculated without sine or cosine.
|
|
springForce = this.options.springConstant * (edgeLength - distance) / distance;
|
|
|
|
fx = dx * springForce;
|
|
fy = dy * springForce;
|
|
|
|
node1.fx += fx;
|
|
node1.fy += fy;
|
|
node2.fx -= fx;
|
|
node2.fy -= fy;
|
|
}
|
|
}
|
|
|
|
export {SpringSolver};
|