dda畫線演算法
A. 分別解釋直線生成演算法DDA法、中點畫線法和Bresenham法的基本原理
DDA稱為數值微分畫線演算法,是直線生成演算法中最簡單的一種。原理相當簡單,就是最直觀的根據斜率的偏移程度,決定是以x為步進方向還是以y為步進方向。然後在相應的步進方向上,步進變數每次增加一個像素,而另一個相關坐標變數則為Yk_1=Yk+m(以x為步進變數為例,m為斜率)
假定直線斜率k在0~1之間,當前象素點為(xp,yp),則下一個象素點有兩種可選擇點P1(xp+1,yp)或P2(xp+1,yp+1)。若P1與P2的中點(xp+1,yp+0.5)稱為M,Q為理想直線與x=xp+1垂線的交點。當M在Q的下方時,則取P2應為下一個象素點;當M在Q的上方時,則取P1為下一個象素點。這就是中點畫線法的基本原理
Bresenham:過各行、各列像素中心構造一組虛擬網格線,按直線從起點到終點的順序計算直線各垂直網格線的交點,然後確定該列像素中與此交點最近的像素。該演算法的優點在於可以採用增量計算,使得對於每一列,只要檢查一個誤差項的符號,就可以確定該列所求的像素。
大概就是這樣,預知詳細,可以參考圖形學的書籍
B. dda法生成直線的基本原理是什麼為什麼說Bersenham畫圓的演算法效率較高
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)的像素值
Bresenham演算法是DDA演算法畫線演算法的一種改進演算法。本質上它也是採取了步進的思想。不過它比DDA演算法作了優化,避免了步進時浮點數運算,同時為選取符合直線方程的點提供了一個好思路。首先通過直線的斜率確定了在x方向進行單位步進還是y方向進行單位步進:當斜率k的絕對值|k|<1時,在x方向進行單位步進;當斜率k的絕對值|k|>1時,在y方向進行單位步進。
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次;
C. bresenham演算法 和 dda 演算法哪個效果好
esenham演算法的特點是:
1,不必計算直線之斜率,因此不做除法;
2,不用浮點數,只用整數;
3,只做整數加減法和乘2運算,而乘2運算可以用硬體移位實現.
Bresenham演算法速度很快,並適於用硬體實現.
DDA演算法的特點:
浮點數運算
不易硬體實現
中點畫線法特點:
只有整數運算,不含乘除法
可用硬體實現
因(X0,Y0)在直線上,所以F(X0,Y
D. DDA演算法:如何畫出斜率大於1的直線
下面是我編寫的一個在12864上畫線的函數,可以畫任意方向的線段。但先要有一個畫點函數:Lcd_PutPixel(x,y,1)。
line(int x0,int y0,int x1,int y1)
{
int i,dx,dy,e,x,y;
Lcd_PutPixel(x0,y0,1);
Lcd_PutPixel(x1,y1,1);
dx=x1-x0;
dy=y1-y0;
x=x0;
y=y0;
if(dx>0&&dy>0)
{
if(dx>dy)
{
e=-dx;
for(i=0;i<dx;i++)
{
Lcd_PutPixel(x,y,1);
x++;
e=e+2*dy;
if(e>=0)
{
y++;
e=e-2*dx;
}
}
}
else
{
e=-dy;
x=x0;
y=y0;
for(i=0;i<dy;i++)
{
Lcd_PutPixel(x,y,1);
y++;
e=e+2*dx;
if(e>=0)
{
x++;
e=e-2*dy;
}
}
}
}
if(dx<0&&dy<0)
{
dx=x0-x1;
dy=y0-y1;
if(dx>dy)
{
e=-dx;
for(i=0;i<dx;i++)
{
Lcd_PutPixel(x,y,1);
x--;
e=e+2*dy;
if(e>=0)
{
y--;
e=e-2*dx;
}
}
}
else
{
e=-dy;
for(i=0;i<dy;i++)
{
Lcd_PutPixel(x,y,1);
y--;
e=e+2*dx;
if(e>=0)
{
x--;
e=e-2*dy;
}
}
}
}
if(dx>0&&dy<0)
{
dy=y0-y1;
if(dx>dy)
{
e=-dx;
for(i=0;i<dx;i++)
{
Lcd_PutPixel(x,y,1);
x++;
e=e+2*dy;
if(e>=0)
{
y--;
e=e-2*dx;
}
}
}
else
{
e=-dy;
for(i=0;i<dy;i++)
{
Lcd_PutPixel(x,y,1);
y--;
e=e+2*dx;
if(e>=0)
{
x++;
e=e-2*dy;
}
}
}
}
if(dx<0&&dy>0)
{
dx=x0-x1;
if(dx>dy)
{
e=-dx;
for(i=0;i<dx;i++)
{
Lcd_PutPixel(x,y,1);
x--;
e=e+2*dy;
if(e>=0)
{
y++;
e=e-2*dx;
}
}
}
else
{
e=-dy;
for(i=0;i<dy;i++)
{
Lcd_PutPixel(x,y,1);
y++;
e=e+2*dx;
if(e>=0)
{
x--;
e=e-2*dy;
}
}
}
}
if(dx!=0&&dy==0)
{
if(dx>0)
{
for(i=0;i<dx;i++)
{
Lcd_PutPixel(x,y,1);
x++;
}
}
else
{
dx=x0-x1;
for(i=0;i<dx;i++)
{
Lcd_PutPixel(x,y,1);
x--;
}
}
}
if(dx==0&&dy!=0)
{
if(dy>0)
{
for(i=0;i<dy;i++)
{
Lcd_PutPixel(x,y,1);
y++;
}
}
else
{
dy=y0-y1;
for(i=0;i<dy;i++)
{
Lcd_PutPixel(x,y,1);
y--;
}
}
}
}
E. 如何用dda演算法在vc++中畫線
在你的CXXXview類上右鍵 添加成員函數類型void 函數名DDALine(參數是兩個點的xy坐標 還有顏色值RGB 一共五個參數)
再次滑鼠右鍵CXXXView添加成員變數 參數兩個點的坐標 四個參數 都是float 公有成員public
如果直接在窗體里根據已知參數話直線的話 把你的代碼放在OnDraw()函數里
如果用滑鼠操作的話 那你要添加windows消息 按快捷鍵ctrl+w 類向導找到你的CXXXView在消息里添加WM_OnLButtonDown(滑鼠按下) WM_OnMouseMove(滑鼠移動) WM_OnButtonUp(滑鼠抬起) 並設置一個BOOL變數控制畫線
在OnLButtonDown里傳遞參數point.x point.y等於初始點xy坐標 bool量=true
OnMouseMove里的point是第二坐標的xy
OnButtonUp bool量等於false
F. 與DDA演算法相比,中點畫線法有什麼優點
void DDALine(int x0,int y0,int x1,int y1,int color) {
int x;
float dx, dy, y, k;
dx = x1-x0; dy=y1-y0;
k=dy/dx,;y=y0;
for (x=x0;x< x1;x++) {
drawpixel (x, int(y+0.5), color);
y=y+k;
}
}
…… top↑
如上面代碼所示,DDA演算法中的y和k都必須用浮點數表示,並且每一步運算都要對y進行舍入取整,這不利於硬體實現。中點畫線法只包含整數變數,並且不含乘除法,因而解決了上述問題
G. 如何用java實現DDA畫線演算法,逐點畫線演算法,BRESENHAM畫線演算法
C++ JAVA 或其它語言, 他們的+-*/ if else while 這些都幾乎一樣, API和數據類型有差異, 但不影響讀懂演算法,還是去試著看懂吧,
而且我搜了一下, 網上有很多這些演算法的文字描述, 理解起來不難;
研究演算法還是自己動手吧;
LZ加油;
H. VC++怎麼實現用戶給出兩點,用DDA演算法連成線段
在你的CXXXview類上右鍵 添加成員函數類型void 函數名DDALine(參數是兩個點的xy坐標 還有顏色值RGB 一共五個參數)
再次滑鼠右鍵CXXXView添加成員變數 參數兩個點的坐標 四個參數 都是float 公有成員public
如果直接在窗體里根據已知參數話直線的話 把你的代碼放在OnDraw()函數里
如果用滑鼠操作的話 那你要添加windows消息 按快捷鍵ctrl+w 類向導找到你的CXXXView在消息里添加WM_OnLButtonDown(滑鼠按下) WM_OnMouseMove(滑鼠移動) WM_OnButtonUp(滑鼠抬起) 並設置一個BOOL變數控制畫線
在OnLButtonDown里傳遞參數point.x point.y等於初始點xy坐標 bool量=true
OnMouseMove里的point是第二坐標的xy
OnButtonUp bool量等於false
I. 如何用java實現在一個畫布上畫一個像素
DDA用來畫線而不是一個像素點。當然因為其演算法肯定要用到畫像素點的函數。
DDA稱為數值微分畫線演算法,是直線生成演算法中最簡單的一種。原理相當簡單,就是最直觀的根據斜率的偏移程度,決定是以x為步進方向還是以y為步進方向。然後在相應的步進方向上,步進變數每次增加一個像素,而另一個相關坐標變數則為Yk_1=Yk+m(以x為步進變數為例,m為斜率)
繪制一個像素點,java貌似沒有相應函數,可以用1個像素的直線代替,或者其他圖形,只要是大小一個像素,直線效率最高。
但是我覺得違背了DDA的本意。
不過,只是演示DDA的演算法,那不需要考慮畫著個像素點的方法,關鍵在於對前邊描述的演算法的表達式上