Javascript 中的递归插值

Recursive Interpolation in Javascript

我正在开发一款网页游戏,其中包含多维度的三次插值。我需要获取一组值和一组坐标,并输出 nD space 中的点的估计值。我找到了一些很棒的一维三次插值教程,以及一些用 c++ 编写的 nD 三次插值示例(两者都是 here)。问题是这个c++代码使用了很多指针和位移位器,我认为JS没有。

一维三次插值很长,但是有兴趣的人看起来像这样:

f(a, b, c, d, x) = b + 0.5 * x*(c - a + x*(2*a - 5*b + 4*c - d + x*(3 *(b - c) + d - a))), 其中 a-d 是已知值,x 是 0 到 1 之间的值,它决定了点在 b 和 c 之间的相对位置

Js:

function interpolate(p, x){
    return p[1] + 0.5 * x*(p[2] - p[0] + x*(2*p[0] - 5*p[1] + 4*p[2] - p[3] + x*(3*(p[1] - p[2]) + p[3] - p[0])));
}

二维插值可以像这样简单地实现:

g(a1, b1, c1, d1,a2,b2,c2,d2, a3, b3, c3, d3, a4, b4, c4, d4, x, y) =

f(f(a1, b1, c1, d1, y), f(a2, b2, c2, d2, y), f(a3, b3, c 3, d3, y), f(a4, b4 , c4, d4, y), x)

Js:

function interpolate2d(arr, x, y){
  let a = [
    interpolate(arr[0], y),
    interpolate(arr[1], y),
    interpolate(arr[2], y),
    interpolate(arr[3], y),
  ];
  return interpolate(a, x);
}

3d同理:

function interpolate3d(arr, x, y, z){
  let a = [
    interpolate2d(arr[0], y, z),
    interpolate2d(arr[1], y, z),
    interpolate2d(arr[2], y, z),
    interpolate2d(arr[3], y, z)
  ];
  return interpolate(a, x);
}

我是 Js 的新手,(刚从 c++ 和 java 转过来)并且不知道很多额外的功能。我没有在网上找到任何东西,除了 Array.reduce()(不知道它如何处理嵌套数组)和上面 link 中的递归 C++ 代码:

double nCubicInterpolate (int n, double* p, double coordinates[]) {
    assert(n > 0);
    if (n == 1) {
        return cubicInterpolate(p, *coordinates);
    }
    else {
        double arr[4];
        int skip = 1 << (n - 1) * 2;
        arr[0] = nCubicInterpolate(n - 1, p, coordinates + 1);
        arr[1] = nCubicInterpolate(n - 1, p + skip, coordinates + 1);
        arr[2] = nCubicInterpolate(n - 1, p + 2*skip, coordinates + 1);
        arr[3] = nCubicInterpolate(n - 1, p + 3*skip, coordinates + 1);
        return cubicInterpolate(arr, *coordinates);
    }
}

复制这个的 Js 函数是什么?

JavaScript 的翻译可以是:

function nCubicInterpolate(p, coordinates) {
    if (coordinates.length == 1) {
        return cubicInterpolate(p, coordinates[0]);
    } else {
        let fewerCoordinates = coordinates.slice(1);
        let arr = p.map(hyperplane => nCubicInterpolate(hyperplane, fewerCoordinates));
        return cubicInterpolate(arr, coordinates[0]);
    }
}

请注意,JavaScript 中不需要参数 n,因为 coordinates 数组参数的长度与其对应。 p 的嵌套级别也应与 n 相同。 JavaScript 没有编译时类型检查,因此自由在这里成为我们的优势:没有指针; p是一个数组,但它可以是一个数字数组,或者是一个数字数组,或者...等等

为了完整起见,cubicInterpolate 函数与您在问题中指定的一样:

function cubicInterpolate(p, x) {
    return p[1] + 0.5 * x*(p[2] - p[0] + x*(2*p[0] - 5*p[1] + 4*p[2] - p[3] + x*(3*(p[1] - p[2]) + p[3] - p[0])));
}