前言
- 本博文算是一个简单的算法类的博客。
- 硬件材料是: 0.96OLED(IIC接口)中景园SSD1306;
STM32L496开发板(IIC-1); - 关于OLED这里就不说了,主要阐述软件这块儿对功能的实现;
要实现的功能描述和效果
如下图:图片中有一对同心固定的大小圆和一个带圆心的移动圆。
要求: 大小圆在整个屏幕内的位置不会变。移动圆随着给定的参数的改变,实际坐标位置可能在屏幕内任意位置。但是为了完成电子气泡的效果,这里要求:移动圆圆心不能出大圆,也就是移动圆的实际坐标位置无论有没有在大圆外,其显示坐标位置都不能在大圆外。当移动圆坐标没有落在大圆内(包含边)时,就要求移动圆圆心落在移动圆圆心实际坐标和大圆圆心坐标之间的连线与大圆的交点上(绕口)。(以上步骤,下面分步实现)
建立平面坐标系
理解两个坐标系:
OLED物理坐标系(如图)
说明::x,y的值是由OLED本身决定,屏幕的原点在屏幕的左上角;但是我们不用这个坐标系,因计算很麻烦,我们希望原点就在(64,32)这个地方。因此我们假设一个抽象坐标系,此坐标系的原点对应于物理坐标系的(64,32);
抽象坐标系
抽象坐标系参数:
- 大圆圆心坐标为(x0=0,y0=0),大圆小圆半径固定为R1和R2,R1=32,R2=7。
- 移动圆的圆心坐标是(x1,y1),半径r1为4;
- 建立平面坐标系:
分析移动圆的位置(初中数学)
转化为C语言就是
double x1 ,y1 , z1;
x1 = -64; //给定移动圆坐标
y1 = -32;
z1= sqrt(pow(x1,2)+pow(y1,2)); //这里的temp就是勾股定理的长边;
if(z1 > 32) //移动圆圆心在大圆外
{
/*code*/
}
else //移动圆圆心在大圆内(包含边)
{
/*code*/
}
分析移动圆在大圆外时如何计算交点坐标
解题思路:等比三角形; 这个解题思路比较简单,用直线与圆的交点太难了,程序很难实现;
程序实现:
void Module_Image_display_Circle(void)
{
double x0 = 64,y0 = 32; //定义偏移量;
double x1 = -64,y1 = -32,z1;
while(Key_F1 == 6)
{
memset(OLED_GRAM,0, sizeof(OLED_GRAM)); //清空数组
//获取倾斜度数据
x1+=2; //x1 =倾斜值x;
y1++; //y1 =倾斜值y;
if( x >= 127)
{
y1 = -32;
x1 = -64;
}
HAL_Delay(100);
//显示倾斜度数据
OLED_DrawPoint(64,32); //圆心
OLED_DrawCircle(64,32,32); //大圆(圆域)
OLED_DrawCircle(64,32,7); //中心园
//计算移动圆位置
z1 = sqrt(pow(x1,2)+pow(y1,2)); //这里的temp就是勾股定理的长边;
if(z1 > 32) //移动圆圆心在大圆外
{
OLED_DrawPoint(x1*(32.0/z1)+x0,y1*(32.0/z1)+y0); //移动圆圆心
OLED_DrawCircle(x1*(32.0/z1)+x0,y1*(32.0/z1)+y0,4); //移动圆
}
else
{
OLED_DrawPoint(x1+x0,y1+y0); //移动圆圆心
OLED_DrawCircle(x1+x0,y1+y0,4); //移动圆
}
OLED_Refresh(); //将显存中的数据传送到OLED的GRAM
}
}
这里估计有人有疑问:为什么最后到显示的时候会出现+x0,+y0这种情况,原因就是抽象坐标系转化成物理坐标系,这样才能正确的显示在OLED上