打印
[技术问答]

单片机屏幕填充任意封闭图形

[复制链接]
64|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
louliana|  楼主 | 2025-1-27 04:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
对于基础的矩形填充来说比较简单,只需找到最大最小坐标然后画线挨行填充即可
设定画线接口函数为Draw_Line(int x1,int y1,int x2,int y2,int color);
则矩形填充程序为:int maxx, maxy, minx, miny;int i;for (i = miny; i < maxy; i++){  Draw_Line(minx,i,maxx i, 0xF800);}填充圆形的方式为:在以圆的外接正方形范围内挨行判断坐标点和圆心的距离,小于等于半径的时候才画点(灰色区域的半径黄色箭头大于半径,不画点,橙色区域半径蓝色箭头小于半径,画点)
不过为了加速绘制速度,减少计算量,一般不使用挨个画点的方式,就像画圆一样不用角度递增挨个画点,加速方式是拆分成画线,一次性绘制一条线,因为屏幕最擅长的就是横平竖直的画线,加速方式如下。707/1000=0.707=1.414/2 ≈ √2 / 2
static void draw_hline(uint16_t x0,uint16_t y0,uint16_t len,uint16_t color){    if(len==0)return;    Draw_Line(x0,y0,x0+len-1,y0,color);}static void fill_circle(uint16_t x0,uint16_t y0,uint16_t r,uint16_t color){    uint32_t i;    uint32_t imax = ((uint32_t)r*707)/1000+1;    uint32_t sqmax = (uint32_t)r*(uint32_t)r+(uint32_t)r/2;    uint32_t x=r;    draw_hline(x0-r,y0,2*r,color);    for (i=1; i<=imax; i++)    {        if ((i*i+x*x)>sqmax)// draw lines from outside        {            if (x>imax)            {                draw_hline (x0-i+1,y0+x,2*(i-1),color);                draw_hline (x0-i+1,y0-x,2*(i-1),color);            }            x--;        }        draw_hline(x0-x,y0+i,2*x,color);        draw_hline(x0-x,y0-i,2*x,color);    }}更为复杂的图形填充方式有几种,对于凸多边形一般是拆分为三角形,使用三角形填充独立部分,凹多边形等复杂图形还是使用扫描方式判断坐标是否在封闭图形内。
判断程序如下。
uint16_t is_point_in(int nvert, float *vertx, float *verty, float testx, float testy){    uint8_t res;    int i, j, c = 0;    res = 0;    if ((testx > maxx) || (testy > maxy) || (testx < minx) || (testy < miny))        return 1000;    for (i = 0, j = nvert - 1; i < nvert; j = i++) {        if ( ( (verty > testy) != (verty[j] > testy) ) && (testx < (vertx[j] - vertx) * (testy - verty) / (verty[j] - verty) + vertx) )            c = !c;    }    return c;}增加原多边形坐标构建和区域显示和填充效果
void draw_shape(int nvert, float *vertx, float *verty){    int i, j;    POINT_COLOR = BLUE;    for (i = 0; i < nvert - 1; i++) {        printf("%5.1f,%5.1f -->> %5.1f,%5.1f\r\n", vertx, verty, vertx[i + 1], verty[i + 1]);        LCD_DrawLine((uint16_t)vertx, (uint16_t)verty, (uint16_t)vertx[i + 1], (uint16_t)verty[i + 1]);    }    LCD_DrawLine((uint16_t)vertx[nvert - 1], (uint16_t)verty[nvert - 1], (uint16_t)vertx[0], (uint16_t)verty[0]);}void create_five_star(float *vertx, float *verty, float x, float y, float r, float offset_angle){    //生成五角星坐标    int i, j;    for (i = 0; i < 10; i++) {        if (i % 2) {            *(vertx + i) = cos((i * 36 + offset_angle) * 3.1415926 / 180) * r + x;            *(verty + i) = sin((i * 36 + offset_angle) * 3.1415926 / 180) * r + y;        } else {            *(vertx + i) = cos((i * 36 + offset_angle) * 3.1415926 / 180) * r * 0.3 + x;            *(verty + i) = sin((i * 36 + offset_angle) * 3.1415926 / 180) * r * 0.3 + y;        }    }}void fill_shape(uint16_t color){    int i, j;    int res;    for (i = miny; i < maxy; i++) {        for (j = minx; j < maxx; j++) {            res = is_point_in(points, pointsx, pointsy, j, i);            if (res == 1000) {            } else if ((res % 2) == 0) {            } else if ((res % 2) == 1) {                LCD_Fast_DrawPoint(j, i, color);            }        }    }}调用演示
calc_min_max(points, pointsx, pointsy);draw_shape(points, pointsx, pointsy);fill_shape(BLUE);create_five_star(pointsx,pointsy,240,400,200,-36);calc_min_max(10,pointsx,pointsy);draw_shape(10,pointsx,pointsy);

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

1349

帖子

1

粉丝