DDA演算法和Bresenham演算法

2021-08-30 21:59:43 字數 3242 閱讀 8883

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!

dda演算法和bresenham演算法是計算機圖形學中繪製直線的兩種常用演算法。本文具體介紹一下dda演算法和bresenham演算法實現的具體思路。dda演算法主要是根據直線公式y = kx + b來推導出來的,其關鍵之處在於如何設定單位步進,即乙個方向的步進為單位步進,另乙個方向的步進必然是小於1。演算法的具體思路如下:

1. 輸入直線的起點、終點;

2. 計算x方向的間距:△x和y方向的間距:△y。

3.  確定單位步進,取maxsteps = max(△x,△y); 若△x>=△y,則x方向的步進為單位步進,x方向步進乙個單位,y方向步進△y/maxsteps;否則相反。

4. 設定第乙個點的畫素值

5. 令迴圈初始值為1,迴圈次數為maxsteps,定義變數x,y,執行以下計算:

a.  x增加乙個單位步進,y增加乙個單位步進

b.  設定位置為(x,y)的畫素值

具體實現**如下:

[cpp]view plain

copy

print?

//@brief 浮點數轉整數的巨集

#define  floattointeger(fnum)   ((fnum>0)?static_cast(fnum+0.5):static_cast(fnum-0.5))

/*!*  @brief dda畫線函式

**  @param pdc      [in]視窗dc

*  @param beginpt  [in]直線起點

*  @param endpt    [in]直線終點

*  @param linecor  [in]直線顏色

*  @return 無

*/void cdrawmsg::dda_drawline(cdc *pdc,cpoint &beginpt,cpoint &endpt,colorref linecor)  

}  //@brief 浮點數轉整數的巨集#define  floattointeger(fnum)   ((fnum>0)?static_cast(fnum+0.5):static_cast(fnum-0.5))/*!*  @brief dda畫線函式**  @param pdc      [in]視窗dc*  @param beginpt  [in]直線起點*  @param endpt    [in]直線終點*  @param linecor  [in]直線顏色*  @return 無*/void cdrawmsg::dda_drawline(cdc *pdc,cpoint &beginpt,cpoint &endpt,colorref linecor)} 

bresenham演算法是dda演算法畫線演算法的一種改進演算法。本質上它也是採取了步進的思想。不過它比dda演算法作了優化,避免了步進時浮點數運算,同時為選取符合直線方程的點提供了乙個好思路。首先通過直線的斜率確定了在x方向進行單位步進還是y方向進行單位步進:當斜率k的絕對值|k|<1時,在x方向進行單位步進;當斜率k的絕對值|k|>1時,在y方向進行單位步進。

下面以|k|<1時推導bresenham演算法的數學依據:

請看上圖,已知有一直線y = kx+b,|k|<1。我們通過斜率確定了x方向為單位步進。當x = xm時,y = ym。那麼當x 執行乙個單位步進時(即x = xm+1時),y等於ym還是等於ym+1更符合這個直線方程呢?單憑肉眼我們很難得出結論,最好的辦法當然是比較ym和ym+1和真實的方程的y值的差是多少(即yreal = k*(xm+1)+b),看看哪乙個更靠近真實的方程的y值。

我們設

dupper = ym+1 - yreal = ym+1 - k*(xm+1)+b); 表示ym+1和方**實值的差

ddown = yreal - ym = k*(xm+1)+b)- ym; 表示ym和方**實值的差

那就是我們要比較dupper和ddown的大小。假設

diff = dupper - ddown = (ym+1 - k*(xm+1)+b)) - (k*(xm+1)+b)- ym)

令△x 為線段x方向的間距,△y 為線段y方向的間距。

pm = △x* diff = 2*△x* ym-2*△y* xm-2*△y-△x*(2b-1);

那麼pm+1 = pm+2*△x*(ym+1- ym)-2*△y;

其中ym+1- ym取0還是1,取決於pm的符號。

根據等式diff = dupper - ddown = (ym+1 - k*(xm+1)+b)) - (k*(xm+1)+b)- ym)以及k = △y/△x,我們可以得出起始畫素(x0,y0)的引數p0的值:

p0 =△x-2*△y;

同理我們推出|k|>1的情況,qm = 2*xm*△y-2*ym*△x+(2b-2)*△x+△y;

qm+1 = qm+2*(xm+1-xm)*△y-2*△x;

其中xm+1-xm等於0還是1,取決於qm的符號

其中第乙個引數q0 = △y-2*△x;

明白了數學原理,我們很快能確定演算法步驟:

1. 輸入線段的起點和終點。

2. 判斷線段的斜率是否存在(即起點和終點的x座標是否相同),若相同,即斜率不存在,

只需計算y方向的單位步進(△y+1次),x方向的座標保持不變即可繪製直線。

3. 計算線段的斜率k,分為下面幾種情況處理

a. k等於0,即線段平行於x軸,即程式只需計算x方向的單位步進,y方向的值不變  

b. |k|等於1,即線段的x方向的單位步進和y方向的單位步進一樣,皆為1。直接迴圈△x次計算x和y座標。

4. 根據輸入的起點和終點的x、y座標值的大小決定x方向和y方向的單位步進是1還是-1

6. 畫出第乙個點。

7. 若|k| <1,設m =0,計算p0,如果pm>0,下乙個要繪製的點為(xm+單位步進,ym),

pm+1 = pm -2*△y;

否則要繪製的點為(xm+單位步進,ym+單位步進)

pm+1 = pm+2*△x-2*△y;

8. 重複執行第七步△x-1次;

9. 若|k| >1,設m =0,計算q0,如果qm>0,下乙個要繪製的點為(xm,ym+單位步進),

pm+1 = pm -2*△x;

否則要繪製的點為(xm+單位步進,ym+單位步進)

pm+1 = pm+2*△y-2*△x;

10. 重複執行第9步△y-1次;

給我老師的人工智慧教程打call!

DDA畫線演算法

假設給定兩個點 a x1,y1 b x2,y2 用dda實現畫直線ab的演算法如下 dx x2 x1 dy y2 y1 斜率k x,y 為需要畫的點座標,初始時 x,y x1,y1 1 dx 0 dy 0 即ab為斜線 1.1 abs dx abs dy 此時以x方向為步長 for i 0 ik d...

DDA演算法畫直線

畫直線的 適合所有斜率的直線 void cmyview linedda cdc pdc,int x0,int y0,int x1,int y1,colorref clr while y ymax return if y0 y1 水平線 while x xmax return double dx x1...

python實現DDA演算法

python實現dda演算法 dda 演算法,即數值微分法 digital differential analyzer 是一種基於直線的微分方程 線段的光柵化過程可以迴圈的讓 x方向變化乙個畫素或者讓 y方向變化乙個畫素,相應的另乙個方向變化0 個畫素或者1 個畫素得到。這樣計算直線段上的每個畫素的...