在编写的FDGK/GUI决定采用中点画线算法绘制直线。故先研究了一下算法。
中点画线算法的原则是:如下图所示,但斜率K<1时,选定一个点之后,再计算中点M。如果M>0,这线更靠近E点,下一点选择为E点。反之选择NE点。
void GUI_DrawLine(uint16 x0,uint16 y0,uint16 x1,uint16 y1,uint16 color)
{
uint16 dx,dy,incrE,incrNE,x,y,d;
dx = x1 - x0;
dy = y1 - y0;
d = (dy<<1) - dx;
incrE = dy<<1;
incrNE = (dy - dx)<<1;
x = x0;
y = y0;
GUI_DrawPoint(x,y,color);
while(x<x1)
{
if(d > 0)
{
d += incrNE;
x++;
y++;
}
else
{
d += incrE;
x++;
}
GUI_DrawPoint(x,y,color);
}
}
void swap(uint16 *x0,uint16 *y0,uint16 *x1,uint16 *y1)
{
uint16 x,y;
x = *x1;
*x1 = *x0;
*x0 = x;
y = *y1;
*y1 = *y0;
*y0 = y;
}
void GUI_DrawLine(uint16 x0,uint16 y0,uint16 x1,uint16 y1,uint16 color)
{
int16 dx,dy,d;
uint16 x,y;
if( x0 > x1) /* 保证x0<x1,即x0为x1左边的点。*/
{
swap(&x0,&y0,&x1,&y1);
}
dx = x1 - x0;
dy = y1 - y0;
if( dx == 0) /* 斜率为无穷大,画直竖线 */
{
LCD_DrawVLine(x0,y0,y1,color);
return;
}
if( dy == 0) /*斜率为零,画水平线 */
{
LCD_DrawHLine(x0,y0,x1,color);
return;
}
x = x0;
y = y0;
GUI_DrawPoint(x,y,color);
if((dx>=dy)&&(dy>0)) /* when 0<k<=1 */
{
d = (dy*2) - dx;
while(x<x1)
{
if(d > 0)
{
d += (dy - dx)*2; /* 选择NE点 */
x++;
y++;
}
else
{
d += dy*2; /* 选择N点 */
x++;
}
GUI_DrawPoint(x,y,color);
}
return;
}
if( (dy>dx)&&(dy>0)) /* when k>1 */
{
d = dy - (dx*2);
while(y<y1)
{
if(d < 0)
{
d += (dy - dx)*2; /* 选择 NE 点 */
x++;
y++;
}
else
{
d += (-dx)*2; /* 选择N点 */
y++;
}
GUI_DrawPoint(x,y,color);
}
return;
}
if((dx>=ABS(dy))&&(dy<0)) /* when -1=<k<0 */
{
d = (dy*2) + dx; /* d = 2a-b */
while(x<x1)
{
if(d < 0)
{
d += (dy+dx) * 2; /* 选择SE点 */
x++;
y--;
}
else
{
d += dy*2; /* 选择S点 */
x++;
}
GUI_DrawPoint(x,y,color);
}
return;
}
if( (ABS(dy)>dx)&&(dy<0)) /* when k<-1 */
{
d = dy + (dx*2); /* d = a - 2b */
while(y>y1)
{
if(d > 0)
{
d += (dy + dx)*2; /* 选择 SE 点 */
x++;
y--;
}
else
{
d += (dx)*2; /* 选择S点 */
y--;
}
GUI_DrawPoint(x,y,color);
}
return;
}
}