1、重点
- (1)画线函数:画任意一条直线,包含斜线
- (2)刻画时钟模型
- (3)模拟时钟划线
2、画线函数
- (1)通过直线方程:
y = kx + b
描线,很简单,但是像素点不会有小数,如此画出来的线,会丢失很多像素点,导致画出来的线不连续
- (2)Bresenham算法,通过直线的一般方程:
Ax + By + C = 0
来进行描绘,依次逼近 。(网上也很多人采取这种算法)
3、时钟的形状
- (1)通过网上找图片然后取模进行显示,就可以很方便弄出时钟模型,但是我不是很熟悉取模的步骤,在尝试过后便放弃了该方法。
- (2)通过自己计算找出每个刻度的位置,然后大概确定起始与终点的位置,然后画线。不得不说,这种方法数据量比较大,只是找数据就会找很久的时间,并且在你显示时会发现误差很大,不准。
- (3)确定指针的长度以及角度与时钟刻度的关系,通过
x = R*cos(angle)`` y = R*sin(angle)
,定好坐标之后便能进行画线(圆心已知)。由于没有取模,因此不容易给表盘定指示。
- (4)怎样确定时钟、分针、秒针的终点坐标,然后结合圆心来画线?
——由于每一个刻度都相应对应一个具体的角度,没走一个刻度偏移角度是确定了的。我们只需要建立一个坐标系,然后通过三角函数来计算,很方便获取坐标。我们只需要想计算就好了,难度不大。
4、函数实现
void L_DrawLine(int x1,int y1,int x2,int y2,int color)
{
int dx,dy,e; //e:误差,偏离的多少
dx=x2-x1;
dy=y2-y1;
if(dx>=0)
{
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 1/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
LCD_SetPoint(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else // 2/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
LCD_SetPoint(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else // dy<0
{
dy=-dy; // dy=abs(dy)
if(dx>=dy) // 8/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
LCD_SetPoint(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else // 7/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
LCD_SetPoint(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1 -= 1;
e += dx;
}
}
}
}
else //dx<0
{
dx=-dx; //dx=abs(dx)
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 4/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
LCD_SetPoint(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else // 3/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
LCD_SetPoint(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else // dy<0
{
dy=-dy; // dy=abs(dy)
if(dx>=dy) // 5/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
LCD_SetPoint(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else // 6/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
LCD_SetPoint(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
}
s_angle = second*6;//秒对应的角度,把360°60等分,一秒偏移6°
scale = (s_angle + 180.0)/180.0*3.1415926;
sx = 80*cos(scale) + X_cicle; //秒针的终点位置,加上圆心坐标
sy = 80*sin(scale) + Y_cicle;//
L_DrawLine(X_cicle, Y_cicle, sx_old, sy_old, Blue);//清除上一次的线(蓝底白线)
L_DrawLine(X_cicle, Y_cicle, sx, sy, White);//画线
sx_old = sx; //用完之后赋值,便于下一次清除之前的线
sy_old = sy;
void Display_Scale(void)//画刻度
{
u8 i = 0,j = 0;
static int x1 = 0,x2 = 0,y1 = 0,y2 = 0,angle = 0;
float scale = 0;;
for(i=0;i<60;i++)
{
angle = i*6;
scale = (angle + 180.0)/180.0*3.1415926;
if(i%5==0)
{
x1 = 100*cos(scale) + X_cicle; //加上圆心坐标
y1 = 100*sin(scale) + Y_cicle;
x2 = 90*cos(scale) + X_cicle; //加上圆心坐标
y2 = 90*sin(scale) + Y_cicle;
L_DrawLine(x1,y1,x2,y2,Red);
}
else
{
x1 = 100*cos(scale) + X_cicle; //加上圆心坐标
y1 = 100*sin(scale) + Y_cicle;
x2 = 95*cos(scale) + X_cicle; //加上圆心坐标
y2 = 95*sin(scale) + Y_cicle;
L_DrawLine(x1,y1,x2,y2,White);
}
}
}
网友评论