Bresenham演算法畫圓

2021-05-22 10:19:44 字數 2781 閱讀 2161

下面先簡要介紹常用的畫圓演算法(bresenham演算法),然後再具體闡述筆者對該演算法的改進。

乙個圓,如果畫出了圓上的某一點,那麼可以利用對稱性計算餘下的七段圓弧:plot(x,y),plot(y,x),plot(y,-x),plot(x,-y),plot(-x,-y),plot(-y,-x),plot(-y,x),plot(-x,y)。

1、bresenham 畫圓演算法。bresenham演算法的主要思想是:以座標原點(0,0)為圓心的圓可以通過0度到45°的弧計算得到,即x從0增加到半徑,然後利用對稱性計算餘下的七段圓弧。當x從0增加到時,y從r遞減到。

設圓的半徑為r,則圓的方程為:

f(x,y)=(x+1)2+y2-r2=0                                   (1)

假設當前列(x=xi列)中最接近圓弧的畫素已經取為p(xi,yi),根據第二卦限1/8圓的走向,下一列(x=xi+1列)中最接近圓弧的畫素只能在p的正右方點h(xi+1,yi)或右下方點l(xi+1,yi-1)中選擇,如圖1所示。bresenham畫圓演算法採用點t(x,y)到圓心的距離平方與半徑平方之差d(t)作為選擇標準,即

d(t)=(x+1)2+y2-r2                                         (2)

通過比較h、l兩點各自對實圓弧上點的距離大小,即根據誤差大小來選取,具有最小誤差的點為繪製點。根據公式(2)得:

對h(xi+1,yi)點有:d(h)=(xi+1)2+yi2-r2;

對l(xi+1,yi-1)點有:d(l)=(xi+1)2+(yi-1)2-r2;

根據bresenham畫圓演算法,則選擇的標準是:

如果|d(h)|<|d(l)|,那麼下一點選取h(xi+1,yi);

如果|d(h)|>|d(l)|,那麼下一點選取l(xi+1,yi-1);

如果|d(h)|=|d(l)|,那麼下一點可以取l(xi+1,yi-1),也可以選取h(xi+1,yi),我們約定選取h(xi+1,yi)。

圖1  bresenham畫圓演算法點的選取

綜合上述情況,得:

當|d(h)|>|d(l)|時,選取l點(xi+1,yi-1)為繪製點座標;

當|d(h)|<|d(l)|時,選取h點(xi+1,yi)為繪製點座標。

然後將選取的點座標作為當前座標,重複上述過程直至xi=或者yi=為止,(xi,yi)的初始值為(0,r)。

以上便是bresenham演算法的主要思想,但是上述演算法是在乙個假設下:以座標原點(0,0)為圓心。該假設實際上只是為了方便演算法的研究。但在實際嵌入式lcd顯示裝置中,往往圓心座標不是(0,0)點,而是以左上角為(0,0)點,這樣就使得在實際運用中,需要對這個演算法做很大的改進。

另外,如果完全按照bresenham畫圓演算法,那麼就會涉及到浮點運算,這使得嵌入式程式設計十分煩瑣,因為本系統中所有資料都是整型的,因此在這方面也要作一定的改進。下面根據本系統中嵌入式硬體特點和資料結構得特點,對這個演算法進行改進。

2、改進的bresenham畫圓演算法。先假設起始點為(r,0),令pi=(xi,yi)為當前的一點,那麼我們就需要在ti=(xi,yi+1)和si=(xi-1,yi+1)中選取一點,如圖2所示。

圖2 嵌入式lcd畫圓時點的選取

設(xi-1/2+e,yi+1)為s和t之間圓上的點,e是s、t中點到圓上點的誤差,帶入圓的方程(1)得:

f(xi-1/2+e,yi+1)=(xi-1/2+e)2+(yi+1)2-r2=f(xi-1/2,yi+1)+2(xi-1/2)e+e2=0   (3)

在式(3)中,令

di="f"(xi-1/2,yi+1)=-2(xi-1/2)e-e2                                    (4)

如果e<0,那麼di>0,因此選擇s=(xi-1,yi+1),根據(3)與(4)得:

di+1=f(xi-1-1/2,yi+1+1)=di-2(xi-1)+2(yi+1)+1=di+2(yi+1-xi+1)+1         (5)

如果e30,那麼di£0,因此選擇t=(xi,yi+1),根據(3)與(4)得:

di+1=f(xi-1/2,yi+1+1)=di+2yi+1+1                                  (6)

起始點是(r,0)的時候,根據(4)得di的初始值d0就是:

d0=f(r-1/2,0+1)=(r-1/2)2+1-r2=5/4-r=1-r(由於程式設計中所用資料型別均為整型,故取1-r)。

綜合上述情況,得:

當選取s=(xi-1,yi+1)時,那麼di+1=di+2(yi+1-xi+1)+1;

當選取t=(xi,yi+1)時,那麼di+1=di+2yi+1+1;

然後將選取的點座標作為當前座標,重複上述過程直至x=y,而不是xi=或者yi=,這樣就可以不用作浮點數計算了。

本專案中的lcd畫素為640×480點陣,並且資料是八位的,當橫座標和縱座標超過255時,那麼資料就不能一次傳送成功,因此需要通過位元組操作來設定高位元組,然後再傳送低位元組。因此,每次畫圓上的點時要傳送的引數至少是六個,圓心座標是四個(因為要考慮圓心座標可能大於255,因此要對其圓心座標設定高、低位元組),另外兩個是圓上的點相對於圓心的座標,但是最後要畫乙個點,需要四個引數,即改進的畫圓演算法為六個引數輸入,四個引數輸出。

用c語言在嵌入式lcd上實現改進的bresenham畫圓演算法的部分**如下:

void midbresenhamcircle(int r)  /*改進的bresenham演算法畫圓程式*/

x++;

delay(900000);

}  /* while */

基於Bresenham演算法畫圓

bresenham演算法畫圓思想與上篇 bresenham演算法畫線段 思想是一致的 畫圓x 2 y 2 r 2 將他分為8個部分,如上圖 1.只要畫出1中1 8圓的圓周,剩下的就可以通過對稱關係畫出這個圓 x變化從0 r 那為什麼不採用從 r r呢,y sqrt r 2 x 2 dy dx x s...

中點Bresenham畫圓

這裡不仔細講原理,只是把我寫的演算法發出來,跟大家分享下,如果有錯誤的話,還請大家告訴我,如果寫的不好,也請指出來,一起討論進步。演算法步驟 1 輸入圓的半徑r。2 計算初始值d 1 r,x 0 y r。3 繪製點 x,y 及其在八分圓中的另外7個對稱點。4 判斷d的符號,若d 0,則先將d更新為d...

利用Bresenham演算法畫圓和直線

利用bresenham演算法,從零開始實現在矩陣中畫圓和直線,效果如下 close all clear all clc create image reactangle img ones 100 200 figure name original image imshow img draw line h...