Как вычислить линейный индекс 3D-координаты и наоборот?

Если у меня есть точка (x, y z), Как найти линейный индекс, i для этой точки? Моя схема нумерации будет (0,0,0) равна 0, (1, 0, 0) равна 1, . . ., (0, 1, 0) является max-X-размерностью, .... Кроме того, если у меня есть линейная координата, i, как найти (x, y, z)? Я не могу найти это в google, все результаты заполнены другими не относящимися к делу вещами. Спасибо!

2 ответов


существует несколько способов отображения 3D-координаты на одно число. Есть один способ.

некоторая функция f(x,y,z) дает линейный индекс координаты (x,y,z). Он имеет некоторые константы a,b,c, d, которые мы хотим получить, чтобы мы могли написать полезную функцию преобразования.

f(x,y,z) = a*x + b*y + c*z + d

вы указали, что (0,0,0) соответствует 0. Итак:

f(0,0,0) = a*0 + b*0 + c*0 + d = 0
d = 0
f(x,y,z) = a*x + b*y + c*z

это решаемо. Вы указали, что (1,0,0) соответствует 1. Итак:

f(1,0,0) = a*1 + b*0 + c*0 = 1
a = 1
f(x,y,z) = x + b*y + c*z

это решаемо. Давайте произвольно решите, что следующее наибольшее число после (MAX_X, 0, 0) равно (0,1,0).

f(MAX_X, 0, 0) = MAX_X
f(0, 1, 0) = 0 + b*1 + c*0 = MAX_X + 1
b = MAX_X + 1
f(x,y,z) = x + (MAX_X + 1)*y + c*z

это b решено. Давайте произвольно решим, что следующее наибольшее число после (MAX_X, MAX_Y, 0) равно (0,0,1).

f(MAX_X, MAX_Y, 0) = MAX_X + MAX_Y * (MAX_X + 1)
f(0,0,1) = 0 + (MAX_X + 1) * 0  + c*1 = MAX_X + MAX_Y * (MAX_X + 1) + 1
c = MAX_X + MAX_Y * (MAX_X + 1) + 1
c = (MAX_X + 1) + MAX_Y * (MAX_X + 1)
c = (MAX_X + 1) * (MAX_Y + 1)

теперь, когда мы знаем a, b, c и d, мы можем написать вашу функцию следующим образом:

function linearIndexFromCoordinate(x,y,z, max_x, max_y){
    a = 1
    b = max_x + 1
    c = (max_x + 1) * (max_y + 1)
    d = 0
    return a*x + b*y + c*z + d
}

вы можете получить координату из линейного индекса по аналогичной логике. У меня есть поистине удивительное доказательство: что эта страница слишком мала, чтобы содержать. Так что я пропущу лекция по математике и просто дать вам окончательный метод.

function coordinateFromLinearIndex(idx, max_x, max_y){
    x =  idx % (max_x+1)
    idx /= (max_x+1)
    y = idx % (max_y+1)
    idx /= (max_y+1)
    z = idx
    return (x,y,z)
}

если у вас нет верхнего предела координат, вы можете пронумеровать их от origo и наружу. Слой за слоем.

(0,0,0) -> 0
(0,0,1) -> 1
(0,1,0) -> 2
(1,0,0) -> 3
(0,0,2) -> 4
   :       :
(a,b,c) -> (a+b+c)·(a+b+c+1)·(a+b+c+2)/6 + (a+b)·(a+b+1)/2 + a

обратное сложнее, так как вам придется решить полином 3-й степени.

m1 = InverseTetrahedralNumber(n)
m2 = InverseTriangularNumber(n - Tetra(m1))
a = n - Tetra(m1) - Tri(m2)
b = m2 - a
c = m1 - m2

здесь

InverseTetrahedralNumber(n) = { x ∈ ℕ | Tetra(n) ≤ x < Tetra(n+1) } 
Tetra(n) = n·(n+1)·(n+2)/6 
InverseTriangularNumber(n) = { x ∈ ℕ | Tri(n) ≤ x < Tri(n+1) } 
Tri(n) = n·(n+1)/2

InverseTetrahedralNumber(n) может быть вычислено из большой аналитическое решение, или искали с какой-то численный метод.


вот моя попытка алгебраической решение (javascript). Я использую замены p = a+b+c, q = a+b, r = a для упрощения уравнений.

function index(a,b,c) {
    var r = a;
    var q = r + b;
    var p = q + c;
    return (p*(p+1)*(p+2) + 3*q*(q+1) + 6*r)/6;
}

function solve(n) {
    if (n <= 0) {
        return [0,0,0];
    }

    var sqrt = Math.sqrt;
    var cbrt = function (x) { return Math.pow(x,1.0/3); };

    var X = sqrt(729*n*n - 3);
    var Y = cbrt(81*n + 3*X);
    var p = Math.floor((Y*(Y-3)+3)/(Y*3));
    if ((p+1)*(p+2)*(p+3) <= n*6) p++;
    var pp = p*(p+1)*(p+2);

    var Z = sqrt(72*n+9-12*pp);
    var q = Math.floor((Z-3)/6);
    if (pp + (q+1)*(q+2)*3 <= n*6) q++;
    var qq = q*(q+1);

    var r = Math.floor((6*n-pp-3*qq)/6);
    if (pp + qq*3 + r*6 < n*6) r++;

    return [r, q - r, p - q];
}