如何在3D网格中线性迭代?

时间:2018-03-09 07:05:16

标签: algorithm math optimization graphics

假设我们有一个跨越一些3D空间的3D网格。此网格由多维数据集构成,多维数据集不需要具有整数长度,它们可以具有任何可能的浮点长度。

我们的目标是,给定一个点和一个方向,在路径中线性地检查每个立方体一次并且恰好一次。

因此,如果这只是一个常规的3D阵列,并且方向是在X方向上说,从位置(1,2,0)开始算法将是:

for(i in number of cubes)
{
     grid[1+i][2][0]
}

但当然,原点和方向是任意的浮点数,因此它不像迭代3D数组的一维那么容易。并且立方体的边长也是任意浮动的事实使得它也稍微更硬。

2 个答案:

答案 0 :(得分:1)

假设您的立方体边长为s = (sx, sy, sz),光线方向为d = (dx, dy, dz),起点为p = (px, py, pz)。然后,您想要遍历的光线是r(t) = p + t * d,其中t是任意正数。

让我们专注于一个维度。如果您当前位于多维数据集的下边界,则需要在光线上为了到达多维数据集的上边界而执行的步长dt为:dt = s / d。我们可以计算三个维度中每个维度的步长,即dt也是一个3D矢量。

现在,我们的想法如下:找到光线起点所在的单元格,找到参数值t,其中每个维度出现与网格的第一个交点。然后,您可以逐步查找每个维度从一个多维数据集切换到下一个多维数据集的参数值。按相应的t值对更改进行排序,然后迭代。

更多细节:

cell = floor(p - gridLowerBound) / s   <-- the / is component-wise division

我只会介绍方向为正的情况。如果你走向负面方向会有一些小的变化,但我相信你可以做到这些。

查找每个维度的第一个交叉点(nextIntersection是一个3D矢量):

nextIntersection = ((cell + (1, 1, 1)) * s - p) / d

并计算步长:

dt = s / d

现在,只需迭代:

if(nextIntersection.x < nextIntersection.y && nextIntersection.x < nextIntersection.z)
    cell.x++
    nextIntersection.x += dt.x
else if(nextIntersection.y < nextIntersection.z)
    cell.y++
    nextIntersection.y += dt.y
else
    cell.z++
    nextIntersection.z += dt.z
end if
if cell is outside of grid
    terminate

我省略了同时更改两个或三个单元格的情况。以上代码一次只能更改一个。如果您需要,请随意调整代码。

答案 1 :(得分:1)

如果您正在使用浮点数,那么您可以在指定的方向上生成线的等式。由t参数化。因为在任意两个浮点数之间存在有限数量的点,您可以简单地检查这些点中的每个点,因为它们很容易导致您具有其组件应该位于的点(x,y,z),相应的区间定义了立方体。

如果考虑密集的区间,问题就会变得更加困难。

这里的关键是浮点数,这是一个离散的搜索问题。任意两点之间的直线方程是一组离散点这一事实意味着您只需要将它们全部检查到立方体间隔。更好的是有一个对称性(一条线),允许你用算术表达式轻松枚举每个点,一个接一个地进行检查。

也许首先考虑整数情况,因为它是相同的,但在确定离散点时稍微简单,因为它是Z_2 ^ 8中的一条线?