【问题标题】:Traverse a 2.5D grid遍历 2.5D 网格
【发布时间】:2012-07-27 20:00:39
【问题描述】:

我试图弄清楚如何以有效的方式遍历 2.5D 网格。网格本身是 2D 的,但网格中的每个单元格都有一个浮动的最小/最大高度。要遍历的线由两个 3D 浮点坐标定义。如果进入/退出网格单元格之间的 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;
        }
    }
}

【问题讨论】:

    标签: c++ algorithm math


    【解决方案1】:

    Bresenham Line Algorithm 的 3D 扩展似乎可以工作。您将遍历 X 并独立跟踪线段的 Y 和 Z 分量的误差,以确定每个相应 X 值的 Y 和 Z 值。当 Z 中的累积误差达到某个临界水平时,您只需停止,这表明它超出了您的最小值/最大值。

    【讨论】:

    • 不幸的是,Bresenham 对于主轴的每一步仅在非主轴中找到一个单元格,因此它错过了与线相交的单元格。即在上图中,左起前四个相交的单元格是 (2,3)、(3,3)、(3,4)、(4,4)。由于 X 是主轴,Bresenham 将跳过单元格 (3,4)
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      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
      

      【讨论】:

        猜你喜欢
        • 2013-07-24
        • 2013-03-19
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 2011-02-26
        • 2013-05-27
        • 2017-02-09
        • 1970-01-01
        相关资源
        最近更新 更多