本帖最后由 _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; } }
|