|
|
- /**
- * Created by Alex on 2/25/2015.
- */
-
- class HierarchicalSpringSolver {
- constructor(body, physicsBody, options) {
- this.body = body;
- this.physicsBody = physicsBody;
- this.options = options;
- }
-
- /**
- * This function calculates the springforces on the nodes, accounting for the support nodes.
- *
- * @private
- */
- solve() {
- var edgeLength, edge, edgeId;
- var dx, dy, fx, fy, springForce, distance;
- var edges = this.body.edges;
-
- var nodes = this.physicsBody.calculationNodes;
- var nodeIndices = this.physicsBody.calculationNodeIndices;
-
- // initialize the spring force counters
- for (let i = 0; i < nodeIndices.length; i++) {
- let node1 = nodes[nodeIndices[i]];
- node1.springFx = 0;
- node1.springFy = 0;
- }
-
-
- // 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.body.nodes[edge.toId] !== undefined && this.body.nodes[edge.fromId] !== undefined) {
- edgeLength = edge.properties.length === undefined ? this.options.springLength : edge.properties.length;
-
- dx = (edge.from.x - edge.to.x);
- dy = (edge.from.y - edge.to.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;
-
- if (edge.to.level != edge.from.level) {
- edge.to.springFx -= fx;
- edge.to.springFy -= fy;
- edge.from.springFx += fx;
- edge.from.springFy += fy;
- }
- else {
- let factor = 0.5;
- edge.to.fx -= factor*fx;
- edge.to.fy -= factor*fy;
- edge.from.fx += factor*fx;
- edge.from.fy += factor*fy;
- }
- }
- }
- }
- }
-
- // normalize spring forces
- var springForce = 1;
- var springFx, springFy;
- for (let i = 0; i < nodeIndices.length; i++) {
- var node = nodes[nodeIndices[i]];
- springFx = Math.min(springForce,Math.max(-springForce,node.springFx));
- springFy = Math.min(springForce,Math.max(-springForce,node.springFy));
-
- node.fx += springFx;
- node.fy += springFy;
- }
-
- // retain energy balance
- var totalFx = 0;
- var totalFy = 0;
- for (let i = 0; i < nodeIndices.length; i++) {
- var node = nodes[nodeIndices[i]];
- totalFx += node.fx;
- totalFy += node.fy;
- }
- var correctionFx = totalFx / nodeIndices.length;
- var correctionFy = totalFy / nodeIndices.length;
-
- for (let i = 0; i < nodeIndices.length; i++) {
- var node = nodes[nodeIndices[i]];
- node.fx -= correctionFx;
- node.fy -= correctionFy;
- }
- }
-
- }
-
- export {HierarchicalSpringSolver};
|