Interp almost-complete brute-force interpolation
This commit is contained in:
@@ -1,60 +1,45 @@
|
||||
export default function(sampleSet, remainderSet, interpSubset, distanceFunction) {
|
||||
export default function(sampleSet, remainderSet, sampleSubset, distanceFn) {
|
||||
var distance = distanceFunction;
|
||||
// var distance = calculateEuclideanDistance;
|
||||
|
||||
// console.log("Brute-force");
|
||||
for (let node of remainderSet) {
|
||||
let nearestSample = undefined,
|
||||
minDist = undefined,
|
||||
sampleSubsetDistanceCache = [];
|
||||
|
||||
for (var i = 0; i < remainderSet.length; i++) {
|
||||
var node = remainderSet[i],
|
||||
minNode = sampleSet[0],
|
||||
minDist = 0,
|
||||
sampleCache = [];
|
||||
for (let sample of sampleSet) {
|
||||
let dist = distanceFn(node, sample);
|
||||
if (nearestSample === undefined || dist < minDist) {
|
||||
minDist = dist;
|
||||
nearestSample = sample;
|
||||
}
|
||||
|
||||
minDist = distance(node, minNode, props, norm);
|
||||
|
||||
for (var j = 1, sample; j < sampleSet.length; j++) {
|
||||
sample = sampleSet[j];
|
||||
if ((sample !== node) && (distance(node, sample, props, norm) < minDist)) {
|
||||
minDist = distance(node, sample, props, norm);
|
||||
minNode = sample;
|
||||
let index = sampleSubset.indexOf(sample);
|
||||
if (index !== -1) {
|
||||
sampleSubsetDistanceCache[index] = dist;
|
||||
}
|
||||
}
|
||||
|
||||
// console.log()
|
||||
|
||||
for (var k = 0; k < interpSubset.length; k++) {
|
||||
sampleCache[k] = distance(node, interpSubset[k], props, norm);
|
||||
}
|
||||
var radius = distance(node, minNode, props, norm);
|
||||
placeNearToNearestNeighbour(node, minNode, interpSubset, sampleCache, radius);
|
||||
placeNearToNearestNeighbour(node, nearestSample, minDist, sampleSubset, sampleSubsetDistanceCache);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function placeNearToNearestNeighbour(node, minNode, sample, sampleCache, radius) {
|
||||
var
|
||||
dist0 = 0.0,
|
||||
dist90 = 0.0,
|
||||
dist180 = 0.0,
|
||||
dist270 = 0.0,
|
||||
function placeNearToNearestNeighbour(node, minNode, radius, samples, realDistances) {
|
||||
let
|
||||
dist0 = sumDistError(pointOnCircle(minNode.x, minNode.y, 0, radius), samples, realDistances),
|
||||
dist90 = sumDistError(pointOnCircle(minNode.x, minNode.y, 90, radius), samples, realDistances),
|
||||
dist180 = sumDistError(pointOnCircle(minNode.x, minNode.y, 180, radius), samples, realDistances),
|
||||
dist270 = sumDistError(pointOnCircle(minNode.x, minNode.y, 270, radius), samples, realDistances),
|
||||
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;
|
||||
@@ -78,8 +63,11 @@ function placeNearToNearestNeighbour(node, minNode, sample, sampleCache, radius)
|
||||
}
|
||||
}
|
||||
|
||||
let angle = binarySearch(lowBound, highBound, minNode.x, minNode.y, radius, node, sample, realDistances);
|
||||
let newPoint = centerPoint(angle, radius, minNode.x, minNode.y);
|
||||
let angle = binarySearchMin(lowBound, highBound,
|
||||
function(angle){
|
||||
return sumDistError(pointOnCircle(minNode.x, minNode.y, angle, radius), samples, realDistances);
|
||||
});
|
||||
let newPoint = pointOnCircle(minNode.x, minNode.y, angle, radius);
|
||||
|
||||
// console.log(newPoint);
|
||||
node.x = newPoint.x;
|
||||
@@ -110,17 +98,13 @@ 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);
|
||||
function sumDistError(currentPos, samples, realDistances) {
|
||||
let total = 0.0;
|
||||
for (let i = 0; i < samples.length; i++) {
|
||||
let sample = samples[i];
|
||||
let lowDDistance = Math.hypot(sample.x - currentPos.x, sample.y - currentPos.y);
|
||||
total += Math.abs(lowDDistance - realDistances[i]);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -165,32 +149,26 @@ function sumForcesToSample(node, sample, sampleCache) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function binarySearch(lb, hb, x, y, r, node, sample, sampleCache) {
|
||||
function binarySearchMin(lb, hb, fn) {
|
||||
while (lb <= hb) {
|
||||
var mid = Math.round((lb + hb) / 2);
|
||||
if(lb === hb) return lb;
|
||||
if(hb-lb == 1) {
|
||||
if (fn(lb) >= fn(hb)) return hb;
|
||||
else return lb;
|
||||
}
|
||||
|
||||
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);
|
||||
let range = hb-lb;
|
||||
let valLowerHalf = fn(lb + range/4);
|
||||
let valHigherHalf = fn(lb + range*3/4);
|
||||
|
||||
if (distMid > distMidLeft) {
|
||||
lb = mid + 1;
|
||||
} else if (distMid > distMidRight) {
|
||||
hb = mid - 1;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
if (valLowerHalf > valHigherHalf)
|
||||
lb = Math.floor((lb + hb) / 2);
|
||||
else if (valLowerHalf < valHigherHalf)
|
||||
hb = Math.ceil((lb + hb) / 2);
|
||||
else {
|
||||
lb += Math.floor(range/4);
|
||||
hb -= Math.ceil(range/4);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user