Bresenham画线算法之我见
2009-04-26 23:06 hbb 阅读(710) 评论(0) 编辑 收藏 举报这样一直到最后,只要向上移一格,判断系数就加1。
2 dx=x1-x0;
3 k=dy/dx;
4 d=0;
5 b=0.5;
6 ix=x0;
7 iy=y0;
8 while(ix<=x1){
9 ++ix;
10 d += k;
11 if(d > b){
12 ++iy;
13 ++b;
14 }
15 }
这里面d就是用来累加斜率的,b是判别系数。
这样的好处很显然,少用一个变量。这就是传统的算法。
2 dx=x1-x0;
3 k=dy/dx;
4 d=0;
5 ix=x0;
6 iy=y0;
7 while(ix<=x1){
8 ++ix;
9 d += k;
10 if(d > 0.5){
11 ++iy;
12 --d;
13 }
14 }
然后是优化上的理解。
先考虑,斜率是否大于0.5,即k-0.5是否大于0。如果是就说明要向上,那么在累加斜率时要再减去1使得坐标轴也跟着向上。否则只加斜率就可以了。
2 while(ix<=x1){
3 ++ix;
4 if(d>0){
5 ++iy;
6 d+=k-1;
7 }else{
8 d+=k;
9 }
10 }
因为2和dx都是正数,只要之后的运算都放大2*dx倍,等号、不等号都不会受到影响。最终简化如下:
2 dx=x1-x0;
3 D=2*dy-dx;
4 ix=x0;
5 iy=y0;
6 while(ix<=x1){
7 ++ix;
8 if(D>0){
9 ++iy;
10 D+=2*(dy-dx);
11 }else{
12 D+=2*dy;
13 }
14 }
我用D表示放大了的d,实际代码中可以直接用同一个变量d。
最后是一般化
如果k<0,也就是本来往上走的,要往下走。这时仍用以前的思路,就要判断是否k-0.5<0,并且在是的时候坐标轴跟着往下移,然后y每次减1。
考虑让k>0,那么所有判断都不变,只要让y每次减1就可以了。因为判断条件只和斜率有关,和y的走向没有关系。我们完全可以根据同一个斜率,通过+-来改变y的走向,+的话就和斜率同向,-的话就和负斜率同向。而k本身是<0的,现在被我们变了向,那么y的走向再变一次,y的走向就成了我们需要的走向。
而此处是垂直翻转,改变k的符号,只要把dy取绝对值就可以了。
如果|k|>1,所谓的折中系数0.5就没意义了,这时可以把x轴看作y轴,y轴看作x轴,这样斜率又回到了0<|k|<1。只要最后在画线的时候,把x当y,y当x来填充就可以了。
最后考虑反向画线,也就是起点大于终点的情况,那很简单把它们颠倒一下就可以了。
注意,以上|k|>1时xy轴的互换的过程要放在最前面。因为在k>-1时,xy轴的互换会使起点终点关系互换,这时需要后面有检测机制。
xy2yx= abs(y1-y0) > abs(x1-x0);
if(xy2yx){
swap(x0,y0);
swap(x1,y1);
}
if(x0>x1){
swap(x0,x1);
swap(y0,y1);
}
ydir = y0>y1 ? -1 : 1;
dy=abs(y1-y0);
dx=x1-x0;
d=2*dy-dx;
ix=x0;
iy=y0;
while(ix<=x1){
if(xy2yx){
draw(iy,ix);
}else{
draw(ix,iy);
}
++ix;
if(d>0){
iy += ydir;
d+=2(dy-dx);
}else{
d+=2*dy;
}
}