目录

一.DDA算法和中点画线算法的回顾

二.Bresenham画线算法


一.DDA算法和中点画线算法的回顾

1.DDA算法(Digtal Differential Analyzer)

假设两个端点坐标值是

Bresenham画线算法原理 bresenham画线算法例题_四舍五入


Bresenham画线算法原理 bresenham画线算法例题_四舍五入_02

,规定

Bresenham画线算法原理 bresenham画线算法例题_学习_03

,且

Bresenham画线算法原理 bresenham画线算法例题_Bresenham画线算法原理_04

由于对直线方程求微分,有

Bresenham画线算法原理 bresenham画线算法例题_学习_05

整理(1)可得

Bresenham画线算法原理 bresenham画线算法例题_学习_06

如果我们把x的步长变得无穷小,就可以近似地估计出下一个点的坐标,从而准确地画出一条直线。但是由于设备的精度是有限的,我们需要将x或者y的点的移动变成单位步长,也就是一次移动1,算法在最大位移方向上每次走一步。也就是说,如果直线当前

Bresenham画线算法原理 bresenham画线算法例题_算法_07

如图中所示(m<1),此时的最大位移方向显然是x,x每次增加一个单位,y增加m。下一个坐标应该如

Bresenham画线算法原理 bresenham画线算法例题_算法_08

,线段上实际点的坐标应当是

Bresenham画线算法原理 bresenham画线算法例题_算法_09

,在这里应当四舍五入,即int(

Bresenham画线算法原理 bresenham画线算法例题_学习_10

+0.5)来选取比较接近的点。类似地,如果m>1,最大位移方向显然是y方向,此时x的增量应当是1/m。

Bresenham画线算法原理 bresenham画线算法例题_学习_11

 综上所述,DDA画线算法如下:

void DDALine(int x1,int y1,int x2,int y2){
    double dx,dy,e,x,y;
    dx = x2-x1;
    dy = y2-y1;
    e = (fabs(dx)>fabs(dy)?fabs(dx):fabs(dy);
    dx/=e;
    dy/=e;
    x = x1;
    y = y1;
    for(int i=0;i<=e;i++){
        SetPixel((int)(x+0.5),(int)(y+0.5));
        x+=dx;
        y+=dy;
    }
}

 2.中点画线算法

假定:直线的斜率在0~1之间

实际上,对于直线扫描算法来说,已知了当前

Bresenham画线算法原理 bresenham画线算法例题_算法_07

,讨论下一个点的坐标,就相当于我们做一个选择题,选右上的点呢还是右边的点呢?(你妈和老婆掉水里了你先救谁?这当然要分情况讨论了。比如我妈会游泳,可以连着我老婆一起拉上来。)

所以说选点的情形是这样的:

Bresenham画线算法原理 bresenham画线算法例题_Bresenham画线算法原理_13

 很显然,直线在

Bresenham画线算法原理 bresenham画线算法例题_学习_14

处有直线的坐标Q(x,y),我们只需要判断一下这个点(x,y)和中点的位置关系,它要是在中点上面,选上面的点,反之选下面的点。这就是中点画线法的基本思想,下面给出数学角度的讨论。假设直线的起点和中点分别是

Bresenham画线算法原理 bresenham画线算法例题_算法_15


Bresenham画线算法原理 bresenham画线算法例题_四舍五入_16

,直线满足

F(x,y) = ax+by+c=0,其中a = y0-y1,b = x1-x0,c = x0y1-x1y0

从而对于直线上的点,F(x,y)=0,直线下方的点F(x,y)<0,直线上方的点F(x,y)>0

为了判断M和直线的位置关系,可以将M的坐标带入直线方程中,得到

Bresenham画线算法原理 bresenham画线算法例题_学习_17

根据d的值,当d<0时,M在Q的下方,应当取上面的点,如图所示:

Bresenham画线算法原理 bresenham画线算法例题_Bresenham画线算法原理_18

进一步讨论,可以对每一个像素都计算判别式d得到下一个像素的位置,在d<0时,考虑下一个点的位置,此时

Bresenham画线算法原理 bresenham画线算法例题_四舍五入_19

的坐标向右移动2个单位,而中点的位置也就是

Bresenham画线算法原理 bresenham画线算法例题_初值_20

,如图中所示

Bresenham画线算法原理 bresenham画线算法例题_学习_21

  从而我们得到判别式

Bresenham画线算法原理 bresenham画线算法例题_算法_22

类似地,在d>=0时,应当取得下方的点,即正右的点,它y的坐标相同和左侧点相同,将M点坐标带入可得到判别式d的值:

Bresenham画线算法原理 bresenham画线算法例题_初值_23

Bresenham画线算法原理 bresenham画线算法例题_Bresenham画线算法原理_24

 初值的计算,此时第一个像素应当取左侧端点(x0,y0),则相应地我们可以得到中点,带入判别式就可以得到初值为:

Bresenham画线算法原理 bresenham画线算法例题_算法_25

综上所述,实际上中点画线算法就是根据中点相对直线的位置进行选点,我们选择了直线的隐式方程得到了判别式d,然后在当前点得到了下一个点的像素选择之后进行了递推,分成了d>=0和d<0两种不同的情况,得到了误差项的递推公式。在下面代码中,为了保证整数运算,将d用2d来代替。

void MidpointLine(int x0,int y0,int x1,int y1){
	int a,b,delta1,delta2,d,x,y;
	a = y0-y1;
	b = x1-x0;
	d = 2*a+b;//设定初值,乘了个2
	delta1 = 2*a;//方便整数运算 
	delta2 = 2*(a+b);
	x = x0;
	y = y0;
	SetPixel(x,y);
	while(x<x1){
		if(d<0){//d<0时,选择右上方的点,增量是a+b,这里乘2 
			x++;
			y++;
			d+=delta2
		}
		else{//右侧点,增量2a 
			x++;
			d+=delta1;
		}
		SetPixel(x,y) //一直到最右侧的端点再结束描像素 
	}
}

二.Bresenham画线算法

1967年,一个叫J.Bresenham的IBM秃头程序员提出了这个算法,这个算法只用整数运算而没有四舍五入,我们还是先看看这个秃头程序员到底想干啥。先看下面这个图:

Bresenham画线算法原理 bresenham画线算法例题_学习_26

 我们现在依然是做选择题,注意那个黄色点它不再是中点,而是直线此刻的与坐标线的交点了,我们不妨设它的值是yi,那么依然是这个直线,我们可以得到d1和d2的值。

Bresenham画线算法原理 bresenham画线算法例题_Bresenham画线算法原理_27

Bresenham画线算法原理 bresenham画线算法例题_算法_28

Bresenham画线算法原理 bresenham画线算法例题_Bresenham画线算法原理_29

可以通过这个差值来衡量接近程度,如果插值是正的,显然d2更小,我们选择上方点,反之取下方点,在这里又引入了新的判别量p,来减少m这个分式带来的计算不便。

Bresenham画线算法原理 bresenham画线算法例题_学习_30

 

Bresenham画线算法原理 bresenham画线算法例题_初值_31

 这就是斜率在0~1之间的Bresenham算法。

你问我为什么不打了?

累了886.