louliana 发表于 2025-1-27 04:51

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

对于基础的矩形填充来说比较简单,只需找到最大最小坐标然后画线挨行填充即可
https://i1.hdslb.com/bfs/article/e80e1347b52dd02d42ded5e1b3806ceac1497a83.png@1192w.webp设定画线接口函数为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);}填充圆形的方式为:在以圆的外接正方形范围内挨行判断坐标点和圆心的距离,小于等于半径的时候才画点(灰色区域的半径黄色箭头大于半径,不画点,橙色区域半径蓝色箭头小于半径,画点)https://i1.hdslb.com/bfs/article/5897c320cdfe33b7348b260215415bd93cb65fa2.png@624w_630h.webp
不过为了加速绘制速度,减少计算量,一般不使用挨个画点的方式,就像画圆一样不用角度递增挨个画点,加速方式是拆分成画线,一次性绘制一条线,因为屏幕最擅长的就是横平竖直的画线,加速方式如下。707/1000=0.707=1.414/2 ≈ √2 / 2static 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 > testy) ) && (testx < (vertx - vertx) * (testy - verty) / (verty - 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, verty);      LCD_DrawLine((uint16_t)vertx, (uint16_t)verty, (uint16_t)vertx, (uint16_t)verty);    }    LCD_DrawLine((uint16_t)vertx, (uint16_t)verty, (uint16_t)vertx, (uint16_t)verty);}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);

mmbs 发表于 2025-2-4 19:35

单片机的内存通常有限,因此在填充图形时需要考虑内存的使用。避免使用过多的临时变量和复杂的算法,以减少内存占用。

wwppd 发表于 2025-2-4 22:24

对于多边形等复杂图形,可能需要将其拆分为更简单的图形(如三角形)进行填充,或者使用扫描线填充算法等更复杂的算法。

hudi008 发表于 2025-2-5 09:34

选择合适的填充算法非常重要。常见的填充算法包括种子填充法、边界填充法和扫描线算法。每种算法都有其优缺点,需要根据具体情况选择。

caigang13 发表于 2025-2-5 11:22

关于GUI的画图这个都是标准函数

modesty3jonah 发表于 2025-2-5 13:12

对于简单的规则图形,如矩形、圆形等,要精确计算其边界坐标;对于复杂的不规则图形,需要通过合适的算法或工具来获取准确的坐标点集,以便正确地描绘出图形的轮廓。

jonas222 发表于 2025-2-5 13:43

对于一些精细的图形,可能需要进行抗锯齿处理,以提高填充效果的平滑度。

cashrwood 发表于 2025-2-5 16:05

在填充图形时,可能需要考虑抗锯齿处理以提高图形的视觉质量。这会增加算法的复杂度,但也可能提高用户的满意度。

kmzuaz 发表于 2025-2-5 18:15

在图形填充过程中,如果单片机需要处理其他中断事件,要确保中断处理不会影响图形填充的正常进行。可以采用中断优先级管理、中断屏蔽等方法来避免中断干扰。

dspmana 发表于 2025-2-5 18:42

单片机的计算能力和内存有限,因此填充算法需要尽量高效。例如,可以使用线段绘制来加速填充过程,而不是逐点填充。

sdlls 发表于 2025-2-5 19:37

根据单片机屏幕的显示能力选择合适的颜色模式和颜色值。如果是彩色屏幕,要考虑颜色的搭配和对比度,以便使填充的图形更加醒目和易于区分;如果是单色或灰度屏幕,则需要通过灰度值的变化来表现图形的不同层次和细节。

biechedan 发表于 2025-2-6 15:27

图形填充过程可能会消耗较多的电量,特别是在需要频繁更新图形的情况下。要合理控制单片机的功耗,采用低功耗模式或优化算法来降低功耗。

uptown 发表于 2025-2-6 16:54

不同的显示屏对驱动信号有不同的要求,要确保单片机的驱动能力能够满足显示屏的需求。如果驱动能力不足,可能会出现显示颜色不准确、亮度不均匀等问题。

chenjun89 发表于 2025-2-6 17:27

最终都是转化为画点操作

uiint 发表于 2025-2-6 17:55

根据图形的复杂度选择合适的填充算法。对于简单的图形(如矩形),可以直接逐行填充;对于复杂的图形(如圆形或任意多边形),可能需要使用更高级的算法,如扫描线填充或三角形填充

adolphcocker 发表于 2025-2-6 18:15

图形的边界和内部点。通常,这需要图形的数学描述,如多边形的顶点坐标。
对于复杂的图形,可能需要将图形分解为多个简单的形状(如矩形、三角形)进行处理。

abotomson 发表于 2025-2-13 20:51

注意填充算法对内存的使用情况,避免内存溢出或不必要的内存占用。

sdlls 发表于 2025-2-14 09:59

如果图形边缘不是垂直或水平线,可能需要考虑抗锯齿技术以平滑边缘。

jackcat 发表于 2025-2-14 12:05

如果需要实现用户与图形的交互功能,如点击、拖动等,要考虑如何检测用户的输入操作,并及时更新图形的状态和显示。这需要编写相应的交互逻辑代码,并与图形填充功能相结合。

claretttt 发表于 2025-2-14 14:43

为了提高绘制效率,可以采用一些优化技巧。例如,对于圆形填充,可以拆分成多条水平线进行绘制,而不是逐个像素绘制
页: [1] 2 3
查看完整版本: 单片机屏幕填充任意封闭图形