Рекурсивная интерполяция в Javascript - PullRequest
1 голос
/ 27 апреля 2020

Я работаю над браузерной игрой, которая включает интерполяцию cubi c во многих измерениях. Мне нужно взять набор значений и набор координат и вывести приблизительное значение, которое будет иметь точка в пространстве nD. Я нашел несколько отличных уроков по интерполяции 1d cubi c и несколько примеров интерполяции nD cubi c в c ++ (Оба здесь ). Проблема в том, что этот код на С ++ использует много указателей и битовых сдвигов, и я не думаю, что в JS.

1D куб. c интерполяция длинная, но для всех, кто интересуется, выглядит так:

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))), где объявление являются известными значениями, а 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])));
}

2d интерполяция может быть достигнута просто как это:

г (а 1 , б 1 , c 1 , д 1 , а 2 , б 2 , c 2 , д 2 , 3 , б 3 , c 3 , д 3 , 4 , b 4 , c 4 , d 4 , x, y) =

f (f (a 1 , b 1 , c 1 , д 1 , у), f (а 2 , б 2 , c 2 , д 2 , у), ф (а 3 , б 3 , c 3 , д 3 , у), f (а 4 , б * 1 074 * 4 , c 4 , д 4 , у), х)

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() (не знаю, как это будет работать с вложенными массивами) и рекурсивного кода 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 Функция, чтобы повторить это будет?

1 Ответ

2 голосов
/ 27 апреля 2020

Перевод на 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]);
    }
}

Обратите внимание, что параметр n не требуется в JavaScript, так как ему соответствует длина аргумента массива coordinates. Также уровень вложенности p должен быть таким же n. JavaScript не имеет проверки типов во время компиляции, так что свобода здесь дает нам преимущество: нет указателей; p - это массив, но он может быть массивом чисел или массивом чисел, или ... et c.

Для завершения функция 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])));
}
...