/*******************************************************************************************
说明:12864字符串显示和绘图函数,包含圆、直线、椭圆的bresenham画法
完成日期:2012.12.18
作者:HB
********************************************************************************************/
//8*16单字符显示函数,x,y表示横纵坐标,str为要现实的字符编码数组
#include <math.h>
/*void dispchar8(uchar x,uchar y,uchar *str)
{
if(x<8) play8(0,x,y,str); //屏 列 页
else play8(1,(x&0x07),y,str);
//delay1ms(200);
}
*/
#define dispchar8(x,y,str) play8((x)>>3,(x)&0x07,y,str)
//8*16连续字符显示函数,x,y表示横纵坐标,str为要现实的字符编码数组,lengsh为要显示的长度
void dispstr8(uchar x,uchar y,uchar *str,uchar length)
{
uchar i;
for(i=0;i<length;i++)
{dispchar8(x+i,y,str);
str+=16; }
}
//16*16单字符显示函数,x,y表示横纵坐标,str为要现实的字符编码数组
void dispchar16(uchar x,uchar y,uchar *str)
{
if(x<4) play16(0,x<<1,y,str); //屏 列 页
else play16(1,(x&0x03)<<1,y,str);
//delay1ms(200);
}
//16*16连续字符显示函数,x,y表示横纵坐标,str为要现实的字符编码数组,lengsh为要显示的长度
void dispstr16(uchar x,uchar y,uchar *str,uchar length)
{
uchar i;
for(i=0;i<length;i++)
{dispchar16(x++,y,str);
str+=32; }
}
/******************************************************************************************
几个绘图函数
******************************************************************************************/
//在屏幕上画一条直线,参数(x1,y1)(x2,y2)为起点终点坐标
void line(uchar x1,uchar y1,uchar x2,uchar y2)
{ uchar x;
if(x1<x2)
for(x=x1;x<=x2;x++)dot(x,y1+(int)(x-x1)*(y2-y1)/(x2-x1));
else if(x1==x2)
{
/*if(y1<=y2) for(x=y1;x<=y2;x++)dot(x1,x);
else for(x=y2;x<=y1;x++)dot(x1,x);*/
vertical(y1,y2,x1);//画竖线
}
else
for(x=x2;x<=x1;x++)dot(x,y2+(int)(x-x2)*(y2-y1)/(x2-x1));
}
//使用Bresenham画直线,包括起始点,不包括终点
void Line_Bresenham(uchar x1, uchar y1, uchar x2, uchar y2)
{
uchar x = x1;
uchar y = y1;
uchar dx = abs(x2 - x1);
uchar dy = abs(y2 - y1);
char s1 = x2 > x1 ? 1 : -1;
char s2 = y2 > y1 ? 1 : -1;
uchar temp;
int p;
uchar i;
bit interchange = 0; // ????? dx?dy
if (dy > dx) // 斜率大于1时dx dy互换
{
temp = dx;
dx = dy;
dy = temp;
interchange = 1;
}
p = 2 * dy - dx;
for( i = 0; i < dx; i++)
{
dot(x, y);
if (p >= 0)
{
if (!interchange) // ??? < 1 ?,???????
y += s2;
else // ??? > 1 ?,???????
x += s1;
p -= 2 * dx;
}
if (!interchange)
x += s1; // ??? < 1 ?,?? x ???
else
y += s2; // ??? > 1 ?,?? y ???
p += 2 * dy;
}
}
//自定义画圆函数
void hbCircle(uchar x,uchar y,uchar r) //顺时针方向画图
{
uchar i,j;
uchar x1,y1;//对称点坐标
for(i=x+r;i>=x+r*7/10;i--) //只计算第四象限
//for(j=x+r+y-i;j<=y-x+i;j++) // 只计算面积为r*r/4 的三角形内的点
for(j=x+r+y-i;j<=x+r+(r>>1)+y-i;j++) // 进一步缩小计算的面积部分
{ //if(2*x<i||i>127||2*y<j||j>63)continue; //如果点落在屏幕外,则跳过
if(abs((i-x)*(i-x)+(j-y)*(j-y)-r*r)<=r) //画圆函数关键算法
{ dot(i,j);
dot(x*2-i,j);
dot(i,y*2-j);
dot(x*2-i,y*2-j);
// 计算关于直线斜对称的点
y1=y-x+i;
x1=x-y+j;
dot(x1,y1);
dot(x*2-x1,y1);
dot(x1,y*2-y1);
dot(x*2-x1,y*2-y1);
}
}
}
// 正负画圆法。画出的圆有点不规则
void Circle_PN(uchar x, uchar y, uchar r)
{
uchar tx = 0, ty = r;
int f = 0;
while(tx <= ty)
{
// 8分法
dot(x + tx, y + ty);
dot(x + tx, y - ty);
dot(x - tx, y + ty);
dot(x - tx, y - ty);
dot(x + ty, y + tx);
dot(x + ty, y - tx);
dot(x - ty, y + tx);
dot(x - ty, y - tx);
if(f <= 0)
f = f + (tx<<1) + 1, tx++;
else
f = f - (ty<<1) + 1, ty--;
}
}
// 中点Bresenham画圆法
void Circle_Midpoint(uchar x, uchar y, uchar r)
{
uchar tx = 0,ty = r;
int d = 1 - r;
while(tx <= ty)
{
// ???????????
dot(x + tx, y + ty);
dot(x + tx, y - ty);
dot(x - tx, y + ty);
dot(x - tx, y - ty);
dot(x + ty, y + tx);
dot(x + ty, y - tx);
dot(x - ty, y + tx);
dot(x - ty, y - tx);
if(d < 0)
d += 2 * tx + 3;
else
d += 2 * (tx - ty) + 5, ty--;
tx++;
}
}
//Bresenham法画圆,比较规则
void Circle_Bresenham(uchar x, uchar y, uchar r)
{
uchar tx = 0,ty = r;
int d = 3 - (r<<1);
while( tx <= ty)
{
// ???????????
dot(x + tx, y + ty);
dot(x + tx, y - ty);
dot(x - tx, y + ty);
dot(x - tx, y - ty);
dot(x + ty, y + tx);
dot(x + ty, y - tx);
dot(x - ty, y + tx);
dot(x - ty, y - tx);
if (d < 0) // ?????
d += (tx<<2) + 6;
else // ?????
d += ((tx - ty)<<2) + 10, ty--;
tx++;
}
}
//Bresenham画椭圆算法
//输入参数:长轴,短轴,中心坐标
void drawEllipse (char a, char b, uchar xLoc,uchar yLoc) //int
{
char x, y; //int
float d1, d2, aa, bb;
aa = a * a;
bb = b * b;
d1 = bb + aa * (-b + 0.25);
x = 0;
y = b;
dot (xLoc+ x, yLoc +y);
dot (xLoc-x, yLoc+y);
dot (xLoc-x, yLoc-y);
dot (xLoc +x, yLoc-y);
while (bb * (x + 1) < aa * (y - 0.5))
{
if (d1 <= -0.000001)
{
d1 += bb * ((x << 1) + 3);
}
else
{
d1 += bb * ((x << 1) + 3) + aa * (2 - (y << 1));
-- y;
}
++ x;
dot (xLoc+ x, yLoc+ y);
dot (xLoc-x, yLoc +y);
dot (xLoc-x, yLoc-y);
dot ( xLoc+x,yLoc -y);
}
d2 = bb * (0.25 * x) + aa * (1 - (y << 1));
while (y > 0)
{
if (d2 <= -0.000001)
{
++ x;
d2 += bb * ((x + 1) << 1) + aa * (3 - (y << 1));
}
else
{
d2 += aa * (3 - (y << 1));
}
-- y;
dot (xLoc+ x, yLoc+ y);
dot (xLoc-x,yLoc -y);
dot (xLoc-x, yLoc+y);
dot (xLoc+ x, yLoc-y);
}
}
//画矩形
void rectangle(uchar x1,uchar y1,uchar x2,uchar y2 )
{
vertical(y1,y2,x1);//画竖线
//line(x1,y1,x1,y2 );
line(x1,y1,x2,y1 );
vertical(y1,y2,x2);//画竖线
//line(x2,y1,x2,y2 );
line(x1,y2,x2,y2 );
}