圆,最开始我们学习的时候,圆是怎么生成的?
给出圆心坐标(xc, yc)和半径r,逐点画出一个圆周的公式有下列两种:
1.直角坐标法
![](https://i-blog.csdnimg.cn/blog_migrate/4bd916c430d1a725e4a21071b320ef7b.png)
推导出:
2.极坐标法
当θ从0到π作递增时,由此式便可求出圆周上均匀分布的360个点的(x, y)坐标。
利用圆周坐标的对称性,此算法还可以简化。将圆周分为8个象限,只要将第1a象限中的圆周光栅点求出,其余7部分圆周就可以通过对称法则计算出来。
设圆的半径为r。先考虑圆心在(0, 0),并从x=0、y=r开始的顺时针方向的1/8圆周的生成过程。在这种情况下,x每步增加1,从x=0开始,到x=y结束。即有
xi+1 = xi + 1
相应的yi+1则在两种可能中选择:
yi+1 = yi 或者 yi+1 = yi-1
选择的原则是考察精确值y是靠近yi还是靠近yi-1,计算式为
令pi=d1-d2,并代入d1、d2,则有
这里我们把pi称为误差
![](https://i-blog.csdnimg.cn/blog_migrate/c96d4a60dbdd85070e914e3f9dab7703.png)
根据上面的推导,圆周生成算法思想如下:
⒈ 求误差初值,p1=3-2r,i=1,画点(0, r);
⒉ 求下一个光栅位置,其中xi+1=xi+1,如果pi<0,则yi+1=yi,否则yi+1=yi-1;
⒊ 画点(xi+1, yi+1);
⒋ 计算下一个误差,如果pi<0,则pi+1=pi+4xi+6,否则,pi+1= pi+4(xi-yi)+10;
⒌ i=i+1,如果x=y,则结束,否则返回步骤2。
代码如下:
#include "graphics.h"
#include <conio.h>
#include "windows.h"
#include <math.h>
void plot_circle_points(int xc,int yc,int x,int y,COLORREF c)//根据对称性画出另外7部分的点
{
putpixel(xc+x, yc+y, c);
putpixel(xc-x, yc+y, c);
putpixel(xc+x, yc-y, c);
putpixel(xc-x, yc-y, c);
putpixel(xc+y, yc+x, c);
putpixel(xc-y, yc+x, c);
putpixel(xc+y, yc-x, c);
putpixel(xc-y, yc-x, c);
}
void BresenhamCircle(int x1,int y1,int r,COLORREF c)//圆的生成
{
int x,y,p;
x=0;
y=r;
p=3-2*r;
while(x<y)
{
plot_circle_points(x1,y1,x,y,c);
if(p<0)
p=p+4*x+6;
else
{
p=p+4*(x-y)+10;
y-=1;
}
x+=1;
}
if(x==y)
plot_circle_points(x1,y1,x,y,c);
}
void main()
{
int gd=DETECT,gm; /*图形屏幕初始化*/
initgraph(&gd,&gm,"");
BresenhamCircle(200,200,50,LIGHTBLUE);
BresenhamCircle(300,200,50,WHITE);
BresenhamCircle(400,200,50,RED);
BresenhamCircle(250,250,50,YELLOW);
BresenhamCircle(350,250,50,GREEN);
getch();
closegraph();
}
最终效果: