计算机图形学(二)输出图元_3_画线算法_3_Bresenham画线算法

Bresenham画线算法

    

本来在word中是有右下数的,一编辑在csdn中编辑就没有了。

                                    

     Bresenham画线算法是由Bresenham提出的一种精确而有效的光栅线生成算法。该算法只使用增量整数计算。另外Bresenham算法还可用于显示圆和其它曲线。图3.8和图3.9给出了绘制线段的屏幕局部。

垂直轴表示扫描线位置,水平轴标识像素列。

在这个样例中,我们以单位x间隔取样,而且须要确定每次取样时两个可能的像素位置中的哪一个更接近于线路径。从图3.8中的左端点開始。须要确定下一个取样像素位置是(11, 1l)还是(1 1, 12)。类似地,图3.9则给出了像素位置(50,50)为左端点的具有负斜率的线段。此时。须要确定下一个像素位置是((51, 50)还是((51, 49)。为了解决这些问题,Bresenham算法将对整型參数的符号进行检測,整型參数的值正比于两像素与实际线段之间的偏移。

    为了说明Bresenham方法。首先考虑斜率小于1的直线的扫描转换过程。沿线路径的像素位置由以单位x间隔的取样来确定。从给定线段的左端点(xo,yo)開始,逐步处理每一个后继列(x位置),并在其扫描线y值最接近线段的像素上绘出一点:图3.10显示了这个过程的第k步。假如已经决定要显示的像素在(xk ,yk)。那么下一步须要确定在列Xk+1 = Xk+1上绘制哪个像素。是在位置(xk+1 , yk) ,还是位置(xk+1,yk+1) 



    在取样位置xk+1,我们使用dlower和dupper,来标识两个像素与数学上线路径的垂直偏移(參见图3.11),在像素列位置xk +1处的直线上的y坐标可计算为

那么


要确定两像素中哪一个更接近线路径,须要測试这两个像素偏移的差:

通过又一次安排等式(3.13)可获得画线算法第k步的决策參数pk,从而仅使用整数进行计算。
设△y和△x分别为两端点的垂直和水平偏移量。令m = △y/△x,将决策參数定义为

pk的符号与dlower - dupper。的符号同样(由于样例中△x >0),參数c是一常量,其值为2△y + △x (2b-1),它与像素位置无关,且会在循环计算pk时被消除。假如yk处的像素比yk+ 1的像素更接近于线段(即dlower < dupper),那么參数pk是负的。此时,绘制以下的像素;反之,绘制上面的像素。

    直线上的坐标会沿x或y方向的单位步长而变化。因此,能够利用递增整数运算得到后继的决策參数值。

在k+1步。决策參数能够从等式(3.14)计算得出:

将上述方程减去等式(3.14),能够得到

可是xk+1 = xk+1,因而得到

当中,yk+1-yk取0或1,取决于參数pk的符号。
    决策參数的递归运算在线段的坐标端点開始的每一个整数x位置进行,起始像素位置(xo,yo)的第一个參数po通过等式(3.14)及m = △y/△x计算得出 

    我们能够将正斜率小于1的线段的Bresenham画线算法概括为下面步骤。常遗2△y和2△y-2△x对每条进行扫描转换的直线仅仅计算一次,因此该系统仅进行这两个常量之间的整数加减法。
:
|m| < 1时的Bresenham画线算法
1.输人线段的两个端点。并将左端点存储在(xo,yo)中;
2.将(xo,yo)装入帧缓存,画出第一个点;

3.计算常量△x 、△y 、2△y和2△y-2△x,并得到决策參数的第一个值:


4.从k=0開始,在沿线路径的每一个xk处,进行下列检測:

假设pk<0,下一个要绘制的点是(xk+1,yk+1)。而且


5.反复步骤4, xk-1

例3.1  Bresenham画线算法
为了演示上述算法,我们绘制这样一条线段:端点为(20, 10)和(30,18)该线段的斜率为0.8且

那么初始决策參数数的值为


计算兴许决策參数的增量为



图3.12中给出了沿这条线路径生成的像素点。



       下列程序中给出了斜率为0 < m < 1.0的Bresenham画线算法的实现。

首先将线段的端点像素位置输入程序,然后从左端点到右端点绘制像素。

#include<stdlib.h>
#include<math.h>

/*Bresenham line-drawing procedure for |m|<1.0. */
void lineBres(int x0,int y0,int xEnd,int yEnd)
{
    int dx = fabs(xEnd - x0),dy = fabs(yEnd - y0);
    int p = 2*dy - dx;
    int twoDy = 2*dy, twoDyMinusDx = 2*(dy - dx);
    int x,y;

/*Determine which endpoint to use as start position.*/
if(x0 > xEnd){
    x = xEnd;
    y = yEnd;
    xEnd = x0;
}
else{
    x = x0;
    y = y0;
}
setPixel(x,y);
while(x<xEnd){
  x++;
if(p < 0)
  p += twoDy;
else{
  y++;
  p += twoDyMinusDx;
}
  setPixel(x,y);
}

}

        通过考虑xy平面各种八分和四分区域间的对称性。Bresenham算法对随意斜率的线段具有通用性。对于斜率为正值且大于1.0的线段,仅仅要交换x和y方向的规则。即沿y方向以单位步长移动并计算最接近线路径的连续x值。当然,也能够改变程序,使之能从不论什么端点開始绘制像素,假如正斜率线段的初始位置是右端点,那么在从右至左的步进中,x和y都将递减。

为了确定不管从不论什么端点開始都能绘制同样的像素。当候选像素相对于线段的两个垂直偏移相等时dlower  =  dupper,我们总是选择当中较高(或较低)的像素。对于绘制负斜率的线段,除非一个坐标递减而还有一个递增,否则程序是类似的。最后,能够分别处理下列特殊情况:水平线(△y = 0)、垂直线(△x = 0)和对角线|△x| = |△y|,它们都可直接装入帧缓存而无需进行画线算法处理。

posted @ 2017-08-06 15:24  jzdwajue  阅读(645)  评论(0编辑  收藏  举报