我正在试图找出如何以有效的方式遍历2.5D网格。网格本身是2D,但网格中的每个单元格都有一个浮动最小/最大高度。要遍历的线由两个3D浮点坐标定义。如果进入/退出网格单元格之间的z值范围与该单元格的最小/最大高度不重叠,我想停止遍历该行。
我目前正在使用2D DDA算法按顺序遍历网格单元(参见图片),但我不确定如何在达到每个网格单元时计算z值。如果我能做到这一点,我可以在进入/离开单元格时测试z值与单元格的最小/最大高度。
有没有办法修改这个算法,允许在输入每个网格单元时计算z?或者是否有更好的遍历算法可以让我这样做?
grid http://i45.tinypic.com/2ez7bk5.jpg
这是我正在使用的当前代码:
void Grid::TraceGrid(Point3<float>& const start, Point3<float>& const end, GridCallback callback )
{
// calculate and normalize the 2D direction vector
Point2<float> direction=end-start;
float length=direction.getLength( );
direction/=length;
// calculate delta using the grid resolution
Point2<float> delta(m_gridresolution/fabs(direction.x), m_gridresolution/fabs(direction.y));
// calculate the starting/ending points in the grid
Point2<int> startGrid((int)(start.x/m_gridresolution), (int)(start.y/m_gridresolution));
Point2<int> endGrid((int)(end.x/m_gridresolution), (int)(end.y/m_gridresolution));
Point2<int> currentGrid=startGrid;
// calculate the direction step in the grid based on the direction vector
Point2<int> step(direction.x>=0?1:-1, direction.y>=0?1:-1);
// calculate the distance to the next grid cell from the start
Point2<float> currentDistance(((step.x>0?start.x:start.x+1)*m_gridresolution-start.x)/direction.x, ((step.y>0?start.y:start.y+1)*m_gridresolution-start.y)/direction.y);
while(true)
{
// pass currentGrid to the callback
float z = 0.0f; // need to calculate z value somehow
bool bstop=callback(currentGrid, z);
// check if the callback wants to stop or the end grid cell was reached
if(bstop||currentGrid==endGrid) break;
// traverse to the next grid cell
if(currentDistance.x<currentDistance.y) {
currentDistance.x+=delta.x;
currentGrid.x+=step.x;
} else {
currentDistance.y+=delta.y;
currentGrid.y+=step.y;
}
}
}
答案 0 :(得分:0)
似乎Bresenham Line Algorithm的3D扩展可行。您将迭代X并独立跟踪线段的Y和Z分量的误差,以确定每个相应X值的Y和Z值。当Z中的累积误差达到某个临界水平时,您就会停止,这表明它超出了您的最小值/最大值
答案 1 :(得分:0)
对于每个细胞,您都知道自己来自哪个细胞。这意味着你知道你来自哪一方。在绿线和给定网格线的交点处计算z似乎微不足道。
答案 2 :(得分:0)
我想出了一个很好的方法。添加到函数的开头:
float fzoffset=end.z-start.z;
Point2<float> deltaZ(fzoffset/fabs(end.x-start.x), fzoffset/fabs(end.y-start.y));
Point2<float> currentOffset((step.x>0?start.x:start.x+1)*m_gridresolution-start.x, (step.y>0?start.y:start.y+1)*m_gridresolution-start.y);
在currentDistance.x / .y递增的循环内,添加:
currentOffset.x+=m_gridresolution; //When stepping in the x axis
currentOffset.y+=m_gridresolution; //When stepping in the y axis
然后在每一步计算z:
z=currentOffset.x*deltaZ.x+start.z; //When stepping in the x axis
z=currentOffset.y*deltaZ.y+start.z; //When stepping in the y axis