OpenGL——使用Bresenham算法绘制圆
Bresenham算法是計算機圖形學中為了“顯示器(屏幕或打印機)系由像素構成”的這個特性而設計出來的算法,使得在求直線各點的過程中全部以整數來運算,因而大幅度提升計算速度。——摘自 “百度百科”。
Bresenham算法繪制直線就不贅述了,大家看一看算法簡介就能很好理解與實踐。
稍稍麻煩一點的就是用該算法繪制圓了,算法思想其實是一樣的,并沒有太大改變。
算法核心:
????
組合以上式子,當Dupper-Dlower<0時,取上點;當Dupper-Dlower>0時,取下點;否則任意。
?
實驗過程中,我使用了兩種方法:① 畫點法 ② 連線法。
一、 畫點法:
畫點法就是僅僅用OpenGL繪制點。可以選擇按照圓的軌跡畫整個圓,當然這樣的算法要比較慢,而且要注意分段函數的增減性。
???? 我使用的是對稱法,利用圓的對稱性質,僅僅計算1/8的圓弧的點(當然算1/4也可以),其余的點均用對稱性直接繪制。如下圖所示:
??????????
代碼如下:
1 /* 2 * Draw Circle by Bresenham Algorithm 3 * @para < xc, yc - 圓心: (xc, yc) > 4 * @para < r - 半徑 > 5 * @para < deltaX - 坐標系每個小格的間距,用于控制精細度 > 6 */ 7 void drawCircle_Bresenham(GLfloat xc, GLfloat yc, GLfloat r, const GLfloat deltaX) { 8 GLfloat xi = - r, yi = 0; /* 圓上點 (xi, yi) */ 9 GLfloat du_l; /* upper - lower */ 10 glBegin(GL_POINTS); 11 while (abs(xi) >= abs(yi)) { 12 // 根據圓的八向對稱,只計算其中八分之一的點,然后對稱得出其他點 13 // 假設圓心在原點,先求點,再平移 14 glVertex2f(xc + xi, yc + yi); 15 glVertex2f(xc - xi, yc + yi); 16 glVertex2f(xc + xi, yc - yi); 17 glVertex2f(xc - xi, yc - yi); 18 glVertex2f(xc + yi, yc + xi); 19 glVertex2f(xc - yi, yc + xi); 20 glVertex2f(xc + yi, yc - xi); 21 glVertex2f(xc - yi, yc - xi); 22 23 xi += deltaX; // 下一個x 24 float yi_1 = sqrt(pow((GLfloat)r, 2) - pow((GLfloat)xi, 2)); // yi+1 25 du_l = 2 * (GLfloat)yi + deltaX - 2 * yi_1; 26 yi = (du_l <= 0) ? (int)yi_1 + deltaX : (int)yi_1; 27 } 28 glEnd(); 29 glFlush(); 30 } 結果如圖(半徑150,圓心在原點,橫坐標間隔為0.001):
?
二、 畫線法:
根據圓弧四個象限的增減性和凹凸性的不同,分別繪制四段曲線,組合成一個圓。核心算法和第一種方法相同。
1 const GLint FIRST_QUA = 1; // 第一象限 2 const GLint SECOND_QUA = 2; // 第二象限 3 const GLint THIRD_QUA = 3; 4 const GLint FOURTH_QUA = 4; 5 6 /* 7 * 根據起點和終點繪制弧(畫線法) 8 * @para < deltaX - 坐標系每個小格的間距,用于控制精細度 > 9 * @para < Quadrant - 象限 > 10 */ 11 void setPixel(GLfloat startX, GLfloat endX, GLfloat startY, GLfloat xc, GLfloat yc, GLfloat r, GLfloat deltaX, GLint Quadrant) { 12 GLfloat du_l; /* upper - lower */ 13 int inc = (Quadrant % 2 == 1) ? -1 : 1; 14 int nag = (Quadrant > 2) ? -1 : 1; 15 glBegin(GL_LINE_STRIP); 16 while (startX <= endX) { 17 // 假設圓心在原點,先求點,再平移 18 glVertex2f(startX + xc, startY + yc); 19 startX += deltaX; 20 float yi_1 = nag * sqrt(pow((GLfloat)r, 2) - pow((GLfloat)startX, 2)); // yi+1 21 du_l = 2 * (GLfloat)startY + inc * deltaX - 2 * yi_1; 22 startY = (du_l <= 0) ? (int)yi_1 + deltaX : (int)yi_1; 23 } 24 glEnd(); 25 } 26 27 /* 28 * Bresenham 算法(畫線法) 29 * @para < xc, yc - 圓心(xc, yc) > 30 * @para < r - 半徑 > 31 */ 32 void drawCircle_Bresenham_line(GLfloat xc, GLfloat yc, GLfloat r, GLfloat deltaX) { 33 setPixel(-r, 0, 0, xc, yc, r, deltaX, SECOND_QUA); // 左上半 34 setPixel(0, r, r, xc, yc, r, deltaX, FIRST_QUA); // 右上半 35 setPixel(0, r , -r, xc, yc, r, deltaX, FOURTH_QUA); // 右下半 36 setPixel(-r, 0, 0, xc, yc, r, deltaX, THIRD_QUA); // 左下半 37 glFlush(); 38 }
結果如圖(半徑150,圓心在原點,橫坐標間隔為0.001):
?
?
轉載于:https://www.cnblogs.com/xulf/p/4357875.html
總結
以上是生活随笔為你收集整理的OpenGL——使用Bresenham算法绘制圆的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 文本框灰色文字提示,鼠标点击文字消失
- 下一篇: sublime text3 注册码,亲测