Bresenham算法的實現思路


條件已知兩個點的坐標p1(x0,y0),p2(x1,y1)要求畫出這條直線

之后的e代表每次的誤差積累,初始值為0,可以計算出斜率為k=dy/dx=(y0-y1)/(x0-x1)

1、x為階躍步長(直線光柵化)    適用於0<k<1的情況

 即x每次增加1,但是y的坐標根據其是靠近該點所處的單元格的距離來決定,如果離上邊近則y加1,如果離下邊近則還是y

可以知道機器在畫每一個點的時候都會有誤差,則畫出的第一個點的坐標(x0,y0)也相當於是(x0,y0+e),那么可以知道下個點的坐標為紅色的p(x0+1,y0+e+k),但是機器在畫p點時,如果p點的縱坐標不是整數時,應該進行判斷這個點是接近黃點(x0+1,y0+1)還是接近藍點(x0+1,y0),最后如果接近黃點則e累積k-1,如果接近藍點則e累積k

 

在判斷條件的兩邊同乘2得:

那么程序為:

void LineB2(int x0,int y0,int x1,int y1,int color,CDC *p){
    int i,x,y,dx,dy;
    float k,e;
    dx=x1-x0;
    dy=y1-y0;
    k=(float)dy/dx;
    e=-0.5;x=x0;y=y0;
    for(i=0;i<=dx;i++){
        p->SetPixel(x,y,color);
        x=x+1;
        e=e+k;
        if(e>=0){
            y+=1;
            e=e-1;
        }
    }
}

上面的程序中e使用了多次除法運算,算法效率低。

優化

將上面的k使用dy/dx替換,並且同乘dx后,令ξ=dx*e則:

 

則程序為:

//在程序中e為上面的ξ
void
LineB3(int x0,int y0,int x1,int y1,int color,CDC *p){ int i,x,y,dx,dy; float e=0; dx=x1-x0; dy=y1-y0; e=-0.5;x=x0;y=y0; for(i=0;i<=dx;i++){ p->SetPixel(x,y,color); x=x+1; if(2*(e+dy)>=dx){ y+=1; e=e+dy-dx; }else{ e=e+dy; } } }

2、y為階躍步長(直線光柵化)    適用於k>1的情況

同上可以推出:

可以知道機器在畫每一個點的時候都會有誤差,則畫出的第一個點的坐標(x0,y0)也相當於是(x0+e,y0),那么可以知道下個點的坐標為紅色的p(x0+e+1/k,y0+1),但是機器在畫p點時,如果p點的橫坐標不是整數時,應該進行判斷這個點是接近右邊(x0+1,y0+1)還是接近藍左邊(x0,y0+1),最后如果接近右邊則e累積1、k-1,如果接近左邊則e累積1/k

優化得:

將上面的k使用dy/dx替換,並且同乘dy后,令ξ=dy*e則:

對於k<-1和-1<=k<=0可以通過對x取相反數來實現(與以上兩種情況關於y軸對稱)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM