中点画线算法

一、原理

已知直线的一般式方程:

F(x,y)=0F(x,y)=0F(x,y)=0, 即Ax+By+C=0Ax+By+C=0Ax+By+C=0

其中:

  • A=−(Δy)A=-(\Delta y)A=(Δy)
  • B=(Δx)B=(\Delta x)B=(Δx)
  • C=−B(Δx)C=-B(\Delta x)C=B(Δx)

如图:

代入m,当xm,ymx_m,y_mxm,ym取不同值时,函数F(xm,ym)F(x_m,y_m)F(xm,ym)的取值可以分三种情况,

  • F(xm,ym)=0F(x_m,y_m)=0F(xm,ym)=0,m点在直线上
  • F(xm,ym)<0F(x_m,y_m)<0F(xm,ym)<0,m点在直线下方
  • F(xm,ym)>0F(x_m,y_m)>0F(xm,ym)>0,m点在直线上方

二、推导

  1. 0≤∣k∣≤10\le |k|\le 10k1来讨论:

    如图:

    可以看出每次在x方向上加1,y方向上加1或不变需要判断。

  2. 通过仔细观察,发现:

    • 当M在Q的下方时,则PuP_uPu 离直线近,应为下一个象素点;

    • 当M在Q的上方,应取PdP_dPd 为下一点。

  3. 利用中点画线的基本原理

    将M带入代入理想直线方程,可得
    F(xm,ym)=Axm+Bym+C F(x_m,y_m)=Ax_m+By_m+C F(xm,ym)=Axm+Bym+C
    di=F(xm,ym)d_i=F(x_m,y_m)di=F(xm,ym)

    则有:di=F(xi+1,yi+0.5)=A(xi+1)+B(yi+0.5)+Cd_i=F(x_i+1,y_i+0.5)=A(x_i+1)+B(y_i+0.5)+Cdi=F(xi+1,yi+0.5)=A(xi+1)+B(yi+0.5)+C

    有三种情况:

    • 当d = 0 时: M在直线上,选pdp_dpdpup_upu均可;
    • 当d > 0 时: M在Q上方,应取pdp_dpd
    • 当d < 0 时: M在Q下方,应取pup_upu

    d的值决定了y的值:

    di=A(xi+1)+B(yi+0.5)+Cd_i=A(x_i+1)+B(y_i+0.5)+Cdi=A(xi+1)+B(yi+0.5)+C

yi+1={yi+1,(di<0)yi,(di≥0) y_{i+1}=\begin{cases} y_i+1, & (d_i<0)\\ y_i, & (d_i\ge 0) \end{cases}yi+1={yi+1,yi,(di<0)(di0)

三、优化

  1. 分析计算量

    为了求出d值,需要两个乘法,四个加法,且有浮点数运算。

  2. 提高运算效率

    因为d是x,y的线性函数,采用增量计算是可行的。

    di+1=di+增量d_{i+1}=d_i + 增量di+1=di+

  3. 计算增量

    • 计算d0d_0d0

      d0=F(xM0,yM0)d_0=F(x_{M_0},y_{M_0})d0=F(xM0,yM0)

      =F(xi,yi+0.5)= F(x_i,y_i+0.5)=F(xi,yi+0.5)

      =A(xi+1)+B(yi+0.5)+C= A(x_i+1)+B(y_i+0.5)+C=A(xi+1)+B(yi+0.5)+C

    • 计算d1d_1d1

      如图:

      d1=F(xM1,yM1)d_1=F(x_{M_1},y_{M_1})d1=F(xM1,yM1)

      =F(xi+2,yi+1.5)= F(x_i+2,y_i+1.5)=F(xi+2,yi+1.5)

      =A(xi+2)+B(yi+1.5)+C=A(x_i+2)+B(y_i+1.5)+C=A(xi+2)+B(yi+1.5)+C

      =A(xi+1)+B(yi+0.5)+C+A+B=A(x_i+1)+B(y_i+0.5)+C+A+B=A(xi+1)+B(yi+0.5)+C+A+B

      =d0+A+B=d_0+A+B=d0+A+B

    • 计算d2d_2d2

      如图:

      d2=F(xM2,yM2)d_2=F(x_{M_2},y_{M_2})d2=F(xM2,yM2)

      =F(xi+2,yi+0.5)= F(x_i+2,y_i+0.5)=F(xi+2,yi+0.5)

      =A(xi+2)+B(yi+0.5)+C=A(x_i+2)+B(y_i+0.5)+C=A(xi+2)+B(yi+0.5)+C

      =A(xi+1)+B(yi+0.5)+C+A=A(x_i+1)+B(y_i+0.5)+C+A=A(xi+1)+B(yi+0.5)+C+A

      =d0+A=d_0+A=d0+A

    • 计算d的初始值d0d_0d0

      因为直线的第一个像素P0(x0,y0)P_0(x_0,y_0)P0(x0,y0)在直线上,即A(x0)+B(y0)+C=0A(x_0)+B(y_0)+C=0A(x0)+B(y0)+C=0,因此相应的d的初始值计算如下:

      d0=F(x0,y0+0.5)d_0=F(x_0,y_0+0.5)d0=F(x0,y0+0.5)

      =A(x0+1)+B(y0+0.5)+C= A(x_0+1)+B(y_0+0.5)+C=A(x0+1)+B(y0+0.5)+C

      =A(x0)+B(y0)+C+A+0.5B=A(x_0)+B(y_0)+C+A+0.5B=A(x0)+B(y0)+C+A+0.5B

      =A+0.5B=A+0.5B=A+0.5B

    • 综上可得:
      d0=A+0.5Bd_0=A+0.5Bd0=A+0.5B

di+1={di+A+B,(di<0)di+A,(di≥0) d_{i+1}=\begin{cases} d_i+A+B, & (d_i<0)\\ d_i+A, & (d_i\ge 0) \end{cases}di+1={di+A+B,di+A,(di<0)(di0)

至此,中点算法至少可以和DDA算法一样好。

  1. 摆脱浮点运算

    用2d代替d来摆脱浮点运算,写出仅包含整数运算的算法。这样,中点生成直线的算法提高到整数加法,优于DDA算法。

    即:

di+1={di+2(A+B),(di<0)di+2A,(di≥0) d_{i+1}=\begin{cases} d_i+2(A+B), & (d_i<0)\\ d_i+2A, & (d_i\ge 0) \end{cases}di+1={di+2(A+B),di+2A,(di<0)(di0)
d0=2A+Bd_0=2A+Bd0=2A+B

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐