function doInterpolation(sampleSet, remainderSet, interpSubset, properties) { var distance = calculateDistancePoker; // var distance = calculateEuclideanDistance; console.log("Brute-force"); for (var i = 0; i < remainderSet.length; i++) { var node = remainderSet[i], minNode = sampleSet[0], minDist = 0, sampleCache = []; minDist = distance(node, minNode, properties); for (var j = 1, sample; j < sampleSet.length; j++) { sample = sampleSet[j]; if ((sample !== node) && (distance(node, sample, properties) < minDist)) { minDist = distance(node, sample, properties); minNode = sample; } } // console.log() for (var k = 0; k < interpSubset.length; k++) { sampleCache[k] = distance(node, interpSubset[k], properties); } var radius = distance(node, minNode, properties); placeNearToNearestNeighbour(node, minNode, interpSubset, sampleCache, radius); } } function placeNearToNearestNeighbour(node, minNode, sample, sampleCache, radius) { var dist0 = 0.0, dist90 = 0.0, dist180 = 0.0, dist270 = 0.0, lowBound = 0.0, highBound = 0.0; dist0 = sumDistToSample(node, centerPoint(0, radius, minNode.x, minNode.y), sample, sampleCache); dist90 = sumDistToSample(node, centerPoint(90, radius, minNode.x, minNode.y), sample, sampleCache); dist180 = sumDistToSample(node, centerPoint(180, radius, minNode.x, minNode.y), sample, sampleCache); dist270 = sumDistToSample(node, centerPoint(270, radius, minNode.x, minNode.y), sample, sampleCache); // console.log(dist0, dist90, dist180, dist270); // Determine the closest quadrant if (dist0 == dist180) { if (dist90 > dist270) lowBound = highBound = 270; else lowBound = highBound = 90; } else if (dist90 == dist270) { if (dist0 > dist180) lowBound = highBound = 180; else lowBound = highBound = 0; } else if (dist0 > dist180) { if (dist90 > dist270) { lowBound = 180; highBound = 270; } else { lowBound = 90; highBound = 180; } } else { if (dist90 > dist270) { lowBound = 270; highBound = 360; } else { lowBound = 0; highBound = 90; } } var angle = binarySearch(lowBound, highBound, minNode.x, minNode.y, radius, node, sample, sampleCache); var newPoint = centerPoint(angle, radius, minNode.x, minNode.y); // console.log(newPoint); node.x = newPoint.x; node.y = newPoint.y; // for (var i = 0; i < 20; i++) { // var forces = sumForcesToSample(node, sample, sampleCache); // // console.log(forces); // node.x += forces.x; // node.y += forces.y; // } } function centerPoint(angle, radius, posX, posY) { var x = posX + Math.cos(toRadians(angle) * radius); var y = posY + Math.sin(toRadians(angle) * radius); return { x: x, y: y }; } function toRadians(degrees) { return degrees * (Math.PI / 180); } function sumDistToSample(node, point, sample, sampleCache) { var total = 0.0; // console.log(total, sample); for (var i = 0; i < sample.length; i++) { var s = sample[i]; var realDist = Math.hypot(s.x - point.x, s.y - point.y); var desDist = sampleCache[i]; total += Math.abs(realDist - desDist); } return total; } function sumForcesToSample(node, sample, sampleCache) { var x = 0, y = 0, // len = 0, dist = 0, force, SPRING_FORCE = 0.7; for (var i = 0, unitX, unitY; i < sample.length; i++) { var s = sample[i]; if (s !== node) { unitX = s.x - node.x; unitY = s.y - node.y; // Normalize coordinates len = Math.sqrt(unitX * unitX + unitY * unitY); unitX /= len; unitY /= len; console.log(unitX, unitY); var realDist = Math.sqrt(unitX * unitX + unitY * unitY); var desDist = sampleCache[i]; dist += realDist - desDist; force = (SPRING_FORCE * dist); x += unitX * force; y += unitY * force; } x *= (1.0 / sample.length); y *= (1.0 / sample.length); return { x: x, y: y }; } } function binarySearch(lb, hb, x, y, r, node, sample, sampleCache) { while (lb <= hb) { var mid = Math.round((lb + hb) / 2); if ((mid === lb) || (mid === hb)) { if (sumDistToSample(node, centerPoint(lb, r, x, y), sample, sampleCache) >= sumDistToSample(node, centerPoint(hb, r, x, y), sample, sampleCache)) { return hb; } else { return lb; } } else { var distMidLeft = sumDistToSample(node, centerPoint(mid + 1, r, x, y), sample, sampleCache); var distMidRight = sumDistToSample(node, centerPoint(mid - 1, r, x, y), sample, sampleCache); var distMid = sumDistToSample(node, centerPoint(mid, r, x, y), sample, sampleCache); if (distMid > distMidLeft) { lb = mid + 1; } else if (distMid > distMidRight) { hb = mid - 1; } else { return mid; } } } return -1; }