C++ 遍历2.5维网格

C++ 遍历2.5维网格,c++,algorithm,math,C++,Algorithm,Math,我正试图找出如何以有效的方式遍历2.5维网格。栅格本身是二维的,但栅格中的每个单元都有一个浮动最小/最大高度。要遍历的线由两个三维浮点坐标定义。如果进入/退出网格单元之间的z值范围与该单元的最小/最大高度不重叠,我希望停止遍历该线 我目前正在使用2D DDA算法按顺序遍历网格单元(见图),但我不确定在到达每个网格单元时如何计算z值。如果我能做到这一点,我就可以在进入/离开单元格时根据单元格的最小/最大高度测试z值 是否有办法修改此算法,以便在输入每个网格单元时计算z?还是有更好的遍历算法可以让我

我正试图找出如何以有效的方式遍历2.5维网格。栅格本身是二维的,但栅格中的每个单元都有一个浮动最小/最大高度。要遍历的线由两个三维浮点坐标定义。如果进入/退出网格单元之间的z值范围与该单元的最小/最大高度不重叠,我希望停止遍历该线

我目前正在使用2D DDA算法按顺序遍历网格单元(见图),但我不确定在到达每个网格单元时如何计算z值。如果我能做到这一点,我就可以在进入/离开单元格时根据单元格的最小/最大高度测试z值

是否有办法修改此算法,以便在输入每个网格单元时计算z?还是有更好的遍历算法可以让我这样做

以下是我正在使用的当前代码:

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;
        }
    }
}
void Grid::TraceGrid(点3&const start,点3&const end,GridCallback)
{
//计算并规格化二维方向向量
点2方向=结束-开始;
float length=direction.getLength();
方向/=长度;
//使用栅格分辨率计算增量
点2δ(m_网格分辨率/fabs(方向x),m_网格分辨率/fabs(方向y));
//计算网格中的起点/终点
点2 startGrid((int)(start.x/m_gridresolution),(int)(start.y/m_gridresolution));
点2 endGrid((int)(end.x/m_gridresolution),(int)(end.y/m_gridresolution));
点2 currentGrid=startGrid;
//基于方向向量计算栅格中的方向步长
点2阶跃(方向x>=0?1:-1,方向y>=0?1:-1);
//计算从起点到下一个栅格单元的距离
点2当前距离((步长x>0?起始点x:start.x+1)*m_gridresolution-start.x)/direction.x,((步长y>0?起始点y:start.y+1)*m_gridresolution-start.y)/direction.y);
while(true)
{
//将currentGrid传递给回调函数
float z=0.0f;//需要以某种方式计算z值
bool bstop=回调(currentGrid,z);
//检查回调是否要停止或是否已到达结束网格单元
如果(bstop | | currentGrid==endGrid)中断;
//遍历到下一个网格单元

如果(currentDistance.x它看起来像是对的3D扩展。您将在x上迭代,并独立跟踪线段Y和Z分量的误差,以确定每个对应x值的Y和Z值。当Z中的累积误差达到某个临界水平时,您将停止,这表明它超出了I计算最小值/最大值。

对于每个单元格,您知道您来自哪个单元格。这意味着您知道您来自哪一侧。在绿线和给定网格线的交点处计算z似乎很简单。

我想出了一个很好的方法。添加到函数的开头:

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);
然后在每一步计算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

不幸的是,对于主轴的每一步,Bresenham只能在非主轴中找到一个单元格,因此它忽略了与直线相交的单元格。即,在上图中,从左侧开始的前四个相交单元格是(2,3)、(3,3)、(3,4)、(4,4)。由于X是主轴,Bresenham将跳过单元格(3,4)
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