中点圆算法

【请问中点bresenham算法画圆与bresenham算法画圆有区别吗?】 Bresenham算法画圆:Bresenham算法用来画直线非常方便,但上次也说了,Bresenham算法也可以用来显示圆和其他曲线,只需要把直线方程改成圆方程或者其他曲线的方程就行,具体的推理过程就不演示了,大体跟直线的差不多!但由推算的结果可以看出,用Bresenh...

请问中点bresenham算法画圆与bresenham算法画圆有区别吗?

Bresenham算法画圆:

Bresenham算法用来画直线非常方便,但上次也说了,Bresenham算法也可以用来显示圆和其他曲线,只需要把直线方程改成圆方程或者其他曲线的方程就行,具体的推理过程就不演示了,大体跟直线的差不多!但由推算的结果可以看出,用Bresenham算法来画圆的确是不大明智的做法,要计算的步骤太多,计算速度比专门的画圆方法慢很多!并且在斜率越大的地方像素的间距就越大,当然我们可以在画某个像素之前先判断一下这一点跟前面一点的连线的斜率,然后在适当的时候交换x、y的坐标,但这样计算量必将增加!

直接给出Bresenham画圆的代码:

#include <gl/glut.h>

#include <math.h>

#include <stdio.h>

void draw_pixel(int ix,int iy)

{

glBegin(GL_POINTS);

glVertex2i(ix,iy);

glEnd();

}

//int inline round(const float a){return int (a+0.5);}

void Bresenham(int x1,int y1,int r,double a,double b,double c)/*圆心在(x1,y1),半径为r的圆*/

{

glColor3f(a,b,c);

int dx=r;//int dy=abs(yEnd-y1);

// int p=2*dy-dx;

// int twoDy=2*dy,twoDyMinusDx=2*dy-2*dx;

int x,y,d1,d2;

/* if (x1>xEnd)

{

x=xEnd;y=yEnd;

xEnd=x1;

}

else

{

x=x1;

y=y1;

}

*/

x=x1;

y=y1+r;

draw_pixel(x1,y1);

draw_pixel(x,y);//起始点装入帧缓存,起始点是圆的最上面一点,然后按顺时针来画

while(x<=x1+dx)

{

d1=y1+sqrt(pow(r,2)-pow(x-x1,2));/* lower */

x++;

d2=2*(y1+sqrt(pow(r,2)-pow(x-x1,2)))-2*d1-1;/* lower-upper */

if(1)

{

y=d1;

draw_pixel(x,y);

draw_pixel(x,2*y1-y);

draw_pixel(2*x1-x,y);

draw_pixel(2*x1-x,2*y1-y);

}

else

{

y++;

//p+=twoDyMinusDx;

draw_pixel(x,y);

}

}

}

void display()

{

glClear(GL_COLOR_BUFFER_BIT);

Bresenham(250,250,200,0.0,0.0,1.0);

Bresenham(300,250,150,1.0,0.0,0.0);

Bresenham(200,250,150,0.0,1.0,0.0);

//Bresenham(250,300,150,0.8,0.4,0.3);

//Bresenham(250,200,150);

glFlush();

}

void myinit()

{

glClearColor(0.8,1.0,1.0,1.0);

//glColor3f(0.0,0.0,1.0);

glPointSize(1.0);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0.0,500.0,0.0,500.0);

}

void main(int argc,char **argv )

{

glutInit(&argc,argv);

glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);

glutInitWindowSize(500,500);

glutInitWindowPosition(200.0,200.0);

glutCreateWindow( CG_test_Bresenham_Circle example );

glutDisplayFunc(display);

myinit();

glutMainLoop();

}

以下为程序运行效果:

中点画圆:

用光栅画圆的不足在上次已经用实例表示的很明白了,上次画的那个圆怎么都不能算满意,虽然可以通过修改算法来得到改善,但本来计算步骤就已经很多了,交换坐标重新计算将会大大增加计算机的就是负担,为此我们采用另一种更加常用的画圆算法——中点画圆算法,之所以叫做“中点”画圆算法是由于它不是像Bresenham算法那样所绘像素不是(xk+1,yk)就是(xk+1,yk+1),而是根据这两个点的中点来判断是(xk+1,yk)还是(xk+1,yk-1)更接近于圆!

对于给定的半径r和圆心(x0,y0),我们先计算圆心在原点(0,0)的点,然后将其平移到圆心(x0,y0)处即可,跟Bresenham算法一样,我们也可以借助圆的高度对称性来减少计算机的计算步骤,在这里我们可以先计算出八分之一圆的像素点,然后根据对称性绘出其他点。这样可以大大加快画圆的速度!

跟光栅化方法一样,我们还是采用步进的方法来逐点描绘,但这里的决策参数计算方式跟Bresenham不大一样,设决策参数为p,则:

P=x2+y2-r2

对于任一个点(x,y),可以根据p的符号来判断点是在圆内还是圆外还是在圆上,这里不多说,假设我们在(xk,yk)处绘制了一个像素,下一步需要确定的是(xk+1,yk)还是(xk+1,yk-1)更接近于圆,在此代入这两个点的中点来求出决策参数:

Pk=(xk+1)2+(yk -1/2)2-r2

如果Pk<0,则yk上的像素更接近于圆,否则就是yk-1更接近于圆

同理可以推出Pk+1= Pk +2(xk+1)+(yk +12-yk2)-(yk +1-yk)+1

给出一个示例,这个圆比用Bresenham画出来的好看多了:

#include<gl\glut.h>

class screenPt

{

private:

int x,y;

public:

screenPt(){ x=y=0;}

void setCoords(GLint xCoordValue,GLint yCoordValue)

{

x=xCoordValue;

y=yCoordValue;

}

GLint getx()const

{

return x;

}

GLint gety()const

{

return y;

}

void incrementx(){x++;}

void decrementy(){y--;}

};

void draw_pixel(int xCoord,int yCoord)

{

glBegin(GL_POINTS);

glVertex2i(xCoord,yCoord);

glEnd();

}

void circleMidpoint(GLint xc,GLint yc,GLint radius)

{

screenPt circPt;

GLint p=1-radius;

circPt.setCoords(0,radius);

void circlePlotPoints(GLint ,GLint, screenPt);

circlePlotPoints(xc,yc,circPt);

while (circPt.getx()<circPt.gety())

{

circPt.incrementx();

if(p<0)

p+=2*circPt.getx()+1;

else

{

circPt.decrementy();

p+=2*(circPt.getx()-circPt.gety())+1;

}

circlePlotPoints(xc,yc,circPt);

}

}

void circlePlotPoints(GLint xc,GLint yc,screenPt circPt)//描绘八分圆各点

{

draw_pixel(xc+circPt.getx(),yc+circPt.gety());

draw_pixel(xc-circPt.getx(),yc+circPt.gety());

draw_pixel(xc+circPt.getx(),yc-circPt.gety());

draw_pixel(xc-circPt.getx(),yc-circPt.gety());

draw_pixel(xc+circPt.gety(),yc+circPt.getx());

draw_pixel(xc-circPt.gety(),yc+circPt.getx());

draw_pixel(xc+circPt.gety(),yc-circPt.getx());

draw_pixel(xc-circPt.gety(),yc-circPt.getx());

}

void display()

{

//screenPt Pt;

glClear(GL_COLOR_BUFFER_BIT);

circleMidpoint(250,250,200);

glFlush();

}

void myinit()

{

glClearColor(0.8,1.0,1.0,1.0);

glColor3f(0.0,0.0,1.0);

glPointSize(1.0);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

gluOrtho2D(0.0,500.0,0.0,500.0);

}

void main(int argc,char **argv )

{

glutInit(&argc,argv);

glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);

glutInitWindowSize(500,500);

glutInitWindowPosition(200.0,200.0);

glutCreateWindow( CG_test_中点画圆 example );

glutDisplayFunc(display);

myinit();

glutMainLoop();

}

运行效果:

继续阅读:请问中点bresenham算法画圆与bresenham算法画圆有区别吗?