How do I compute the linear index of a 3D coordinate and vice versa?

前端 未结 2 646
长情又很酷
长情又很酷 2021-02-06 00:30

If I have a point (x, y z), how do I find the linear index, i for that point? My numbering scheme would be (0,0,0) is 0, (1, 0, 0) is 1, . . ., (0, 1, 0) is the max-x-dimension,

2条回答
  •  忘了有多久
    2021-02-06 01:08

    If you have no upper limit on the coordinates, you can number them from origo and outwards. Layer by layer.

    (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
    

    The inverse is harder, since you would have to solve a 3rd degree polynomial.

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

    where

    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) could either be calculated from the large analytic solution, or searched for with some numeric method.


    Here is my attempt at an algebraic solution (javascript). I am using the substitutions p = a+b+c, q = a+b, r = a to simplify the equations.

    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];
    }
    

提交回复
热议问题