Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/427.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript中不规则二维数据的插值_Javascript_Math - Fatal编程技术网

JavaScript中不规则二维数据的插值

JavaScript中不规则二维数据的插值,javascript,math,Javascript,Math,我需要找到一个库,它允许我从不规则的2d数据中获取插值。想象一下有这样的东西: var data = [{{x: 0, y: 0, value: 0}, {x: 0.5, y: 1, value: 1}, {x: 1, y: 0, value: 2}}, .... Many more elements] var value = interpolate(data, 0.24, 0.3); // 0.24 = x, 0.3 = y 插值方法的作

我需要找到一个库,它允许我从不规则的2d数据中获取插值。想象一下有这样的东西:

var data = [{{x: 0, y: 0, value: 0},
             {x: 0.5, y: 1, value: 1},
             {x: 1, y: 0, value: 2}}, .... Many more elements]

var value = interpolate(data, 0.24, 0.3); // 0.24 = x, 0.3 = y
插值方法的作用是找到坐标在里面的元素,在本例中是三角形。然后,它在包含它的元素的角点之间插入值

我确实意识到它有很多方面可以优化性能,比如建立一棵树,通过预处理边界框可以快速缩小元素范围。所有这些都很好,但我只是想开始

这里一定有一些库,我可以用它来代替我自己编写的库。

因为javascript中重心插值的搜索结果是不确定的,这里有一些代码可以帮助您开始

该代码将2D点的数据集作为输入,每个点都有一个“值”,一个“新点”有一个未知值。它首先在包含“新点”的数据集中查找最小的三角形,然后使用该三角形查找“新点”的值

使用几百个点的数据集,运行速度相当快。测试、错误检查和优化有很多机会——例如,不要查看数据集中所有可能的三角形。N choose 3随N的立方体增长,因此优化以查看仅由“接近”新点的点构成的三角形可以显示显著的性能提升

// Calculate the area of a triangle
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)
}

// Given a number N, return a list of all possible triples from the list [1..N]
// credit: http://stackoverflow.com/a/5752056/1612562
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 = [];

  // Generates the list [0, ..., N]
  // credit: http://stackoverflow.com/a/20066663/1612562
  var indices = 
      Array.apply(null, {length: N}).map(Number.call, Number);

  fn(3, indices, [], triples);

  return triples;
}

// Given three vertices of a triangle and a point, determine if
// the point falls in the triangle
// credit: https://koozdra.wordpress.com/2012/06/27/javascript-is-point-in-triangle/
// credit: http://www.blackpawn.com/texts/pointinpoly/default.html
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));
}

// Perform barycentric interpolation on a point in a triangle
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;
}

// Find the smallest triangle in the data set containing the new
// point, and perform barycentric interpolation using that triangle 
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)); 
//计算三角形的面积
功能三角形面积(顶点A、顶点B、顶点C){
返回Math.abs((vertexA.x-vertexC.x)*(vertexB.y-vertexA.y)-(
顶点x-顶点b.x)*(顶点x.y-顶点x.y))*0.5)
}
//给定一个数字N,返回列表[1..N]中所有可能的三元组的列表
//学分:http://stackoverflow.com/a/5752056/1612562
函数列表\u三元组(N){
var fn=函数(n,src,got,all){
如果(n==0){
如果(got.length>0){
全部[全部长度]=got;
}
返回;
}
对于(var j=0;j=0)和&(v>=0)和&(u+v<1));
}
//对三角形中的点执行重心插值
函数重心插值(newPoint、vertexA、vertexB、vertexC){
var面积=三角形面积(顶点A、顶点B、顶点C);
var sub_area_1=三角形_area(新点、顶点B、顶点C);
var sub_area_2=三角形_area(顶点、新点、顶点);
var sub_area_3=三角形_area(顶点A、顶点B、新点);
返回((子区域1*vertexA.v)+(子区域2*vertexB.v)+(子区域3*
vertexC.v))/面积;
}
//在包含新三角形的数据集中查找最小三角形
//点,并使用该三角形执行重心插值
函数插值(新点、数据){
var三角形=列表三元组(data.length);
var最小三角形面积=Number.MAX\u值;
var_三角形;
对于(三角形中的t){
var vertexA=数据[三角形[t][0]];
var vertexB=数据[三角形[t][1]];
var vertexC=数据[三角形[t][2];
var in_三角形=is_in_三角形(newPoint、vertexA、vertexB、vertexC);
如果(在三角形中){
if(三角形面积(顶点A、顶点B、顶点C)<最小三角形面积){
最小的_三角形=[vertexA,vertexB,vertexC];
}
}
}
返回最小三角形
?重心插值(新点、最小的_三角形[0]、最小的_三角形[1]、最小的_三角形[2])
:“插值失败:newPoint不在三角形中”;
}
var newPoint={'x':0.24,'y':0.3};
风险值数据=[
{'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}
];
log(插值(newPoint,data));

还有其他类型的空间插值,例如,至少有一种。

感谢rphv,非常感谢:-)这两行是仅声明变量还是分配数值,甚至是对象引用?var三角形=列表三元组(data.length);var最小三角形面积=Number.MAX\u值;是的,这些行声明变量并初始化它们<代码>var最小三角形面积=Number.MAX\u值是一个变量,用于跟踪找到的最小三角形。它被初始化为一个大值<代码>变量三角形=列表三元组(data.length)是一个数组,初始化后可保存由点数组生成的所有可能的三个点集(三元组)的数组,例如,如果点数组为[1,2,3,4],则三元组列表为[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]。