EdgeSpring = function(edgeId, graph) { this.edgeId = edgeId; this.graph = graph; var magBallsData = getMagBallsData(this.edgeId); this.start = magBallsData.start; this.end = magBallsData.end; this.desiredLength = magBallsData.length || BALL_DISTANCE; } // FIXME as iterations increase, start introducing some randomness // to the adjustment so that we avoid false equilibriums // Alternatively, larger iterations could increase the acceptable variance EdgeSpring.prototype.adjust = function(results, iterations) { var startPos = this.getAdjustedPosition(this.start, results); var endPos = this.getAdjustedPosition(this.end, results); var vector = Vec3.subtract(endPos, startPos); var length = Vec3.length(vector); var variance = this.getVariance(length); if (Math.abs(variance) <= this.MAX_VARIANCE) { return false; } // adjust by halves until we fall below our variance var adjustmentVector = Vec3.multiply(variance / 4, vector); var newStartPos = Vec3.sum(Vec3.multiply(-1, adjustmentVector), startPos); var newEndPos = Vec3.sum(adjustmentVector, endPos); results[this.start] = newStartPos; results[this.end] = newEndPos; return true; } EdgeSpring.prototype.MAX_VARIANCE = 0.005; EdgeSpring.prototype.getAdjustedPosition = function(nodeId, results) { if (results[nodeId]) { return results[nodeId]; } return this.graph.getNodePosition(nodeId); } EdgeSpring.prototype.getVariance = function(length) { var difference = this.desiredLength - length; return difference / this.desiredLength; }