编程环境:codeblocks+EGE库
用到的函数:putpixel(int x1,int y1,int color) 用某种颜色打亮一个坐标点。
这俩种算法都是用来在计算机上画一条直线的,那么我们为什么不直接用直线方程分别带点再打亮呢,这是因为,计算机中每个坐标点都是整数,而直线是由一个个像素点组合而成的,那么,直接将坐标点再进行四舍五入整数化就好了啊,的确,这是一种方法,但计算机中进行浮点数的四舍五入会使运算效率变差,因此真正画直线时是用到上边这俩种方法的。
1、中点画线法
只考虑当直线的斜率|k|<1时的情况,假设现在有一条直线(x1,y1,x2,y2),那么第一个点一定是(x1,y1)无疑,下一个点的x坐标为x1+1,y坐标要么为y1要么为y1+。关键在于每次取下一个点时,是取前一个的y1呢,还是y1+1,这时一定是取直线上点最靠近的那个了,而判断取哪个点就用到了中点,我们将中点代入直线中 d=F(x1+1,y1+0.5)=a*(x1+1)+b*(y1+0.5)+c。
(1)如果直线d>=0,则取下边的点也就是(x1+1,y1)。 (2)如果直线d<0,则取上边的点也就是(x1+1,y1+1)。
它的实际过程就是这样每次根据前边的点判断下一个点在哪,然后进行打亮,但这样每次判断的时候都得代入直线方程计算太麻烦了,我们将这俩种情况分别代入直线方程中可以找出规律:
(1)当直线>=0时,经过化解得d1=d+a;
(2)当直线<0时,经过化解得d2=d+a+b;
(3)初始值d0=a+0.5b。
也就是说每次的增量要么为a,要么为a+b,那么这样判断的时候就简单多了,因为我们每次只是判断它的正负。所以给等式同时乘2,将其中浮点数0.5化为整数,这样硬件操作时无疑更快了。
代码:
1 #include <iostream>
2 #include <graphics.h>
3 using namespace std;
4 //中点画线法
5 void line1(int x1,int y1,int x2,int y2){
6
7 int x,y,d0,d1,d2,a,b;
8 y=y1;
9 a=y1-y2; //直线方程中的a的算法
10 b=x2-x1; //直线方程中的b的算法
11 d0=2*a+b; //增量初始值
12 d1=2*a; //当>=0时的增量
13 d2=2*(a+b); //当<0时的增量
14 for(x=x1;x<=x2;x++){
15 putpixel(x,y,GREEN); //打亮
16 if(d0<0){
17 y++;
18 d0+=d2;
19 }else{
20
21 d0+=d1;
22 }
23
24 }
25 }
26 //Bresenham画线算法
27 void line2(int x1,int y1,int x2,int y2){
28
29 int x,y,dx,dy,d;
30 y=y1;
31 dx=x2-x1;
32 dy=y2-y1;
33 d=2*dy-dx; //增量d的初始值
34 for(x=x1;x<=x2;x++){
35 putpixel(x,y,GREEN); //打亮
36 if(d<0){
37 d+=2*dy;
38 }else{
39 y++;
40 d+=2*dy-2*dx;
41 }
42
43
44
45 }
46
47 }
48 int main()
49 {
50 initgraph(640,480); //打开EGE初始化
51 line1(200,160,400,400); //画线
52 getch(); //等待用户操作
53 closegraph(); //关闭图形
54 return 0;
55 }
2、Bresenham画线算法
这种画线算法的思想和中点画线的一致,只是在判断取哪个点时,不是看它位于中点的上边还是下边,而是将这俩个点到直线上那个点的距离相减,判断其正负,如果下边的点到直线实际点距离远则的d1-d2>=0那么取上边的点y1+1,同样也是代入直线化解可以得出下面结论:
(1)当d1-d2<0时,d=d+2*dy.
(2)当d1-d2>=0时,d=d+2*dy-2*dx.
(3)d的初始值为 d=2*dy-dx.
其代码如上所示。运行截图如下: