中點圓演算法
① 請利用中點圓演算法實現第一個八分圓的掃描轉換。
摘要 圓的掃描轉換-中點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畫圓演算法(要求寫清原理、誤差函數、遞推公式及最終的畫圖過程)
嗯,小紅啊!哈哈!希望快點有人幫咱解決!