畫線演算法——DDA和Bresenham
阿新 • • 發佈:2019-02-01
通過學習《Hearn&Backer.Computer Graphics with OpenGL》 實現畫線演算法
一、直線方程
直線的笛卡爾斜率截距方程:
斜率為m,截距為b
在端點(x0,y0)和(xend,yend)之間的線段:
根據兩個端點的x和y值可以得到計算斜率和截距的公式:
通過沿直線的x的增量δx,可以計算出對應y的增量δy:
同理,通過沿直線y的增量δy,可以計算出對應x的增量δx:
二、DDA
DDA(digital differential analyzer)演算法,在一個座標軸上對線段以單位間隔取樣,計算另一座標軸上最靠近線段的對應整數值。
根據斜率m的取值範圍,一共可以分為4種情況:
斜率為正,且小於等於1 (1>=m>0)
此時以單位x間隔(δx=1)取樣,並計算每一個y值
斜率為正,且大於1 (m>1)
此時以單位x間隔(δy=1)取樣,並計算每一個x值
斜率為負,且大於等於-1 (-1<=m<0)
此時以單位x間隔(δx=-1)取樣,並計算每一個y值
斜率為負,且小於-1 (m<-1)
此時以單位x間隔(δy=-1)取樣,並計算每一個x值
演算法程式碼
int Round (float a)//將float型別數四捨五入轉化成int型別
{
int b = (a+0.5);
return b;
}
void lineDDA(int x0, int y0, int xEnd, int yEnd)
{
int dx,dy,steps,i;
float xInc,yInc,x=x0,y=y0;
dx = xEnd - x0;
dy = yEnd - y0;
if (fabs(dx) > fabs(dy)){
steps = fabs(dx);
}
else{
steps = fabs(dy);
}
drawPixel(Round(x), Round(y));
xInc = (float)dx / (float)steps;
yInc = (float)dy / (float)steps;
for(i=0;i<steps;i++){
x += xInc;
y += yInc;
drawPixel(Round(x), Round(y));
}
}
三、Bresenham
Bresenham演算法是一個只用整數增量進行計算,精確並且有效的光柵線生成演算法。
同DDA演算法一樣Bresenham演算法,根據直線的斜率數值,有著不同的情況
斜率為正且小於1
從端點開始,沿線路徑的畫素位置由以單位x間隔的取樣來確定
比如決定現在顯示的座標是(Xk,yk),下一個畫素的座標位置是(Xk + 1,yk)或者(Xk + 1, yk + 1) 根據哪一個點距離直線的距離更近而決定
使用dlower和dupper分別表示垂直畫素偏移:
可以得到計算相關變數的數學表示式:
比較兩個垂直畫素偏移,哪個小則下一畫素點在離得近的畫素點
此時建立一個引數pk,代表第k步時畫素偏移之差的正負值,並將m=δy/δx帶入化簡(δx和δy分別是線段兩個端點的水平和垂直移動距離):