DDA与Bresenham画线算法

一、数字微分分析仪(digital differential analyzer, DDA)方法是一种线段扫描转换算法。在一个坐标轴上以单位间隔对线段取样,从而确定另一个坐标轴上最靠近线路径的对应整数值。主要是根据直线公式y = kx + b来推导出来的,其关键之处在于如何设定单位步进,即一个方向的步进为单位步进,另一个方向的步进必然是小于1。

算法过程:

输入线段两个端点的像素位置,端点位置间的水平和垂直差赋给参数dx和dy。绝对值大的参数确定steps的值。从像素位置(xBegin,yBegin)开始,确定沿线段生成下一个像素位置的每一步所需的偏移量,并循环上述过程setps次。假如dx的绝对值大于dy的绝对值,且xBegin小于xEnd,那么x和y方向的增量值分别为1和m。假如x方向的变化较大,但xBegin大于xEnd,那么就采用减量-1和-m来生成线段上的每个点。在其他情况下,y方向使用单位增量(或减量),x方向使用1/m的增量(或减量)。

 1 inline int Round(const float a) { return static_cast<int>(a + 0.5); }
 2 
 3 void LineDDA(int xBegin, int yBegin, int xEnd, int yEnd)
 4 {
 5     int dx = xEnd - xBegin;
 6     int dy = yEnd - yBegin;
 7     int steps, k;
 8 
 9     float xIncrement, yIncrement;
10     float x = static_cast<int>(xBegin);
11     float y = static_cast<int>(yBegin);
12 
13     if (fabs(dx) > fabs(dy)) {
14         steps = fabs(dx);
15     }
16     else {
17         steps = fabs(dy);
18     }
19 
20     xIncrement = static_cast<float>(dx) / static_cast<float>(steps);
21     yIncrement = static_cast<float>(dy) / static_cast<float>(steps);
22 
23     glBegin(GL_POINTS);
24 
25     for (k = 0; k < steps; ++k) {
26         x += xIncrement;
27         y += yIncrement;
28         glVertex2i(round(x), round(y));
29     }
30     glEnd();
31 }

 

二、Bresenham画线算法是一种精确而有效的光栅线生成算法,该算法仅仅使用了增量整数计算。

 

  

在取样位置,用来标识两个像素与数学上线路径的垂直偏移。在像素列位置处的直线上的坐标可计算为

   

那么

   

     

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

   

   

相减可得到

   

       

算法过程:

时的Bresenham画线算法:

1.输入线段的两个端点,并将左端点存储在(xBegin, yBegin)中;

2.将(xBegin, yBegin)装入帧缓存,画出第一个点;

3.计算常量,并得到决策参数的第一个值:

   

4.从开始,在沿线路径的每个处,进行下列检测:

如果,下一个要绘制的点是,并且

   

否则,下一个要绘制的点是,并且

   

5.重读步骤4,共;

 1 void LineBresenham(int xBegin, int yBegin, int xEnd, int yEnd)
 2 {
 3     int dx = fabs(xEnd - xBegin);
 4     int dy = fabs(yEnd - yBegin);
 5 
 6 
 7     int p = 2 * dy - dx;
 8     int two_dy = 2 * dy;
 9     int two_dy_minus_dx = 2 * (dy - dx);
10     int x, y;
11     int yName;
12 
13     if (xBegin > xEnd) {
14         yName = yBegin - yEnd;
15         x = xEnd;
16         y = yEnd;
17         xEnd = xBegin;
18     }
19     else {
20         yName = yEnd - yBegin;
21         x = xBegin;
22         y = yBegin;
23     }
24     while (x <= xEnd) {
25         glBegin(GL_POINTS);
26         glVertex2i(x, y);
27         glEnd();
28         
29         if (dx == 0 && y < yEnd) {
30             y++;
31             continue;
32         }
33         if (p < 0) {
34             x++;
35             p += two_dy;
36         }
37         else if (yName > 0) {
38             y++;
39             x++;
40             p += two_dy_minus_dx;
41         }
42         else if (yName < 0) {
43             y--;
44             x++;
45             p += two_dy_minus_dx;
46         }
47     }
48 }

 

posted @ 2016-05-24 14:59  clairvoyant  阅读(8257)  评论(0编辑  收藏  举报