LCD直线(线段)画线算法

尝试了多个版本,最好用的还是正点原子LCD驱动提供的版本。

  1. x轴扫描法


    image.png

没有进行任何优化,扫描也是最简单的沿着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;
  }
}
  1. 正点原子优化方法


    image.png

    采用了自适应逼近方法,自动选取最合适的增量方式,并规避了浮点数运算。

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;
    }
  }
}