如果我有一个点 (x, yz),我如何找到该点的线性索引 i?我的编号方案是 (0,0,0) is 0, (1, 0, 0) is 1, . . ., (0, 1, 0) 是最大 x 维度, .... 另外,如果我有一个线性坐标 i,我如何找到 (x, y, z)?我似乎在谷歌上找不到这个,所有的结果都充满了其他不相关的东西。谢谢!
问问题
8292 次
2 回答
24
有几种方法可以将 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)
}
于 2012-06-05T20:18:41.513 回答
1
如果坐标没有上限,可以从 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];
}
于 2012-06-06T01:27:29.830 回答