由于搜索关于在javascript中的重心插值的结果不确定,这里提供了一些代码,可能会帮助你入门。
此代码以数据集的2D点为输入,每个点都有一个“值”,以及一个未知值的“新点”。它首先找到包含“新点”的数据集中最小的三角形,然后使用该三角形执行重心插值以找到“新点”的值。
对于几百个点的数据集,这个程序运行得相当快。有很多测试、错误检查和优化的机会——例如,不要查看数据集中的每个可能的三角形。N选择3随着N的立方增长,因此优化只查看由“接近”“新点”的点组成的三角形可以显示出显著的性能提升。
function triangle_area(vertexA, vertexB, vertexC) {
return Math.abs(((vertexA.x - vertexC.x) * (vertexB.y - vertexA.y) - (
vertexA.x - vertexB.x) * (vertexC.y - vertexA.y)) * 0.5)
}
function list_triples(N) {
var fn = function(n, src, got, all) {
if (n == 0) {
if (got.length > 0) {
all[all.length] = got;
}
return;
}
for (var j = 0; j < src.length; j++) {
fn(n - 1, src.slice(j + 1), got.concat([ src[j] ]), all);
}
return;
}
var triples = [];
var indices =
Array.apply(null, {length: N}).map(Number.call, Number);
fn(3, indices, [], triples);
return triples;
}
function is_in_triangle(newPoint, vertexA, vertexB, vertexC) {
var v0 = [vertexC.x - vertexA.x, vertexC.y - vertexA.y];
var v1 = [vertexB.x - vertexA.x, vertexB.y - vertexA.y];
var v2 = [newPoint.x - vertexA.x, newPoint.y - vertexA.y];
var dot00 = (v0[0] * v0[0]) + (v0[1] * v0[1]);
var dot01 = (v0[0] * v1[0]) + (v0[1] * v1[1]);
var dot02 = (v0[0] * v2[0]) + (v0[1] * v2[1]);
var dot11 = (v1[0] * v1[0]) + (v1[1] * v1[1]);
var dot12 = (v1[0] * v2[0]) + (v1[1] * v2[1]);
var invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
return ((u >= 0) && (v >= 0) && (u + v < 1));
}
function barycentric_interpolate(newPoint, vertexA, vertexB, vertexC) {
var area = triangle_area(vertexA, vertexB, vertexC);
var sub_area_1 = triangle_area(newPoint, vertexB, vertexC);
var sub_area_2 = triangle_area(vertexA, newPoint, vertexC);
var sub_area_3 = triangle_area(vertexA, vertexB, newPoint);
return ((sub_area_1 * vertexA.v) + (sub_area_2 * vertexB.v) + (sub_area_3 *
vertexC.v)) / area;
}
function interpolate(newPoint, data) {
var triangles = list_triples(data.length);
var smallest_triangle_area = Number.MAX_VALUE;
var smallest_triangle;
for (t in triangles) {
var vertexA = data[triangles[t][0]];
var vertexB = data[triangles[t][1]];
var vertexC = data[triangles[t][2]];
var in_triangle = is_in_triangle(newPoint, vertexA, vertexB, vertexC);
if (in_triangle) {
if (triangle_area(vertexA, vertexB, vertexC) < smallest_triangle_area) {
smallest_triangle = [vertexA, vertexB, vertexC];
}
}
}
return smallest_triangle
? barycentric_interpolate(newPoint, smallest_triangle[0], smallest_triangle[1], smallest_triangle[2])
: "Interpolation failed: newPoint isn't in a triangle";
}
var newPoint = {'x': 0.24, 'y': 0.3};
var data = [
{'x': 0, 'y': 0, 'v': 0},
{'x': 0.5, 'y': 1, 'v': 1},
{'x': 1, 'y': 0, 'v': 2},
{'x': 1.5, 'y': 2.5, 'v': 1.5},
{'x': 2, 'y': 1, 'v': 0.5}
];
console.log(interpolate(newPoint, data));
还有其他种类的空间插值,例如克里金插值, 它至少有一个现成的.js库。
var smallest_triangle_area = Number.MAX_VALUE;
是一个变量,用于跟踪找到的最小三角形。它被初始化为一个大值。var triangles = list_triples(data.length);
是一个数组,它被初始化为包含从点数组生成的所有可能的三个点(三元组)集合的数组,例如,如果点数组是[1,2,3,4],则三元组列表是[[1,2,3], [1,2,4],[1,3,4],[2,3,4]]。 - rphv