📜  Bresenham的3-D线图绘制算法

📅  最后修改于: 2021-04-29 07:45:27             🧑  作者: Mango

给定两个3-D坐标,我们需要在连接它们的线上找到点。所有点都有整数坐标。

例子:

输入:(-1,1,1),(5,3,-1)输出:(-1,1,1),(0,1,1),(1,2,0),(2,2 ,0),(3,2,0),(4,3,-1),(5,3,-1) 从XY平面的(-1、1、1)到(5、3,-1)的3D线视图YZ平面从(-1,1,1)到(5,3,-1)的3D线视图ZX平面从(-1,1,1)到(5,3,-1)的3D线视图从抽象角度看从(-1,1,1)到(5,3,-1)的3D线输入:(-7,0,-3),(2,-5,-1)输出:(-7,0,-3),(-6,-1,-3),(-5,-1 ,-3),(-4,-2,-2),(-3,-2,-2),(-2,-3,-2),(-1,-3,-2),( 0,-4,-1),(1,-4,-1),(2,-5,-1)

Bresenham的算法非常有效,因为它避免了浮点算术运算。与二维线图一样,我们使用一个变量来存储坡度误差,即从实际几何线绘制的线的坡度误差。一旦该斜率误差超过允许值,我们将修改数字以消除误差。

要绘制的线的驱动轴是线沿其行进最远的那条,即,轴坐标之差最大。因此,坐标值沿着驱动轴线性增加1,并且使用斜率误差变量来确定另一个轴的坐标值的变化。

对于2D线,我们使用一个斜率误差变量,但对于3D线,我们需要两个( py, pz )的每个非驱动轴。如果当前点是P_{k} (x,y,z)并且驱动轴为正X轴,则下一个点P_{k+1}可能

  • (x + 1,y,z)
  • (x + 1,y + 1,z)
  • (x + 1,y,z + 1)
  • (x + 1,y + 1,z + 1)

3D线上下一个点的候选点

斜率误差变量的值根据以下公式确定:
 py_{k+1} = py_{k} + 2dy - 2dx(y_{k+1} - y_{k})\\ pz_{k+1} = pz_{k} + 2dz - 2dx(z_{k+1} - z_{k})

斜率误差变量的初始值由以下方程式给出:
 py_{0} = 2dy - dx\\ pz_{0} = 2dz - dx
这里dx, dy, dz表示两个端点沿X,Y,Z轴的坐标差。

算法:-

  1. 输入两个端点并将初始点存储为(x_{0}, y_{0}, z_{0})
  2. 阴谋(x_{0}, y_{0}, z_{0})
  3. 计算常数dx, dy, dz并通过比较确定驱动轴
    的绝对值dx, dy, dz
    如果绝对dx )为最大值,则X轴为驱动轴
    如果绝对dy )为最大值,则Y轴为驱动轴
    如果绝对dz )为最大值,则Z轴为驱动轴
  4. 假设X轴是驱动轴,那么
     py_{0} = 2dy - dx\\ pz_{0} = 2dz - dx
  5. 在每一个x_{k}沿着线,从k = 0开始,检查以下条件
    并确定下一点:
    • 如果py_{k} < 0pz_{k} < 0 , 然后
      阴谋(x_{k}+1, y_{k}, z_{k})
      py_{k+1}=py_{k}+2dy, pz_{k+1}=pz_{k}+2dz
    • 否则py_{k} > 0pz_{k} < 0 , 然后
      阴谋(x_{k}+1, y_{k}+1, z_{k})
      py_{k+1}=py_{k}+2dy-2dx, pz_{k+1}=pz_{k}+2dz
    • 否则py_{k}  0 , 然后
      阴谋(x_{k}+1, y_{k}, z_{k}+1)
      py_{k+1}=py_{k}+2dy, pz_{k+1}=pz_{k}+2dz-2dx
    • 否则
      阴谋(x_{k}+1, y_{k}+1, z_{k}+1)
      py_{k+1}=py_{k}+2dy-2dx, pz_{k+1}=pz_{k}+2dz-2dx >
  6. 重复步骤5 dx-1
Python3
# Python3 code for generating points on a 3-D line 
# using Bresenham's Algorithm
  
def Bresenham3D(x1, y1, z1, x2, y2, z2):
    ListOfPoints = []
    ListOfPoints.append((x1, y1, z1))
    dx = abs(x2 - x1)
    dy = abs(y2 - y1)
    dz = abs(z2 - z1)
    if (x2 > x1):
        xs = 1
    else:
        xs = -1
    if (y2 > y1):
        ys = 1
    else:
        ys = -1
    if (z2 > z1):
        zs = 1
    else:
        zs = -1
  
    # Driving axis is X-axis"
    if (dx >= dy and dx >= dz):        
        p1 = 2 * dy - dx
        p2 = 2 * dz - dx
        while (x1 != x2):
            x1 += xs
            if (p1 >= 0):
                y1 += ys
                p1 -= 2 * dx
            if (p2 >= 0):
                z1 += zs
                p2 -= 2 * dx
            p1 += 2 * dy
            p2 += 2 * dz
            ListOfPoints.append((x1, y1, z1))
  
    # Driving axis is Y-axis"
    elif (dy >= dx and dy >= dz):       
        p1 = 2 * dx - dy
        p2 = 2 * dz - dy
        while (y1 != y2):
            y1 += ys
            if (p1 >= 0):
                x1 += xs
                p1 -= 2 * dy
            if (p2 >= 0):
                z1 += zs
                p2 -= 2 * dy
            p1 += 2 * dx
            p2 += 2 * dz
            ListOfPoints.append((x1, y1, z1))
  
    # Driving axis is Z-axis"
    else:        
        p1 = 2 * dy - dz
        p2 = 2 * dx - dz
        while (z1 != z2):
            z1 += zs
            if (p1 >= 0):
                y1 += ys
                p1 -= 2 * dz
            if (p2 >= 0):
                x1 += xs
                p2 -= 2 * dz
            p1 += 2 * dy
            p2 += 2 * dx
            ListOfPoints.append((x1, y1, z1))
    return ListOfPoints
  
  
def main():
    (x1, y1, z1) = (-1, 1, 1)
    (x2, y2, z2) = (5, 3, -1)
    ListOfPoints = Bresenham3D(x1, y1, z1, x2, y2, z2)
    print(ListOfPoints)
  
main()


输出:
[(-1, 1, 1), (0, 1, 1), (1, 2, 0), (2, 2, 0), (3, 2, 0), (4, 3, -1), (5, 3, -1)]