标签:
一. 任务目标
利用OpenGL,实现Bresenham算法画圆。
二. 任务要求
三. 使用平台
Windows 8.1
Visual Studio 2012
四. 实现简述
与Bresenham直线算法类似,采用的是中点画圆算法。
定义圆的一个函数
可根据f(x, y)符号判断点(x, y)的位置:
于是假设点pi(xi, yi)为当前点,下一个点要么是点E(xi + 1, yi),要么是点SE(xi + 1, yi – 1)。取两点中点M(xi + 1, yi – 1/2),带入f(x,y),根据f(M)符号来选择下一给点。
就像bresenham画直线算法一样,
设一个决策变量为
并迭代出下一个中点M 的决策变量di+1, 而di+1是根据di正负决定的:
而(要求点都是整数)
首先顺时针生成八分之一圆,然后根据对称性生成全部圆。
优化:将di+1=di+2xi+3中的乘2用位运算表示:di+1=di+(xi<<1)+3,将di+1=di+2(xi-yi)+5表示为:di+1=di+((xi-yi)<<1)+5
五. 心得体会
开始一直不明白bresenham算法跟中点midpoint算法的区别。最后总算找到答案:midpoint算法是bresenham算法的推广。两者的推理角度不同(虽然都有使用迭代),但最终得到的结果是一样的。Bresenham算法一开始的想法是用于画直线和圆,而midpoint算法更加通用。
为了便于比较,用最基本的画直线(0<k<1)来看两种算法的思路:
bresenham算法:根据当前点和直线y=f(x)(0<k<1)计算下一个点和f(x+1)的距离,有可能是 ,有可能是。迭代的决策变量是dupper-dlower,根据变量符号判断与哪个点更近来进行选择,并更新决策变量来迭代进行下一次选择。
Midpoint算法:使用了一个隐式方程f(x,y)=c0*x+c1*y+c2=0。对当前点,它的下一个中点M(,将该中点带入上方程,通过判断f()符号决定直线靠哪个点更近,并同样使用迭代的方法进行下一次判断。中点算发除了可画直线和圆,还能画椭圆、双曲线等。
还有一点体会比较深的是这种问题必须看国外论坛才能找到好的解释。
代码:
#include <gl/glut.h> #include <math.h> void myInit(void) { glClearColor(1.0f, 1.0f, 1.0f, 0.0f); glColor3f(1.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, 500.0, 0.0, 500.0); glMatrixMode(GL_MODELVIEW); } void plotCirclePixel(int cx, int cy, int x, int y) { glBegin(GL_POINTS); glVertex2i(cx + x, cy + y); glVertex2i(cx - x, cy + y); glVertex2i(cx + x, cy - y); glVertex2i(cx - x, cy - y); glVertex2i(cx + y, cy + x); glVertex2i(cx - y, cy + x); glVertex2i(cx + y, cy - x); glVertex2i(cx - y, cy - x); glEnd(); } // @param cx x coordinate of center // @param cy y coordinate of center // @param r radius of circle void bresenhamCircle(int cx, int cy, int r) { int x = 0, y = r; //initial position int d = 1 - r; //draw a point at the center of the circle glBegin(GL_POINTS); glVertex2i(cx, cy); glEnd(); while (x <= y) { plotCirclePixel(cx, cy, x, y); if (d <= 0) { d += (x << 1) + 3; } else { d += ((x - y) << 1) + 5; y--; } x++; } } void display(void) { glClear(GL_COLOR_BUFFER_BIT); bresenhamCircle(250, 250, 150); glFlush(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(100, 100); glutInitWindowSize(500, 500); glutCreateWindow("Bresenham Circle"); myInit(); glutDisplayFunc(display); glutMainLoop(); return 0; }
Assignment 3 在OpenGL中使用Bresenham算法画圆
标签:
原文地址:http://www.cnblogs.com/xiaovid/p/4455178.html