畫直線演算法

2021-04-12 19:27:11 字數 4488 閱讀 4526

畫直線演算法

前段時間做了一下光柵直線生成演算法的研究,並且在vc下實現了dda

演算法、bresenham

演算法、對稱演算法、兩步演算法、及四步演算法。這裡給個總結,希望和大家交流。

主要研究的演算法主要有

dda演算法、

bresenham

演算法、對稱演算法、兩步演算法、及四步演算法,此外還對自適應多步位移碼畫線演算法進行了一定研究。其中,

dda、

bresenham

演算法都是單步畫線演算法,其它是多步畫線演算法。

dda演算法和bresenham

演算法是經典的畫線演算法,並且業已證明

bresenham

畫線演算法使用了最小的計算量,是最高效的單步畫線演算法,這裡不再對其進行說明。以下對其餘各個演算法進行必要的說明。

對稱直線生成演算法基於這樣乙個事實:直線以中點位界,其兩邊是對稱的。因而可以利用這個對稱性,對

bresenham

演算法進行改進,使得每進行一次判斷就可以生成相對於直線中點的兩個對稱點。如此以來,直線就由兩端向中間生成。演算法用

c++語言描述如下:

intx1 = m_start.m_x;//

起點x

int y1 = m_start.m_y;//

起點y

int x2 = m_end.m_x;//

終點x

int y2 = m_end.m_y;//

終點y

int dx = m_end.m_x - m_start.m_x;

int dy = m_end.m_y - m_start.m_y;

int dx2 = dx << 1;

int dy2 = dy << 1;

int e= dy2 - dx;//

決策量int half = (dx+1) >> 1;

for (int i=0; i

//始端x向加1,末端x向減1

x1++;

x2--;

e += dy2;

}

兩步畫線演算法每判斷一次就生成兩個點,這與對稱演算法相似,不同的是對稱演算法是從兩端向中間進行的,而該演算法是始終沿乙個方向進行的,一次生成2個連續的點。當斜率k滿足條件

0≤k<

1時,考慮當前點

p,如圖

1所示,直線與

ab的交點一定落在

ab區間的四等分中之一。 圖

1 下一待選點位置必在四個等分區間之一

實際上,兩個連續點可能出現的形式只有四種情況,即dd、

dx、xd和

xx。其中

x表示沿水平方向移動乙個畫素,

d表示沿對角方向移動乙個畫素,見圖2。

圖2 連續兩點可能出現的

4種形式

決策量e的初值為

e=4dy–dx

,對於pattern 1,e

的增量為

4dy-4dx;對於

pattern 2

和3,e的增量為4dy-2dx;對於pattern 4,e的增量為4dy。

演算法用c++

語言描述如下:

intx = m_start.m_x;//

起點x

int y = m_start.m_y;//

起點y

int dx = m_end.m_x - m_start.m_x;

int dy = m_end.m_y - m_start.m_y;

int dx2 = dx << 1;

int dy2 = dy << 1;

int dx4 = dx2 << 1;

int dy4 = dy2 << 1;

int inc4 = dy4 - dx4;

int inc2 = dy4 - dx2;

int e = dy4 - dx;

pdc->setpixel(x, y, color);

for (int i=0; i

// pattern 3

else

}else

// pattern 1

else

}}每計算一次e值就生成兩個點,從而提高畫線效率,但是要進行較多的判斷,所以效率提高並不明顯。

四步畫線演算法類似域兩步畫線演算法,不同的時每判斷一次,就生成四個點。如圖3所示,直線一次前進四個點的情形。

圖3 四步畫線演算法示意圖

對於四步畫線演算法,規的跟兩步演算法相似的表示方法,共有

14種形式,如圖4。

圖4 連續四點肯能出現的

14種形式 圖

4中,自底向上依次是

pattern 1

到pattern 14

,pattern 1

為***x

,pattern 2

為***d

,……,

pattern 14

為dddd。

初始時,

e=-dx

,pattern 1時e

的增量為

8dy;

pattern 2

到pattern 4時e

的增量為

8dy-2dx

;pattern 5

到pattern 8時e

的增量為

8dy-4dx

;pattern 9

到pattern 13時e

的增量為

8dy-6dx

;pattern 14時e

的增量為

8dy-8dx

。鑑於**過長,這裡不再給出。

與傳統的直線演算法不同,自適應多步位移碼畫線演算法首先將待繪製直線表達成一串由0和

1組成的位移碼,根據位移碼的特點,自適應的確定一次生成的畫素數目,從而獲得更高的繪製效率。這裡引入兩個引理: 引理

1 設有從(

x1, y1

)到(x2, y2)

的直線,

0<h=y2-y1<k=x2-x1。那麼在該直線的位移碼中,相鄰兩個1之間連續0的數目w為[(k-h)/h]或[k/h]。[a]表示對a取整。

引理2設有從(

x1, y1

)到(x2, y2)

的直線,

0<h=y2-y1<k=x2-x1。那麼在該直線的位移碼中,相鄰兩個0之間連續1的數目w為[h/(k-h)]或[k/(k-h)]。

證明略。

這裡給出自適應多步位移碼畫線演算法的偽**:

k = x2 – x1;

h = y2 – y1;

t = [(k – 1)/2] – h;

divide(h, k – h, n, tchg);

x = x1;

y = y1;

while x<= x2 do

if t<0 then

y = y +1;

xend = x+n;

while x

drawpixel(x, y);

x = x +1;

end while

t = t+tchg;

else

t = t – h;

drawpixel(x, y);

end if

x = x +1;

end while

從理論而言,該演算法根據直線斜率自適應地選擇乙個步長,

以一次判斷生成多個取樣點的方式對直線進行繪製,從而大大提供了繪製效率。但是實際上,連續兩個1(

0)中間0(

1)的個數雖然只在兩個整數上選擇,但是到底在哪一步是哪乙個難以判斷,所以實現起來並不容易,而且目前尚未有解決方法。

bresenham

對稱 兩步 四步

加法 1

0.5

1

1 比較

2

1

1.5

1.3

加法和比較 3

1.5

2.5

2.3 乘法

2

3

4

6

上表給出平均每步所進行的加法次數和比較次數,乘除次數是整演算法總共的次數。

dda演算法未在表中給出,它與

bresenham

相似,但使用了多次浮點乘除運算和取整運算,效率明顯低於其它演算法。

bresenham

與其它演算法相比,加法步驟相當(對稱演算法除外),但比較次數較多。理論上而言,後面的演算法效率較高。但是應該注意到多步演算法,如兩步和四步演算法,在進行迴圈之前要做很多的初始化工作,而且乘除次數大於

bresenham

演算法。在進行較短直線繪製時,效率反而不如

bresenham

演算法快。

(一些演算法的源程式較長,這裡未給出。)

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...

dda演算法畫直線 再談繪製直線

之前已經在 從零開始計算機圖形學 之七畫線 寫過繪製直線了,現在再來仔細的看一下這個問題。tinyrenderer github.com void line int x0,int y0,int x1,int y1,tgaimage image,tgacolor color 這裡的問題有兩個 t取大了...

Bresenham快速畫直線演算法

一 演算法原理簡介 演算法原理的詳細描述及部分實現可參考 假設以 x,y 為繪製起點,一般情況下的直觀想法是先求m dy dx 即x每增加1,y的增量 然後逐步遞增x,設新的點為x1 x j,則y1 round y j m 可以看到,這個過程涉及大量的浮點運算,效率上是比較低的 特別是在嵌入式應用中...