得鹿梦鱼 得鹿梦鱼

直线的生成算法 BresenHam

线条绘制算法是一种用于在离散视觉媒体上显示线段的方法

设直线的从起点x1,y1x_1, y_1到终点x2,y2x_2,y_2,直线可以表示方程y=kx+by = kx + b

假定直线的点是位于第一象限,并且斜率是大于 0 小于 1 的,这这种情况下,当直线光栅化时,xx每次都是自增 1,而相应的yy的增量是小于 1 的,为了光栅化,当xix_i增加 1 时,y 只能是yiy_i或者yi+1y_i + 1两个位置之一

yiy_i或者yi+1y_i + 1的位置选择的原则是有精确值yyyiy_iyi+1y_i + 1的距离d1d_1d2d_2的大小而定的,计算公式如下

y=kxi+1+bd1=yyid2=yi+1yy = kx_i + 1 + b \\d_1 = y - y_i \\d_2 = y_i + 1 - y

如果d1d2>0d_1 - d_2 > 0,则选择yi+1yi + 1, 否则选择yiy_i,因此算法的关键在与简便的求出d1d2d_1 - d_2的符号,
d1d2=2y2yi1=2mxi+12yi+2b11d_1 - d_2 = 2y - 2y_i -1 = 2mx_i + 1 - 2y_i + 2b -1 \tag{1}
m=y2y1x2x12m = \frac{y_2 - y_1}{x_2 - x_1} \tag{2}
Δx=x2x1\Delta x =x_2 - x_1, Δy=y2y1\Delta y =y_2 - y_1
将2式带入1式
Δxd1d2=2xiΔy2yiΔx+2Δy+Δx2b13\Delta xd_1 - d_2 = 2x_i\Delta y - 2y_i\Delta x + 2\Delta y + \Delta x2b-1 \tag{3}

由于已经假定直线的 2 个端点都是在第一象限,并且斜率是大于 0 小于 1 的,所以Δx\Delta x大于 0,因此Δxd1d2\Delta xd_1 - d_2依然可以用作符号判断

Pi=Δxd1d2P_i = \Delta xd_1 - d_2
则 3 式表示为
Pi=2xiΔy2yiΔx+2Δy+Δx2b14P_i = 2x_i\Delta y - 2y_i\Delta x + 2\Delta y + \Delta x2b-1 \tag{4}

Pi+1=2xi+1Δy2yi+1Δx+2Δy+Δx2b1P_{i+1} = 2x_{i+1}\Delta y - 2y_{i+1}\Delta x + 2\Delta y + \Delta x2b-1
Pi+1Pi=2Δy2Δxyi+1yi5P_{i+1} - P_i = 2\Delta y - 2\Delta xy_{i + 1} - y_i \tag{5}

综合所述,针对上述条件下的直线 BresenHam 算法思想如下

  1. 绘制第一个点 计算Δx,Δy,P0=2Δy1\Delta x, \Delta y, P_0 = 2\Delta y - 1
  2. 求下个位置xi+1=xi+1x_{i+1} = x_i + 1Pi>0P_i > 0则取yi+1y_{i+1}否则yiy_i
  3. 绘制
  4. 求下一个误差,若Pi>0P_i > 0则取Pi+1=Pi+2Δy2ΔxP_i+ 1 = P_i + 2\Delta y - 2 \Delta x否则Pi+1=Pi+2ΔyP_i+ 1 = P_i + 2\Delta y
  5. 判断是否需要终止,否则执行2、3、4

当斜率的绝对值大于1时,将x和y,dx,dy进行对换

代码实现

请参考直线的生成算法_BresenHam