尝试了多个版本,最好用的还是正点原子LCD驱动提供的版本。
-
x轴扫描法
没有进行任何优化,扫描也是最简单的沿着x轴扫描,y轴以斜率k逼近,最后采用四舍五入完成绘图。
特点是只能画斜率比较小的线,斜率增大后会出现明显的锯齿,垂直直线画出来就只剩下散点。
优点也有,就是易于理解,画图速度高。
void LCD_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, unsigned int color)
{
if (x1 < x0)
{
int t = x0;
x0 = x1;
x1 = t;
t = y0;
y0 = y1;
y1 = t;
}
int x;
float dx, dy, y, k;
dx = x1 - x0;
dy = y1 - y0;
k = dy / (float)dx;
y = y0;
// int step = x1>x0? 1 : -1;
for (x = x0; x <= x1; x++)
{
LCD_DrawPixel(x, (int)(y + 0.5), color);
y = y + k;
}
}
-
正点原子优化方法
采用了自适应逼近方法,自动选取最合适的增量方式,并规避了浮点数运算。
void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, unsigned int color)
{
uint16_t t;
int xerr = 0, yerr = 0, delta_x, delta_y, distance;
int incx, incy, uRow, uCol;
delta_x = x2 - x1; //计算坐标增量
delta_y = y2 - y1;
uRow = x1;
uCol = y1;
if (delta_x > 0)
incx = 1; //设置单步方向
else if (delta_x == 0)
incx = 0; //垂直线
else
{
incx = -1;
delta_x = -delta_x;
}
if (delta_y > 0)
incy = 1;
else if (delta_y == 0)
incy = 0; //水平线
else
{
incy = -1;
delta_y = -delta_y;
}
if (delta_x > delta_y)
distance = delta_x; //选取基本增量坐标轴
else
distance = delta_y;
for (t = 0; t <= distance + 1; t++) //画线输出
{
LCD_DrawPixel(uRow, uCol, color); //画点
xerr += delta_x;
yerr += delta_y;
if (xerr > distance)
{
xerr -= distance;
uRow += incx;
}
if (yerr > distance)
{
yerr -= distance;
uCol += incy;
}
}
}