一個防止直線走樣的函數

最近一直陷於繪圖過程中直線走樣的痛苦中,偶然從網上看到一個防止直線走樣的函數,拿來試了下,效果還成。

在Windows裏畫直線時,如果該直線具有一定的傾斜度,那麼直線會產生走樣(鋸齒),這要關係到光柵顯示器的顯示原理,至於具體怎麼會發生走樣,原因過於複雜微妙,每本計算機圖形學的書都有描述。下面是從網上找到的一個畫直線的算法函數,該算法具體作者不記得是誰了,我作了一些小的修改,在此提供,希望能對各位帶來方便(你無須苦苦的另去研究一個算法啦),直接拿去用即可。

這個函數優點是:對於鋸齒的修正比較逼真,使用簡單方便,直接調用即可。
同時也有缺點:函數運算量有點大,對於速度要求比較高的程序不是很好。在多線程實時通信的程序中,要求界面實時刷新,運算量太大會直接導致圖形的刷新會出現閃爍(儘管不是很明顯)。不過對於閃爍的解決也很簡單——將繪製工作放入兼容DC中,利用二次緩存來顯示就可以了。不過,如果你的繪製工作是在一張位圖上,那麼閃爍情況就不太好解決了(至少我還沒有好的辦法)。在實時通信中,這有可能會導致你的程序跟老年癡呆一樣反應緩慢。由於我的程序是放在Windows CE系統上,至於在PC上會不會出現這種情況,還有待查證(我也懶的查證)。

代碼如下:
WuLine(CDC *pDC, CPoint &pt1, CPoint &pt2, int color)
{  
      int deltax, deltay, start, finish;  
      double dx, dy, dydx;   //   fractional   parts  
      BYTE LR, LG, LB;  
   int x1,x2,y1,y2;  
   double d1,d2;  
                
      x1 = pt1.x;   y1 = pt1.y;  
      x2 = pt2.x;   y2 = pt2.y;  
      deltax = abs(x2 -x1);   //   Calculate   deltax   and   deltay   for   initialisation  
      deltay = abs(y2 -y1);  
        
      if((deltax == 0)||(deltay == 0))  
      {  
    pDC->MoveTo(x1,y1);  
    pDC->LineTo(x2,y2);  
    return;  
      }  
        
      LR =color&0x0000FF;  
      LG =(color&0x00FF00)>>8;  
      LB =(color&0xFF0000)>>16;  
      if(deltax > deltay) //   then   begin   //   horizontal   or   vertical  
      {  
  if(y2 > y1) //   determine   rise   and   run  
   dydx= -((double)deltay / deltax);  
  else  
   dydx = (double)deltay / deltax;  
  if(x2 < x1)  
  {  
   start = x2;   //   right   to   left  
   finish = x1;  
   dy = y2;  
  }  
  else  
  {  
           start = x1;   //   left   to   right  
           finish = x2;  
           dy = y1;  
           dydx = -dydx;   //   inverse   slope  
  }  
  for(int x= start; x <= finish; x++)  
  {  
    d2 = modf(dy, &d1);  
    AlphaBlendPixel(pDC,x,(int)d1,LR,LG,LB,1-d2);  
    AlphaBlendPixel(pDC,x,(int)d1+1,LR,LG,LB,d2);  
    dy = dy + dydx;   //   next   point  
  }  
   }  
      else  
      {  
        if(x2 > x1) //   determine   rise   and   run  
           dydx = -((double)deltax/deltay);  
        else  
          dydx = (double)deltax/deltay;  
        if(y2 < y1)  
  {  
   start = y2;   //   right   to   left  
   finish = y1;  
   dx = x2;  
  }  
  else  
  {  
    start = y1;   //   left   to   right  
    finish = y2;  
    dx = x1;  
    dydx = -dydx;   //   inverse   slope  
  }  
  for(int y = start; y <= finish; y++)  
  {  
    d2 = modf(dx, &d1);  
          AlphaBlendPixel(pDC, (int)d1, y, LR, LG, LB, 1 - d2);  
          AlphaBlendPixel(pDC, (int)d1 + 1, y, LR, LG, LB, d2);  
          dx = dx + dydx;  
  }  
   }  
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章