野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 11792|回复: 1

直线Bresenham算法的一个程序分析

[复制链接]
发表于 2018-9-13 19:38:15 | 显示全部楼层 |阅读模式
本帖最后由 _libra 于 2018-9-13 19:39 编辑

 四、直线Bresenham算法实现:

  条件:0≤m≤1且x1<x2

  1、输入线段的两个端点坐标和画线颜色:x1,y1,x2,y2,color;
  2、设置象素坐标初值:x=x1,y=y1;
  3、设置初始误差判别值:p=2·Δy-Δx;
  4、分别计算:Δx=x2-x1、Δy=y2-y1;
  5、循环实现直线的生成:
   for(x=x1;x<=x2;x++)   //  显示的像素点数目;要显示的x改变;
   { putpixel(x,y,color) ;     //  点亮像素;
    if(p>=0)                       

     { y=y+1;                   //  p>0 , 说明,当Xi+1时 ,即点亮的下一个点靠近yi+1,即像素点画在  (xi+1,yi+1)处

                                                    //   P=0 ,说明,当Xi+1时,下一个点与yi和yi+1距离相等,此时像素点画在(xi+1,yi+1)或(xi+1,yi)都可以,按照一个规定即可;
      p=p+2·(Δy-Δx);    // 更新P值;(dx>0,dy>0,斜率dy/dx<1,so  dy-dx<0 ) why要这个公式,需要看懂Bresenham算法;
     }
    else                               //   要显示的 y 值不变;p<0 , 说明,当Xi+1时 ,即点亮的下一个点靠近yi,即像素点画在  (xi+1,yi)处
     { p=p+2·Δy;             //    why要这个公式,需要看懂Bresenham算法;

                                                           //https://blog.csdn.net/cjw_soledad/article/details/78886117  这个地址可以看到Bresenham算法的多个解析;以及这个算法
     }

  }

下面是我根据上面的代码和Bresenham算法写的适用于任意方向直线的程序代码;

//   上面的 12345678 显示 x2 y2的地点,即线段终点所在的区域;

void Bresenhamline (uint x1,uint y1,uint x2,uint y2,uint color) // x1,y1, 直线起始像素点位置, x2,y2  直线结束像素点位置,color 直线颜色;

{

        uint x, y, dx, dy, temp, interchange, i;

        char  Step_x, Step_y ,p;

         x=x1;

         y=y1;

        if(x2>=x1){dx = x2-x1;Step_x = 1;}else{dx = x1-x2;Step_x = -1;}                          // x2>=x1 , 直线终点在  上图的 1 2 7 8 区域;x2<x1, 直线终点在  上图的 3 4  5 6 区域;

        if(y2>=y1){dy = y2-y1;Step_y = 1;}else{dy = y1-y2;Step_y = -1;}                          // y2>=y1 , 直线终点在  上图的 1 2 3 4 区域;y2<y1, 直线终点在  上图的 5 6  7 8 区域;

        if(dy>dx){/* temp = dx;dx = dy;dy = temp; */interchange = 1;}else{interchange = 0;}     //



//  if(dx>=dy){                            //  扩展到 1 8 4 5 区域

//        p = 2*dy-dx;                 //  最初p判定式;

//        for(i=1;i<=dx+1;i++)    //  显示 dx+1 个像素; 如x2 = 3 ,x1 = 8; dx = 8 - 3 = 5 ;实际需要显示 8 7 6 5 4 3 六个 dx+1 像素;

//        {

//                GUI_Dot(x, y, color);            //  i=1时 显示第一个像素,即最初像素;

//                if(p>=0)                             //  x,y都改变

//                {

//                        if(0==interchange)     //  0<斜率1 或者  -1<斜率<0  ,dx>dy;

//                        {

//                                x += Step_x;     //  直线终点在 1 8 区域(x2>=x1) ,Step_x = 1; 直线终点在 4 5 区域(x2<x1) ,Step_x = -1;

//                                y += Step_y;     //  直线终点在 1 4 区域(y2>=y1) ,Step_y = 1; 直线终点在 5 8 区域(y2<y1) ,Step_y = -1;

//                        }  //  结合上面的图看,应该会较容易明白;

//                        p = p + 2*(dy-dx);

//                }

//                else                                 //  p<0;

//                {

//                        if(0==interchange)

//                        {

//                                x += Step_x;  //  x改变,y不变

//                        }

//                        p = p + 2*dy;

//                }

//        }

//}


//if(dx<dy){                                //  扩展到 2 3 6 7 区域

//        p = 2*dx-dy;                       //  判定式p  变成 2*dx-dy;

//        for(i=1;i<=dy+1;i++)          // dy>dx, dy决定显示的像素个数;

//        {

//                GUI_Dot(x, y, color);

//                if(p>=0)                                    //  x,y 都改变;

//                {

//                        if(1==interchange)            // y 相当于 自变量;

//                        {

//                                x += Step_x;           //   直线终点在 2 3 区域(x2>=x1) ,Step_x = 1; 直线终点在 6 7 区域(x2<x1) ,Step_x = -1;

//                                y += Step_y;           //   直线终点在 2 3 区域(y2>=y1) ,Step_y = 1; 直线终点在 6 7 区域(y2<y1) ,Step_y = -1;

//                        }

//                        p = p + 2*(dx-dy);

//                }

//                else                                       //  p<0 , y改变,x不变;

//                {

//                        if(1==interchange)  

//                        {

//                                y += Step_y;  

//                        }

//                        p = p + 2*dx;

//                }

//        }

//}       


/*  通过分析上面dx>=dy,与dx<dy的程序 ,下面是合并起来的程序  */

//   上面的/* temp = dx;dx = dy;dy = temp; */  取消注释,使得dx总是大于dy,并把初始dx与dy的大小关系保存在interchange中;

        p = 2*dy-dx;

        for(i=1;i<=dx+1;i++)              

        {

                GUI_Dot(x, y, color);

                if(p>=0)                  

                {

//                        if(0==interchange)

//                        {                           

                                x += Step_x;           //  p>=0,x,y总是改变;所以无需判断interchange;

                                y += Step_y;

//                        }

                        p = p + 2*(dy-dx);

                }

                else

                {

                        if(0==interchange)       //  初始dx >= dy ,x 改变;

                        {

                                x += Step_x;

                        }

                        else                              // 初始dx < dy ,y 改变;

                        {

                                y += Step_y;

                        }

                        p = p + 2*dy;

                }

        }



回复

使用道具 举报

 楼主| 发表于 2018-9-13 19:42:39 | 显示全部楼层
为以后忘记备忘一下
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-23 04:32 , Processed in 0.032249 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表