中点圆算法
① 请利用中点圆算法实现第一个八分圆的扫描转换。
摘要 圆的扫描转换-中点Bresenham算法_做自己喜欢的事是多么幸福的一件事呀!-CSDN博客 https://blog.csdn.net/weixin_44350205/article/details/105572494
② 图形学中的中点画线法与Bresenham算法画线的区别
个人认为最关键的区别就是那个决策参数的计算方式!
在Bresenham算法中,假设我们在(x0,y0)处画了一个点,那我们就要决定下一个点是在(x0+1,y0)还是在(x0+1,y0+1)处画,这两个点一般都不在直线上,我们要计算这两个点离直线有多远,分别设两个点离直线的距离为p1、p2,然后决策参数就是p=p2-p1,再根据p的符号来判断选择哪个点
至于中点法,我没有用它来画过直线,只用来画过圆(自我感觉画圆用这个算法比Bresenham算法要好很多),但原理应该差不多!
在中点算法中,决策参数的就是方式就是圆的方程(换成直线就是直线的方程了),比如要画x^2+y^2=r^2的圆,那决策参数p=x^2+y^2-r^2,然后就不是代入上面找到的两个点直接代进去,而是代这两个点的中点进去,求出p的值,根据p的符号来判断那个中点是在圆上、圆内还是圆外,再进一步决定选择绘哪个点!
具体的计算过程没办法在这里完整演示,但个人认为不同之处还是在于决策参数的选择与计算
③ 请问中点bresenham算法画圆与bresenham算法画圆有区别吗
Bresenham算法画圆:
Bresenham算法用来画直线非常方便,但上次也说了,Bresenham算法也可以用来显示圆和其他曲线,只需要把直线方程改成圆方程或者其他曲线的方程就行,具体的推理过程就不演示了,大体跟直线的差不多!但由推算的结果可以看出,用Bresenham算法来画圆的确是不大明智的做法,要计算的步骤太多,计算速度比专门的画圆方法慢很多!并且在斜率越大的地方像素的间距就越大,当然我们可以在画某个像素之前先判断一下这一点跟前面一点的连线的斜率,然后在适当的时候交换x、y的坐标,但这样计算量必将增加!
直接给出Bresenham画圆的代码:
#include<gl/glut.h>
#include<math.h>
#include<stdio.h>
voiddraw_pixel(intix,intiy)
{
glBegin(GL_POINTS);
glVertex2i(ix,iy);
glEnd();
}
//intinlineround(constfloata){returnint(a+0.5);}
voidBresenham(intx1,inty1,intr,doublea,doubleb,doublec)/*圆心在(x1,y1),半径为r的圆*/
{
glColor3f(a,b,c);
intdx=r;//intdy=abs(yEnd-y1);
//intp=2*dy-dx;
//inttwoDy=2*dy,twoDyMinusDx=2*dy-2*dx;
intx,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);
}
}
}
voiddisplay()
{
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();
}
voidmyinit()
{
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);
}
voidmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(200.0,200.0);
glutCreateWindow("CG_test_Bresenham_Circleexample");
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<glglut.h>
classscreenPt
{
private:
intx,y;
public:
screenPt(){x=y=0;}
voidsetCoords(GLintxCoordValue,GLintyCoordValue)
{
x=xCoordValue;
y=yCoordValue;
}
GLintgetx()const
{
returnx;
}
GLintgety()const
{
returny;
}
voidincrementx(){x++;}
voiddecrementy(){y--;}
};
voiddraw_pixel(intxCoord,intyCoord)
{
glBegin(GL_POINTS);
glVertex2i(xCoord,yCoord);
glEnd();
}
voidcircleMidpoint(GLintxc,GLintyc,GLintradius)
{
screenPtcircPt;
GLintp=1-radius;
circPt.setCoords(0,radius);
voidcirclePlotPoints(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);
}
}
voidcirclePlotPoints(GLintxc,GLintyc,screenPtcircPt)//描绘八分圆各点
{
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());
}
voiddisplay()
{
//screenPtPt;
glClear(GL_COLOR_BUFFER_BIT);
circleMidpoint(250,250,200);
glFlush();
}
voidmyinit()
{
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);
}
voidmain(intargc,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算法;
多边形迫近法—圆与椭圆
...
推导出圆弧的增量算法的表达式:
缺点:所产生的圆是不封闭的,且该圆的半径有不断增大的趋势。
⑤ C++中,中点画圆算法,编译时出现错误 ,哪儿错了
变量y0不是yo
⑥ 计算机图形学 问题 中点圆算法和扫描线算法
写个文档解释一下。
⑦ 1.请根据中点圆生成算法思想,对圆x2+y2=r2,推出第一象限中从y=0到 y = x 这段
R2)*R2=2
求出R2=10
因为U=6,u2的变化范围0~2,U=U1+U2,所以U1的变化范围是4~6
⑧ 试推导任意圆的中点Bresenham画圆算法(要求写清原理、误差函数、递推公式及最终的画图过程)
嗯,小红啊!哈哈!希望快点有人帮咱解决!