以前我都没注意在LCD上画线、画圆,这两天想在LCD画线、画圆,就找资料找到了Bresenham算法,还找了一些分析文档,觉得好就分享给大家,知道的高手不要拍砖~
废话少说看图、看资料:
先看程序(程序分析自己看资料):
/***********************************************************
* 函数名称:LCD_DrawLine
* 函数功能:LCD画线函数
* 入口参数: x1,y1(起点坐标)x2,y2(终点坐标)c(颜色)
* 出口参数:无
***********************************************************/
// 交换整数 a 、b 的值
__inline void swap_int(u16 *a, u16 *b)
{
*a ^= *b;
*b ^= *a;
*a ^= *b;
}
// Bresenham's line algorithm
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2, u16 c)
{
u16 dx =abs( x2 - x1), // 水平距离
dy =abs( y2 - y1), // 垂直距离
yy = 0; // 角度是否大于45°标志
int ix ,
iy,
cx ,
cy ,
n2dy,
n2dydx ,
d ;
if(dx < dy) // 当斜率大于 1 时,dx、dy 互换, 即角度大于45°
{
yy = 1; // 设置标志位
swap_int(&x1, &y1); // 交换坐标
swap_int(&x2, &y2);
swap_int(&dx, &dy);
}
ix = (x2 - x1) > 0 ? 1 : -1; // 判断是否加1还是减一
iy = (y2 - y1) > 0 ? 1 : -1;
cx = x1; // x初值
cy = y1; // y初值
n2dy = dy * 2; // 求要比较的各个差值
n2dydx = (dy - dx) * 2;
d = dy * 2 - dx;
// 如果直线与 x 轴的夹角大于45度
if(yy)
{
while(cx != x2) // 计数是否达到终点
{
if(d < 0)
{
d += n2dy;
}
else
{
cy += iy;
d += n2dydx;
}
LCD_DrawPoint( cy, cx, c); // 画点
cx += ix;
}
}
// 如果直线与 x 轴的夹角小于45度
else
{
while(cx != x2)
{
if(d < 0)
{
d += n2dy;
}
else
{
cy += iy;
d += n2dydx;
}
LCD_DrawPoint( cx, cy, c);
cx += ix;
}
}
}
/**********************************************************
* 函数名称:LCD_DrawRectangle
* 函数功能:LCD画矩形函数
* 入口参数: x1,y1(对角线起点坐标)x2,y2(对角线终点坐标)color(颜色)
* 出口参数:无
***********************************************************/
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
{
LCD_DrawLine(x1,y1,x2,y1,color);
LCD_DrawLine(x1,y1,x1,y2,color);
LCD_DrawLine(x1,y2,x2,y2,color);
LCD_DrawLine(x2,y1,x2,y2,color);
}
/**********************************************************
* 函数名称:LCD_Drawcircle
* 函数功能:在指定位置画一个指定大小的圆
* 入口参数: (x,y)-(中心点坐标)r(半径)
* fill(为是否填充) c(颜色)
* 出口参数:无
***********************************************************/
__inline void draw_circle_8( u16 xc, u16 yc, u16 x, u16 y, u16 c)
{
// 参数 c 为颜色值
LCD_DrawPoint( xc + x, yc + y, c);
LCD_DrawPoint( xc - x, yc + y, c);
LCD_DrawPoint( xc + x, yc - y, c);
LCD_DrawPoint( xc - x, yc - y, c);
LCD_DrawPoint( xc + y, yc + x, c);
LCD_DrawPoint( xc - y, yc + x, c);
LCD_DrawPoint( xc + y, yc - x, c);
LCD_DrawPoint( xc - y, yc - x, c);
}
//Bresenham's circle algorithm
void LCD_Drawcircle( u16 xc, u16 yc, u16 r, u16 fill, u16 c)
{
// (xc, yc) 为圆心,r 为半径
// fill 为是否填充
// c 为颜色值
// 如果圆在图片可见区域外,直接退出
int x = 0, y = r, yi, d;
d = 3 - 2 * r;
if(xc + r < 0 || xc - r >= 240 || yc + r < 0 || yc - r >= 320)
{
return;
}
if(fill)
{
// 如果填充(画实心圆)
while(x <= y)
{
for(yi = x; yi <= y; yi ++)
{
draw_circle_8(xc, yc, x, yi, c);
}
if(d < 0)
{
d = d + 4 * x + 6;
}
else
{
d = d + 4 * (x - y);
y --;
}
x++;
}
}
else
{
// 如果不填充(画空心圆)
while (x <= y)
{
draw_circle_8(xc, yc, x, y, c);
if(d < 0)
{
d = d + 4 * x + 6;
}
else
{
d = d + 4 * (x - y);
y --;
}
x ++;
}
}
}
|