本帖最后由 ALTIUM2 于 2015-9-2 19:21 编辑
------------------------------------------------------------------------------------------------------------- 每天解决一个问题7:UI中的八分画圆法
还记得上学时,老师布置任务做课程设计,我呢设计的题目就是电子指南针。方向计算这些都木有问题,但是想要显示一个圆形的方向盘时却遇到了些问题。界面采用的是液晶显示屏240*320彩色,采用的是ST51单片机,可是在显示圆形的时候却速度非常的慢,不能忍受啊(那时也不懂UI设计,知道的也太少,就用sin,cos函数这么计算着,后来表哥让我看看8分画圆法,顿时干嚼这个世界真的好牛X啊!)
现在都流行各种库函数,各种调用,各种移植,可是库函数中的精髓却很少有人深究!
进入主题……
(一)想一想,如何画圆 a.第一印象 正弦公式 sin (A) = y / R; 余弦公式 cos (A) = x / R; 既然R一定,那我就从0度~360度画一遍不久好了吗?
嗯!会不会立马的想法跟我一样呢! 所以我第一次就是按这种方法把圆给画出来了,用单片机求正弦值…… 这个真心慢,吃过亏,再也不会了……
b.再想一想,画圆有什么好方法
圆是对称的,显然,我们只需要知道了圆上的一个点的坐标 (x, y) ,利用八对称性,我们马上就能得到另外七个对称点的坐标。
所以最终话好一个圆,实际只要画8分之一,也就所谓的8分画圆法.
(二)如何在我们的显示屏画圆
我们的显示屏,实际都是一颗颗像素点,并不会是完美的曲线。
下图最左边的就是我们肉眼看到的,右边呢实际显示的点阵效果。
也就是说我们只要在局部尽可能的按照曲线走下去,远看就是完美的弧线了,最后圆也就出来了。
(三)Bresenham画圆算法
Bresenham画圆算法又称中点画圆算法,与Bresenham 直线算法一样,其基本的方法是利用判别变量来判断选择最近的像素点,判别变量的数值仅仅用一些加、减和移位运算就可以计算出来。为了简便起见,考虑一个圆心在坐标原点的圆,而且只计算八分圆周上的点,其余圆周上的点利用对称性就可得到。
(四)程序代码
void Round( uchar X, uchar Y, uchar R, unsigned int color )
{
int a, b, num;
a = 0;
b = R;
while(a<=b) // 1/8圆即可
{
Put_pixel(X + a, Y - b,color); // 0~1
Put_pixel(X - a, Y - b,color); // 0~7
Put_pixel(X - a, Y + b,color); // 4~5
Put_pixel(X + a, Y + b,color); // 4~3
Put_pixel(X + b, Y + a,color); // 2~3
Put_pixel(X + b, Y - a,color); // 2~1
Put_pixel(X - b, Y - a,color); // 6~7
Put_pixel(X - b, Y + a,color); // 6~5
a++;
num = (a * a + b * b) - R*R;
if(num >=0)
{
b--;
a--;
}
}
}
也许这个程序看似不难,但确是UI设计的必经之路,这里处处是智慧的结晶!

|