光柵圖形學——直線段的掃描轉換算法

   數學上的直線是沒有寬度、由無數個點構成的集合,顯然,光柵顯示器只能近地似顯示直線。當我們對直線進行光柵化時,需要在顯示器有限個象素中,確定最佳逼近該直線的一組象素,並且按掃描線順序,對這些象素進行寫操作,這個過程稱爲用顯示器繪製直線或直線的掃描轉換

 

一、數值微分(DDA)算法

1、算法原理

     根據直線方程y=kx+b,由兩個直線的端點(x0,y)(x1y1)可求得斜率k。可以將變量x設定初值爲x0,y初值y0。每次x步進1,同時使y步進k,可獲得表示直線的所有近似的結果集。

2、算法實現

3、補充

     這個算法只適合|k|<=1的情況。在|k|>1時,必須交換x和y的位置,y每增加1,x增加1/k。

     在這個算法中,y和k必須用浮點數來表示,每一步都要對y進行四捨五入後取整,不利於機器實現

 

 

二、中點劃線法

1、算法原理

     在直線斜率在0~1直接的情況下,設當前像素點爲(x,y),那麼它的下一個像素點就是p1(x+1,y)或者p2(x+1,y+1),若稱p1和p2的中點M(px+1,y+0.5),Q爲理想直線與x+1垂線的交點,當Q在M的下方時,p1即爲下一個像素點,否則p2即爲下一個像素點。

     下面討論中點畫線法的實現。過點(x0,y0)、(x1, y1)的直線段L的方程式爲F(x, y)=ax+by+c=0,其中,a=y0-y1, b=x1-x0, c=x0y1-x1y0,欲判斷中點M在Q點的上方還是下方,只要把M代入F(x,y),並判斷它的符號即可。爲此,我們構造判別式:

d=F(M)=F(xp+1, yp+0.5)=a(xp+1)+b(yp+0.5)+c

     當d<0時,M在L(Q點)下方,取P2爲下一個象素;

     當d>0時,M在L(Q點)上方,取P1爲下一個象素;

     當d=0時,選P1或P2均可,約定取P1爲下一個象素;

注意到d是xp, yp的線性函數,可採用增量計算,提高運算效率。

    若當前象素處於d³0情況,則取正右方象素P1(xp+1, yp),要判下一個象素位置,應計算 d1=F(xp+2, yp+0.5)=a(xp+2)+b(yp+0.5)=d+a,增量爲a。

    若d<0時,則取右上方象素P2(xp+1, yp+1)。要判斷再下一象素,則要計算d2= F(xp+2, yp+1.5)=a(xp+2)+b(yp+1.5)+c=d+a+b ,增量爲a+b。畫線從(x0, y0)開始,d的初值 d0=F(x0+1, y0+0.5)=F(x0, y0)+a+0.5b,因  F(x0, y0)=0,所以d0=a+0.5b。

    由於我們使用的只是d的符號,而且d的增量都是整數,只是初始值包含小數。因此,我們可以用2d代替d來擺脫小數,寫出僅包含整數運算的算法程序。

2、算法實現

 

 

 

三、Bresenham算法

1、算法原理

    過各行各列象素中心構造一組虛擬網格線。按直線從起點到終點的順序計算直線與各垂直網格線的交點,然後確定該列象素中與此交點最近的象素。該算法的巧妙之處在於採用增量計算,使得對於每一列,只要檢查一個誤差項的符號,就可以確定該列的所求象素。

    如圖所示,設直線方程爲yi+1=yi+k(xi+1-xi)+k。假設列座標象素已經確定爲xi,其行座標爲yi。那麼下一個象素的列座標爲xi+1,而行座標要麼爲yi,要麼遞增1爲yi+1。是否增1取決於誤差項d的值。誤差項d的初值d0=0,x座標每增加1,d的值相應遞增直線的斜率值k,即d=d+k。一旦  d≥1,就把它減去1,這樣保證d在0、1之間。當d≥0.5時,直線與垂線x=xi+1交點最接近於當前象素(xi,yi)的右上方象素(xi+1,yi+1);而當d<0.5時,更接近於右方象素(xi+1,yi)。爲方便計算,令e=d-0.5,e的初值爲-0.5,增量爲k。當e≥0時,取當前象素(xi,yi)的右上方象素(xi+1,yi+1);而當e<0時,取(xi,yi)右方象素(xi+1,yi)。

2、算法實現

     上述Bresenham算法在計算直線斜率與誤差項時用到小數與除法。可以改用整數以避免除法。由於算法中只用到誤差項的符號,因此可作如下替換:2*e*dx。那麼可以改進如下

發佈了35 篇原創文章 · 獲贊 4 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章