STM32学习笔记-LCD画直线,画圆
1.画直线
如果在两点(a,b)(c,d)之间画直线,首先考虑c>a,d>b,且k<1的情况,其他情况根据对称关系就能推导出来了。
为了使问题简单化,先将这两点进行平移,将(a,b)平移到原点,那么(c,d)变换后的坐标就是(e,f),其中e=c-a,f=d-b,斜率k=f/e;
假设在LCD上我们取的第i个像素点的坐标是(i,j),那么第i+1个像素点的坐标应该是(i+1,j)或者(i+1,j+1),到底取那个点,我们就需要判定这两个点离哪个点距离实际点(i+1,(i+1)*k)更近
(i+1,j)与(i+1,(i+1)*k)距离S1=(i+1)*k-j
(i+1,j+1)与(i+1,(i+1)*k)距离S2=j+1-(i+1)k
设S1>S2
(i+1)k-j>j+1-(i+1)k
2(i+1)k>2j+1
将k=f/e,代入
2(i+1)f/e>2j+1
2(i+1)f>(2j+1)*e //根据第i点来推测i+1个点位置的判别式
i=0;j=0;//初始点
for(i=0;i<e+1;i++)
{
if(e*(2*j+1)<2*f*(i+1))//根据当前点的位置来推测下一个点的位置
{
j++; //像素点(i+1,j+1)距离实际点(i+1,(i+1)*k)更近
}
}
根据上述代码我们就得到(0,0)到(e,f)的所有点,其他情况可以根据对称性得到,以下为所有情况的代码
void drawline(u32 a,u32 b,u32 c,u32 d,u16 color)
{
u32 e,f,i,j,g,flag;//flag为两点之间状态标志位
flag=0;
if(c>a)
{
e=c-a;
}
else
{
e=a-c;
flag|=0x01;
}
if(d>b)
{
f=d-b;
}
else
{
f=b-d;
flag|=0x02;
}
if(f>e)//当画线斜率大于1时,
{
g=f;
f=e;
e=g;
flag|=0x04;
}
j=0;
for(i=0;i<e+1;i++)
{
switch(flag&0x07)
{
case 0:LCD_dpoint(a+i,b+j,color); break; //画点时要将坐标平移回来
case 1:LCD_dpoint(a-i,b+j,color); break;
case 2:LCD_dpoint(a+i,b-j,color); break;
case 3:LCD_dpoint(a-i,b-j,color); break;
case 4:LCD_dpoint(a+j,b+i,color); break;
case 5:LCD_dpoint(a-j,b+i,color); break;
case 6:LCD_dpoint(a+j,b-i,color); break;
case 7:LCD_dpoint(a-j,b-i,color); break;
default:break;
}
if(e*(2*j+1)<2*f*(i+1))//根据当前点的位置来推测下一个点的位置
{
j++;
}
}
}
2.画圆
画圆的方法与画直线的方法类似,也是根据第i个点的坐标来推测i+1个点的坐标,因为圆的对称性,只需要画1/8圆即可,只需要画出从A到B的圆弧
已知圆心(a,b)与半径r,横坐标变化量i,纵坐标变化量j,A点坐标为(a,b+r)
第i个像素点的坐标为(a+i,b+r-j) 第i+1像素点的坐标就是(a+i+1,b+r-j)或者是(a+i+1,b+r-(j+1)),我们需要判断那个点离实际点更近。我们可以首先求出这两个像素点的中点C(x,y)其中x=(2a+2i+1)/2,y=(2b+2r-2j-1)/2,当中点C在圆外时(x-a) ^2+ (y-b) ^2>r ^2,此时实际点离(a+i+1,b+r-j)更近,当中点C在圆内时(x-a) ^2+ (y-b) ^2
停止点B坐标满足的条件为i+j=r,但实际仅设置这个条件可能不行还需要加上条件i+j+1;
i=j=0;
while((i+j!=r)&&(i+j!=r+1))
{
if(4*(i+1)*(i+1)+(2*r-2*j+1)*(2*r-2*j+1)>4*r*r)
{
j++;
}
i++;
}
这样就得到了所有点,再根据对称性得到其他部分圆弧,以下为实现代码
void draw_circle(u32 a,u32 b,u32 r,u16 color)
{
u32 i,j;
i=j=0;
while((i+j!=r)&&(i+j!=r+1))
{
LCD_dpoint(a+i,b+r-j,color);
LCD_dpoint(a+i,b-r+j,color);
LCD_dpoint(a-i,b+r-j,color);
LCD_dpoint(a-i,b-r+j,color);
LCD_dpoint(a+r-j,b+i,color);
LCD_dpoint(a-r+j,b+i,color);
LCD_dpoint(a+r-j,b-i,color);
LCD_dpoint(a-r+j,b-i,color);
if(4*(i+1)*(i+1)+(2*r-2*j+1)*(2*r-2*j+1)>4*r*r)
{
j++;
}
i++;
}
}