1. 程式人生 > >計算機圖形學(二)輸出圖元_3_畫線算法_2_DDA算法

計算機圖形學(二)輸出圖元_3_畫線算法_2_DDA算法

通過 程序 之間 tro 取整 xen git 方程 class

DDA算法
? ? ? ? 數字微分分析儀(digital differential analyzer, DDA)方法是一種線段掃描轉換算法。基於使用等式(3.4)或等式(3.5)計算的&x或&y。

在一個坐標軸上以單位間隔對線段取樣,從而確定還有一個坐標軸上最靠近線路徑的相應整數值。首先考慮如圖3.6所看到的的具有正斜率的線段。比如。如果斜率小於等於1。則以單位x間隔(&x = 1)取樣,並逐個計算每個y值:
技術分享圖片
? ? ? ?下標k取整數值,從第一個點1開始遞增直至最後端點。因為m能夠是0與1之間的隨意實數。所以計算出的y值必須取整。對於具有大於l的正斜率的線段,則交換x和y的位置。也就是以單位Y間隔(&y = 1)取樣,並計算每個連續的x值:


技術分享圖片


? ? ? ? 此時,每個計算出的x值要沿y掃描線舍入到近期的像素位置。?等式(3.6)和等式(3.7)基於從左端點到右端點處理線段的如果(參見圖3.6)。假如這個過程中的處理方向相反。即起始端點在右側。那麽&x = -1,而且
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??技術分享圖片
或者(當斜率大於1時)是&y = -1。而且

技術分享圖片

? ? ? ? 等式(3.6)和等式(3.9)也能夠用來計算具有負斜率的線段的像素位置。假如斜率的絕對值小於1。而且起始端點在左側。可設置&x = 1並用等式(3.6)計算y值。當起始端點在右側(具有相同斜率)時。我們可設置&x = -1而且由等式(3.8 )得到y的位置。

相同,負斜率的絕對值大於1時,能夠使用&y = -1和等式(3.9)或者&y = 1和等式(3.7)進行計算。
? ? ? ?這個算法能夠概括為以下的過程:輸人線段兩個端點的像素位置,端點位置間的水平和垂直差值賦給參數dx和dy。絕對值大的參數確定參數steps的值。從像素位置(x0, y0)開始,確定沿線段生成下一個像素位置的每一步所需的偏移量。並循環上述過程steps次。

假如dx的絕對值大於dy的絕對值,且x0小於xEnd。那麽x和y方向的增量值分別為1和m。假如x方向的變化較大,但x0大於xEnd。那麽就採用減量-1和-m來生成線段上的每個點。

在其它情況下,y方向使用單位增量(或減量),x方向使用1/m的增量(或減量)。


#include <stdlib.h>
#include <math.h>

inline int round(const float a) {return int (a + 0.5);}
void lineDDA(int x0,int y0,int xEnd,int yEnd){
     int dx = xEnd - x0, dy = yEnd - y0,steps, k ;
	float xIncrement, yIncrement,x = x0,y = y0;
	if(fabs(dx)>fabs(dr))
	   steps = fabs(dx);
	else
		steps = fabs(dy);
	xIncrement = float (dx) / float (steps);
	yIncrement = float (dy) / float (steps);
	
	setPixel (round(x),round(y));
	for(k = 0;k<steps;k++){
	    x += xIncrement;
	    y += yIncrement;
		setPixel(round(x),round(y));
	}
	

}

? ? ? ?DDA方法計算像素位置要比直接使用直線方程(3.1 )計算的速度更快

它利用光柵特性消除了直線方程(3.1 )中的乘法,而在x或Y方向使用合適的增量。從而沿線路徑逐步得到各像素的位置。但在浮點增量的連續叠加中,取整誤差的積累使得對於較長線段所計算的像素位置偏離實際線段。

而且該過程中的取整操作和浮點運算仍然十分耗時。我們能夠通過將增量m和1/m分離成整數和小數部分,從而使全部的計算都簡化為整數操作來改善DDA算法的性能。在以後將討論用整數步長計算1 /m增量的方法。在下一節中。我們考慮既能用於直線又能用於曲線的更通用的掃描線程序。

計算機圖形學(二)輸出圖元_3_畫線算法_2_DDA算法