画线函数Glib_Line算法研究续

          Glib_Line是2440开发板上的LCD_TFT驱动中的一个函数。在Chinaunix网上有网友发过博文《对于画线函数Glib_Line算法的研究》,读过如拨云见日,一解我多日对此函数的困惑。受原博文的启发,加上我自己的理解,我整理出下面的博文,做一个学习记录,也希望各位能互相学习。

   void Glib_Line的部分函数如下:

void Glib_Line(int x1,int y1,int x2,int y2,int color)
{
    int dx,dy,e;
    dx=x2-x1; 
    dy=y2-y1;
     
    if(dx>=0)
    {
        if(dy >= 0) // dy>=0
        {
            if(dx>=dy) // 1/8 octant
            {
                e=dy-dx/2;
                while(x1<=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1+=1;e-=dx;}    
                    x1+=1;
                    e+=dy;
                }
            }
       .......................
}
   假设需要划线的两点坐标分别是(x1,y1)和(x2,y2),dx=x2-x1,dy=y2-y1.对于画线来讲,我们只关心相对坐标,所以我们可以把两个点的坐标进行变换,变成(0,0)和(dx,dy).我们以代码中的dx>0,dy>0,dx>=dy这种情况为例进行讨论。

   这条线理论上:y=kx,k=dy/dx.对LCD显示来说,x和y点坐标都为整数。我们算法的思想是什么?就是要比较y的理论值与当前y值+1/2的大小,也就是要判断理论值更接近于谁。从(0,0)开始,当x=1,y=k*1=dy/dx,由于k<=1,y<=x,我们需要判断y和1/2(也就是1和0的中间)谁较大,也就是比较dy/dx-1/2是否大于0,即e=dy-1/2*dx是否大于0.如果大于0,那么说明理论y值接近1,所以画线时取(1,1),否则说明理论y值接近0,所以画线时取(1,0).对于第三点,分两种情况,

(1) 如果第二点取(1,1),那么第三点理论值y=k*2=2*dy/dx,需要比较y和3/2(即1和2的中间值)谁大,也就是要比较2*dy/dx-3/2是否大于0,即e=dy+dy-1/2*dx-dx是否大于0,可以看到这次的e与上次的e比较多了-dx,+dy,这也正是函数中多出现的e-=dx和d+=dy.

(2) 如果第二点取(1,0),那么第三点理论值y=k*2=2*dy/dx,需要比较y和1/2(即1和0的中间值)谁大,也就是要比较2*dy/dx-1/2是否大于0,即e=dy+dy-1/2*dx是否大于0,可以看到这次的e与上次的e比较多了+dy,这也正是函数中多出现的d+=dy,没有-dx.

现在我们大致可以看出判断条件与代码是一致的,也基本上说明了代码正是按照这种判断的算法思想编程的。

我们注意到代码中e的值实际上就是要比较判断的值,进一步推导:

1 假定画面中有一点(n,m)(如红点所示),那么下一个理论点是y=k*(n+1)=(n+1)*dy/dx,需要比较(n+1)*dy/dx和m+1/2(即m和m+1的中间值)谁大,也就是要比较e=(n+1)dy-m*dx-dx/2是否大于0.

2 从图中比较得到e>0,那么画线取点为(n+1,m+1)(如红点所示).

3 根据代码,e'=e+dy-dx=(n+2)dy-(m+1+1/2)dx, 这也等同于比较 (n+2)*dy/dx和(m+1+1/2)(即m+1和m+2的中间值)的大小,与我们之前所述的算法的思想是一致的。

 

 这里只列出了一种情况,其他情况也类似。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值