每次想寫點東西的時候,都不知道該寫點什麼,想起來在ai for game developer上看到使用bresenham演算法來做tile地形中的追逐和逃避演算法,正好可以寫點關於直線畫法的東西,這也是計算機圖形學中的基本圖元生成演算法了,還是比較簡單的。很多人都寫過,網上資料也很多,這裡也就不怕再重複一次了。
首先從最直觀的
dda演算法說起,已知過端點
p0 (x0, y0), p1(x1, y1)
的直線段l:
y = kx + b
,容易得知直線斜率為:
k = (y1-y0)/(x1-x0)
,(假設
x1 ≠
x0)。
我們假設
|k| ≤ 1
,這樣x
每增加1,y
將增加k
,並且保證
x每增加1,
y的增量不能大於
1;如果
|k|
> 1,
則應該將x和y互換。由於k是浮點數,因此演算法中需要將y捨入為int型,並圓整到最接近的位置。
演算法本身也很簡單,
c++形式的演算法實現如下:
void drawlinedda(int x0, int y0, int x1, int y1, long color) }
很明顯dda
演算法在每次迭代中的
x, y
值是上一步的值加上乙個增量獲得的,因此它是乙個增量演算法。
但是這種方法直觀,但效率太低,因為每一步需要一次浮點乘法和一次捨入運算。
bresenham
畫線演算法是使用最廣泛的直線生成演算法,
dda演算法確定下乙個點座標的方式是根據直接斜率
k得到,由於
k是浮點數,因此將不得不使用浮點運算,並將浮點數轉換整數。而
bresenham
演算法的思想則是根據誤差項來決定下乙個畫素是取正右方還是右上方(
|k| < 1
的情況),因此就不需要求斜率
k的除法運算和浮點數運算,提高了效率。
假設以確定了第i個點
pi(xi, yi)
,接下來需要確定第
i+1個點
p(x, y)
,那麼根據直線方程有:
y = yi + k;
如果delta(i+1) = y – (yi + 0.5f) < 0
,那麼表明p距
c點較近,取
c點,否則取
d點。左圖中
p將取為
d點。當
i=0時有,
delta(1) = y1 – (0+0.5) = -0.5 (k < 1)
。由此我們可以得到畫線的方法。
1) 求出k = (y1 – y0)/(x1 – x0)
,初始化
delta = -0.5;
2) 迭代x
,每次delta += k
,如果delta ≥0
則表明需要取右上方的點,使y增
1,同時使e減
1;演算法**如下:
int dx = x1- x0;
itn dy = y1- y0;
float k = dy/dx, delta = -0.5f;
for (int x = x0, y = y0; x
<=
x1; x++) }
} 考察上面的方法,依然需要計算
k和使用浮點數;好像比起
dda沒有什麼改進嘛,只不過是將浮點運算搬到了誤差項
delta
上而已,其實我們距目標已經非常近了,從演算法中可以看到只用到誤差項
delta
的符號來判斷,因此可以做如下的簡單替換:
e = delta*dx*2
現在一切水落石出了,我們已經可以消除浮點數了,也不必計算
k了。好了,下面是完整的
bresenham
演算法程式:
void drawlinebresenham(int x0, int y0, int x1, int y1, long color)
}}else }
} }
直線掃瞄 Bresenham演算法
計算機掃瞄直線原理 直線方程 y kx b y kx b 0 在第一象限畫線 x0,y0 x1,y1 當前點pi xi yi 則下一點必為p1 xi 1,yi 或 p2 xi 1,yi 1 理想直線靠近哪個點,就取那個點。推導 令f x,y y kx b,那麼理想直線上方有f 0,下方f 0.取p1...
計算機掃瞄直線Bresenham演算法
計算機掃瞄直線原理 直線方程 y kx b y kx b 0 在第一象限畫線 x0,y0 x1,y1 當前點pi xi yi 則下一點必為p1 xi 1,yi 或 p2 xi 1,yi 1 理想直線靠近哪個點,就取那個點。推導 令f x,y y kx b,那麼理想直線上方有f 0,下方f 0.取p1...
直線段掃瞄轉換演算法
數值微分 dda 法 設過端點p0 x0,y 0 p1 x1,y1 的直線段為l p0,p 1 則直線段 l的斜率dda畫線演算法程式 void ddaline int x0,int y0,int x1,int y1,int color 注意 我們這裡用整型變數color表示象素的顏色和灰度。舉例 ...