算法系列之十三:橢圓的生成算法

        橢圓和直線、圓一樣,是圖形學領域中的一種常見圖元,橢圓的生成算法(光柵轉換算法)也是圖形學軟件中最常見的生成算法之一。在平面解析幾何中,橢圓的方程可以描述爲(x – x0)2 / a2+ (y – y0)2 / b2 = 1,其中(x0, y0)是圓心座標,ab是橢圓的長短軸,特別的,當(x0, y0)就是座標中心點時,橢圓方程可以簡化爲x2 / a2 + y2 / b2 = 1。在計算機圖形學中,橢圓圖形也存在在點陣輸出設備上顯示或輸出的問題,因此也需要一套光柵掃描轉換算法。爲了簡化,我們先考慮圓心在原點的橢圓的生成,對於中心不是原點的橢圓,可以通過座標的平移變換獲得相應位置的橢圓。

        在進行掃描轉換之前,需要了解一下橢圓的對稱性,如圖(1)所示:

圖(1)橢圓的對稱性

 

中心在原點。焦點在座標軸上的標準橢圓具有X軸對稱、Y軸對稱和原點對稱特性,已知橢圓上第一象限的P點座標是(x, y),則橢圓在另外三個象限的對稱點分別是(x, -y)(-x, y)(-x, -y)。因此,只要畫出第一象限的四分之一橢圓,就可以利用這三個對稱性得到整個橢圓。

        在光柵設備上輸出橢圓有很多種方法,可以根據直角平面座標方程直接求解點座標,yekeyii利用極座標方程求解,但是因爲涉及到浮點數取整,效果都不好,一般都不使用直接求解的方式。本文就介紹幾種計算機圖形學中兩種比較常用的橢圓生成方法:中點畫橢圓算法和Bresenham橢圓生成算法。

 

1、  中點畫橢圓法

 

        中點在座標原點,焦點在座標軸上(軸對齊)的橢圓的平面集合方程是:

 

x2 / a2 + y2 / b2 = 1,也可以轉化爲如下非參數化方程形式:

F(x, y) = b2x2 + a2y2 - a2b2 = 0                  (方程 1

 

無論是中點畫線算法、中點畫圓算法還是本節要介紹的中點畫橢圓算法,對選擇x方向像素Δ增量還是y方向像素Δ增量都是很敏感的。舉個例子,如果某段圓弧上,x方向上增量+1個像素時,y方向上的增量如果 < 1,則比較適合用中點算法,如果y方向上的增量 > 1,就會產生一些跳躍的點,最後生成的光柵位圖圓弧會有一些突變的點,看起來好像不在圓弧上。因此,對於中點畫圓弧算法,要區分出橢圓弧上哪段Δx增量變化顯著,哪段Δy增量變化顯著,然後區別對待。由於橢圓的對稱性,我們只考慮第一象限的橢圓圓弧,如圖(2)所示:

圖(2)第一象限橢圓弧示意圖

 

定義橢圓弧上某點的切線法向量N如下:

對方程1分別求x偏導和y偏導,最後得到橢圓弧上(x,y)點處的法向量是(2b2x, 2a2y)。dy/dx = -1的點是橢圓弧上的分界點。此點之上的部分(橙褐色部分)橢圓弧法向量的y分量比較大,即:2b2(x + 1) < 2a2(y – 0.5);此點之下的部分(藍紫色部分)橢圓弧法向量的x分量比較大,即:2b2(x + 1) > 2a2(y – 0.5)

        對於圖(2)中橙褐色標識的上部區域,y方向每變化1個單位,x方向變化大於一個單位,因此中點算法需要沿着x方向步進畫點,x每次增量加1,求y的值。同理,對於圖(2)中藍紫色標識的下部區域,中點算法沿着y方向反向步進,y每次減1,求x的值。先來討論上部區域橢圓弧的生成,如圖(3)所示:

圖(3)中點畫橢圓算法對上部區域處理示意圖

 

假設當前位置是P(xi, yi),則下一個可能的點就是P點右邊的P1(xi+1, yi)點或右下方的P2(xi+1, yi-1)點,取捨的方法取決於判別式didi的定義如下:

 

di = F(xi+1, yi-0.5) = b2(xi+1)2 + a2(yi-0.5)2 – a2b2

 

di < 0,表示像素點P1P2的中點在橢圓內,這時可取P1爲下一個像素點。此時xi+1 = xi + 1yi+1 = yi,代入判別式di得到di+1

 

di+1 = F(xi+1+1, yi+1-0.5) = b2(xi+2)2 + a2(yi-0.5)2 – a2b2 = di + b2(2xi + 3)

 

計算出di的增量是b2(2xi + 3)。同理,若di >= 0,表示像素點P1P2的中點在橢圓外,這時應當取P2爲下一個像素點。此時xi+1 = xi + 1yi+1 = yi - 1,代入判別式di得到di+1

 

di+1 = F(xi+1+1, yi+1-0.5) = b2(xi+2)2 + a2(yi-1.5)2 – a2b2 = d1 + b2(2xi+3) + a2(-2yi+2)

 

計算出di的增量是b2(2xi+3)+a2(-2yi+2)。計算di的增量的目的是減少計算量,提高算法效率,每次判斷一個點時,不必完整的計算判別式di,只需在上一次計算出的判別式上增加一個增量即可。

        接下來繼續討論下部區域橢圓弧的生成,如圖(4)所示:

圖(4)中點畫橢圓算法對下部區域處理示意圖

 

假設當前位置是P(xi, yi),則下一個可能的點就是P點左下方的P1(xi -1, yi-1)點或下方的P2(xi, yi-1)點,取捨的方法同樣取決於判別式didi的定義如下:

 

di = F(xi+0.5, yi-1) = b2(xi+0.5)2 + a2(yi-1)2 – a2b2

 

di < 0,表示像素點P1P2的中點在橢圓內,這時可取P2爲下一個像素點。此時xi+1 = xi + 1yi+1 = yi - 1,代入判別式di得到di+1

 

di+1 = F(xi+1+0.5, yi+1-1) = b2(xi+1.5)2 + a2(yi-2)2 – a2b2 = di + b2(2xi+2)+a2(-2yi+3)

 

計算出di的增量是b2(2xi+2)+a2(-2yi+3)。同理,若di >= 0,表示像素點P1P2的中點在橢圓外,這時應當取P1爲下一個像素點。此時xi+1 = xiyi+1 = yi - 1,代入判別式di得到di+1

 

di+1 = F(xi+1+0.5, yi+1-1) = b2(xi+0.5)2 + a2(yi-2)2 – a2b2 = d1 + a2(-2yi+3)

 

計算出di的增量是a2(-2yi+3)

        中點畫橢圓算法從(0, b)點開始,第一個中點是(1, b – 0.5),判別式d的初始值是:

 

d0 = F(1, b–0.5) = b2 + a2(-b+0.25)

 

上部區域生成算法的循環終止條件是:2b2(x + 1) >= 2a2(y – 0.5),下部區域的循環終止條件是y = 0,至此,中點畫橢圓算法就可以完整給出了:

20 void MP_Ellipse(int xc , int yc , int a, int b)

21 { 

22     double sqa = a * a;

23     double sqb = b * b;

24 

25     double d = sqb + sqa * (-b + 0.25);

26     int x = 0;

27     int y = b;

28     EllipsePlot(xc, yc, x, y);

29     while( sqb * (x + 1) < sqa * (y - 0.5))

30     {    

31         if (d < 0)

32         {

33             d += sqb * (2 * x + 3);

34         }

35         else 

36         { 

37             d += (sqb * (2 * x + 3) + sqa * (-2 * y + 2));

38             y--;   

39         }

40         x++; 

41         EllipsePlot(xc, yc, x, y);

42     }

43     d = (b * (x + 0.5)) * 2 + (a * (y - 1)) * 2 - (a * b) * 2;

44     while(y > 0)

45     { 

46         if (d < 0)

47         {

48             d += sqb * (2 * x + 2) + sqa * (-2 * y + 3);

49             x++; 

50         }

51         else 

52         {

53             d += sqa * (-2 * y + 3); 

54         }

55         y--;

56         EllipsePlot(xc, yc, x, y);

57     }

58 }

EllipsePlot()函數利用橢圓的三個對稱性,一次完成四個對稱點的繪製,因爲簡單,此處就不再列出代碼。

 

2、  Bresenham算法

 

        中點畫橢圓法中,計算判別式d使用了浮點運算,影響了橢圓的生成效率。如果能將判別式規約到整數運算,則可以簡化計算,提高效率。於是人們針對中點畫橢圓法進行了多種改進,提出了很多種中點生成橢圓的整數型算法,Bresenham橢圓生成算法就是其中之一。

        在生成橢圓上部區域時,以x軸爲步進方向,如圖(5-a)所示:

圖(5Bresenham橢圓生成算法判別式

 

x每步進一個單位,就需要在判斷y保持不變還是也步進減1bresenham算法定義判別式爲:

 

D = d1 – d2

 

如果D < 0,則取P1爲下一個點,否則,取P2爲下一個點。採用判別式D,避免了中點算法因y-0.5而引入的浮點運算,使得判別式規約爲全整數運算,算法效率得到了很大的提升。根據橢圓方程,可以計算出d1d2分別是:

 

d1 = a2(yi2 – y2)

d2 = a2(y2 – yi+12)

 

(0, b)作爲橢圓上部區域的起點,將其代入判別式D可以得到如下遞推關係:

 

Di+1 = Di + 2b2(2xi + 3)                     (Di < 0)

Di+1 = Di + 2b2(2xi + 3) – 4a2(yi - 1)           (Di >= 0)

D0 = 2b2 – 2a2b + a2

 

在生成橢圓下部區域時,以y軸爲步進方向,如圖(5-b)所示,y每步進減一個單位,就需要在判斷x保持不變還是步進加一個單位,對於下部區域,計算出d1d2分別是:

 

d1 = b2(xi+12 – x2)

d2 = b2(x2 – xi2)

 

(xp, yp)作爲橢圓下部區域的起點,將其代入判別式D可以得到如下遞推關係:

 

Di+1 = Di – 4a2(yi - 1) + 2a2                     (Di < 0)

Di+1 = Di + 2b2(xi + 1) – 4a2(y - 1) + 2a2 + b2          (Di >= 0)

D0 = b2(xp + 1)2 +b2xp2 - 2a2b2 + 2a2(yp - 1)2

 

       根據以上分析,Bresenham橢圓生成算法的實現就比較簡單了:

 

 61 void Bresenham_Ellipse(int xc , int yc , int a, int b)

 62 {

 63     int sqa = a * a;

 64     int sqb = b * b;

 65 

 66     int x = 0;

 67     int y = b;

 68     int d = 2 * sqb - 2 * b * sqa + sqa;

 69     EllipsePlot(xc, yc, x, y);

 70     int P_x = ROUND_INT( (double)sqa/sqrt((double)(sqa+sqb)) );

 71     while(x <= P_x)

 72     {

 73         if(d < 0)

 74         {

 75             d += 2 * sqb * (2 * x + 3);

 76         }

 77         else

 78         {

 79             d += 2 * sqb * (2 * x + 3) - 4 * sqa * (y - 1);

 80             y--;

 81         }

 82         x++;

 83         EllipsePlot(xc, yc, x, y);

 84     }

 85 

 86     d = sqb * (x * x + x) + sqa * (y * y - y) - sqa * sqb;

 87     while(y >= 0)

 88     {

 89         EllipsePlot(xc, yc, x, y);

 90         y--;

 91         if(d < 0)

 92         {

 93             x++;

 94             d = d - 2 * sqa * y - sqa + 2 * sqb * x + 2 * sqb;

 95         }

 96         else

 97         {

 98             d = d - 2 * sqa * y - sqa;

 99         }

100     }

101 }

        總結一下,本文介紹了兩種計算機圖形學中常見的橢圓生成算法,實際上還有很多種改進算法,包括提高效率,引入反走樣技術等等,但那已經不是本文的重點,能把算法的基本原理講清楚纔是本文的目的。

 

 

 

 

 

參考資料:

 

1】計算幾何:算法設計與分析周培德  清華大學出版社 2005

2】計算幾何:算法與應用德貝爾赫(鄧俊輝譯)  清華大學出版社 2005

3】計算機圖形學孫家廣、楊常貴清華大學出版社 1995

 

 

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