2023年全國碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩26頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、<p>  設(shè)計題目 改進(jìn)的有效邊表算法對多邊形的填充 </p><p><b>  目錄</b></p><p>  一、設(shè)計內(nèi)容與要求3</p><p>  1.1設(shè)

2、計題目3</p><p>  1.2 設(shè)計內(nèi)容3</p><p>  1.3 設(shè)計目標(biāo)3</p><p><b>  二、總體設(shè)計3</b></p><p>  2.1 多邊形的表示3</p><p>  2.2 x-掃描線算法4</p><p>  2.3 改

3、進(jìn)的有效邊表算法4</p><p>  2.3.1 改進(jìn)的有效邊表算法4</p><p>  2.3.2 有效邊表5</p><p>  2.3.3 邊表6</p><p><b>  三、詳細(xì)設(shè)計8</b></p><p>  3.1 改進(jìn)的有效邊表算法的實現(xiàn)8</p>

4、<p>  3.2 有效邊表算法程序流程圖9</p><p><b>  四、測試結(jié)果9</b></p><p><b>  五、總結(jié)15</b></p><p><b>  六、源代碼15</b></p><p><b>  參考文獻(xiàn)26<

5、;/b></p><p><b>  一、設(shè)計內(nèi)容與要求</b></p><p><b>  設(shè)計題目</b></p><p>  用改進(jìn)的有效邊表算法實現(xiàn)多邊形的填充</p><p><b>  1.2 設(shè)計內(nèi)容</b></p><p>  使用

6、OpenGL實現(xiàn)用改進(jìn)的有效邊表算法填充多邊形</p><p><b>  1.3 設(shè)計目標(biāo)</b></p><p>  參照課本上改進(jìn)的有效邊表算法的思想,實現(xiàn)該算法的C語言代碼,并用該算法搭配OpenGL以像素點(diǎn)的方式繪制出給定頂點(diǎn)坐標(biāo)的多邊形。</p><p><b>  二、總體設(shè)計</b></p>

7、<p>  2.1 多邊形的表示</p><p>  在計算機(jī)圖形學(xué)中,多邊形有2種重要的表示方法:頂點(diǎn)表示和點(diǎn)陣表示。</p><p>  頂點(diǎn)表示用多邊形的頂點(diǎn)序列來刻畫多邊形,這種方法直觀、幾何意義強(qiáng),占用內(nèi)存少,應(yīng)用普遍,但它沒有明確指出哪些像素在多邊形內(nèi),故不能直接用于面著色。</p><p>  點(diǎn)陣表示用位于多邊形內(nèi)的像素的集合來刻畫多邊形。

8、 這種表示法雖然失去了許多重要的幾何信息,但便于運(yùn)用幀緩存表示圖形,是面著色所需要的圖形表示形式。</p><p>  大多數(shù)圖形應(yīng)用系統(tǒng)采用頂點(diǎn)序列表示多邊形,而頂點(diǎn)表示又不能直接用于顯示,那么就必須有從多邊形的頂點(diǎn)表示到點(diǎn)陣表示的轉(zhuǎn)換,這種轉(zhuǎn)換稱為多邊形的掃描轉(zhuǎn)換或多邊形的填充。即從多邊形的頂點(diǎn)信息出發(fā),求出位于其內(nèi)部的各個像素,并將其顏色值寫入幀緩存的相應(yīng)單元中。</p><p> 

9、 2.2 x-掃描線算法</p><p>  x-掃描線算法的基本思想是,按照掃描線的順序,計算掃描線與多邊形的相交區(qū)間,再用要求的顏色顯示這些區(qū)間的像素,即完成填充工作。區(qū)間的端點(diǎn)可以通過計算掃描線與多邊形邊界線的交點(diǎn)獲得。根據(jù)此原理,x-掃描線算法可以填充凸的、凹的或帶有孔的多邊形區(qū)域。</p><p>  x-掃描線的算法步驟如下:</p><p>  確定多

10、邊形頂點(diǎn)的最小和最大y值(ymin和ymax),得到多邊形所占有的最大掃描線數(shù)。</p><p>  從y=ymin到y(tǒng)=ymax,每次用一條掃描線填充。每一條掃描線填充的過程分為4個步驟:</p><p>  求交。計算掃描線與多邊形所有邊的交點(diǎn)。</p><p>  排序。把所有交點(diǎn)按x坐標(biāo)遞增的順序進(jìn)行排序。</p><p>  交點(diǎn)配

11、對。配對第一與第二、第三與第四個交點(diǎn)等,每對交點(diǎn)代表一個填充區(qū)間。</p><p>  區(qū)間填色。把這些相交區(qū)間內(nèi)的像素置成不同于背景色的填充色。</p><p>  x-掃描線算法在處理每條掃描線時,需要與多邊形的所有邊求交,這樣處理效率非常低。因為一條掃描線往往只與少數(shù)幾條邊相交,甚至與整個多邊形都不相交。因此,有必要對算法進(jìn)行改進(jìn)。</p><p>  2.3

12、 改進(jìn)的有效邊表算法</p><p>  2.3.1 改進(jìn)的有效邊表算法</p><p>  將x-掃描線算法加以改進(jìn)可以得到改進(jìn)的有效邊表算法,也稱y連貫算法。改進(jìn)可以從三個方面進(jìn)行:首先,在處理一條掃描線時,僅對與它相交的多邊形的邊(有效邊)求交;其次,利用掃描線的連貫性,考慮到當(dāng)前掃描線與各邊的交點(diǎn)順序與下一條掃描線與各邊的交點(diǎn)順序很可能相同或非常相似,因此在當(dāng)前掃描線處理完畢之后,

13、不必為下一條掃描線從頭開始構(gòu)造交點(diǎn)信息;最后,利用多邊形的連貫性,認(rèn)為若某條邊與當(dāng)前掃描線相交,則它很可能也與下一條掃描線相交且其交點(diǎn)與上一次的交點(diǎn)相關(guān)。如下圖所示,設(shè)直線的斜率為k,若y=yi時,x=xi;則當(dāng)y=yi+1時,有xi+1=xi+1/k。</p><p>  2.3.2 有效邊表</p><p>  有效邊(Active Edge)是指與當(dāng)前掃描線相交的多邊形的邊,也稱活性

14、邊。把有效邊按與掃描線交點(diǎn)x坐標(biāo)遞增的順序存放在一個鏈表中,此鏈表稱為有效邊表(Active Edge Table, AET)。有效邊表的每個結(jié)點(diǎn)存放對應(yīng)邊的如下信息:</p><p>  其中,x為當(dāng)前掃描線與有效邊交點(diǎn)的x坐標(biāo);ymax是有效邊所在的最大掃描線值,通過它可以知道何時才能“拋棄”該邊;1/k是邊斜率的倒數(shù);next是下一個結(jié)點(diǎn)的指針。</p><p>  如下圖所示的多邊

15、形P0P1P2P3P4P5P6,其頂點(diǎn)表示為:</p><p>  P0(7,8),P1(3,12),P2(1,7),P3(3,1),P4(6,5),P5(8,1),P6(12,9)。</p><p>  當(dāng)y=8時的有效邊表如下圖所示:</p><p><b>  2.3.3 邊表</b></p><p>  有效邊表

16、給出了掃描線和有效邊交點(diǎn)坐標(biāo)的計算方法,但是沒有給出新邊出現(xiàn)的位置坐標(biāo)。為了方便有效邊表的建立與更新,就需要構(gòu)造一個邊表(Edge Table, ET),用以存放掃描線上多邊形各條邊的信息。由于水平邊的1/k為∞,并且水平邊本身就是掃描線,所以在建立邊表時不予考慮。</p><p>  邊表的構(gòu)造分為4個步驟:</p><p>  首先構(gòu)造一個縱向鏈表,鏈表的長度為多邊形占有的最大掃描線數(shù)

17、,鏈表的每個結(jié)點(diǎn),稱為一個桶,對應(yīng)多邊形覆蓋的每一條掃描線。</p><p>  將每條邊的信息裝入與該邊最小y坐標(biāo)(ymin)相對應(yīng)的桶中。也就是說,若某邊的較低端點(diǎn)為ymin,則該邊就放在相應(yīng)的y=ymin的掃描線桶中。</p><p>  每條邊的數(shù)據(jù)形成一個結(jié)點(diǎn),內(nèi)容包括該掃描線與該邊的初始交點(diǎn)x(即較低端點(diǎn)的x坐標(biāo)值),該邊最大y坐標(biāo)值ymax,以及斜率的倒數(shù)1/k和下一個邊結(jié)點(diǎn)

18、的指針next:</p><p>  同一桶中若干條邊按x|ymin由小到大排列,若x|ymin相等,則按1/k由小到大排序。</p><p>  從上面可以看出,邊表是有效邊表的特例,有效邊表和邊表可以使用同一個數(shù)據(jù)結(jié)構(gòu)來表示。</p><p>  對于多邊形P0P1P2P3P4P5P6,它的邊表結(jié)構(gòu)如下圖所示:</p><p><b

19、>  三、詳細(xì)設(shè)計</b></p><p>  3.1 改進(jìn)的有效邊表算法的實現(xiàn)</p><p>  改進(jìn)的有效邊表算法具體實現(xiàn)過程如下:</p><p><b>  初始化邊表ET。</b></p><p>  為了方便邊表的建立,可以定義sort()函數(shù)對多邊形的邊進(jìn)行排序,保證邊表中每個桶中的邊是

20、有序的。同時定義一個creat_edge_table()函數(shù),該函數(shù)需要多邊形的頂點(diǎn)信息作為參數(shù)傳入,并返回一個邊表指針。</p><p>  初始化有效邊表AET。從ET表中取出第一個不為空的桶與AET表合并。</p><p>  為了初始化AET表,可以定義一個init_active_table()函數(shù),該函數(shù)傳入邊表指針作為形參,返回一個有效邊表指針。</p><

21、p>  從AET表中取出交點(diǎn)進(jìn)行填充。</p><p>  填充時設(shè)置一個布爾值b(初值為假),令指針從有效邊表的第一個結(jié)點(diǎn)(也就是掃描線與有效邊的交點(diǎn))開始遍歷。每訪問一個結(jié)點(diǎn),把b取反一次。若b為真,則把從當(dāng)前結(jié)點(diǎn)的x值開始(設(shè)為x1)到下一結(jié)點(diǎn)的x值結(jié)束(設(shè)為x2)的區(qū)間[x1, x2]用多邊形色填充。填充時為了避免多邊形區(qū)域擴(kuò)大化,需要對區(qū)間邊界進(jìn)行如下處理:</p><p>

22、;  若x是整數(shù),則按“左閉右開”的原則處理,即左邊界上的x(x1)不變,右邊界上的x(x2)減1;若x不是整數(shù),左邊界上的x(x1)向右取整,右邊界上的x(x2)向左取整。</p><p><b>  更新AET表。</b></p><p>  設(shè)當(dāng)前AET表中掃描線為y,首先更新掃描線為y=y+1,然后刪除AET表中所有ymax=y的邊結(jié)點(diǎn);再根據(jù)xi+1=xi+

23、1/k計算并修改AET表中各邊結(jié)點(diǎn)的x坐標(biāo),同時合并ET表對應(yīng)于掃描線y的桶中的邊,按次序插入到AET表中,形成新AET表。此步驟滿足多邊形的“下閉上開”原則。</p><p>  此過程用到自定義的函數(shù)delete_edge()、add_edge()、update_active_table()。</p><p>  判斷AET表是否為空。若為空,則結(jié)束;否則轉(zhuǎn)到③</p>

24、<p>  3.2 有效邊表算法程序流程圖</p><p><b>  四、測試結(jié)果</b></p><p>  為了便于觀察多邊形的填充,本程序?qū)⑾袼攸c(diǎn)進(jìn)行放大處理,400 x 300的分辨率投影到20 x 15,并繪制出網(wǎng)格,使用OpenGL畫出多邊形的邊框。使用了Sleep()函數(shù)來延時生成像素點(diǎn),并且每填充一個像素點(diǎn)刷新一次,給人動態(tài)直觀的感受。&l

25、t;/p><p>  在不處理邊界的情況下,如下圖所示,多邊形的區(qū)域可能會擴(kuò)大化。</p><p>  對邊界進(jìn)行處理后,結(jié)果如下:</p><p>  為了驗證改進(jìn)的有效邊表填充算法,現(xiàn)將本程序的像素大小恢復(fù)為1:1,按比例擴(kuò)大多邊形的頂點(diǎn)坐標(biāo),測試結(jié)果如下:</p><p>  從上圖可以看出填充過后的多邊形與原多邊形P0P1P2P3P4P5

26、P6的形狀一致,該算法驗證通過。</p><p><b>  測試其他多邊形</b></p><p><b>  長方形:</b></p><p><b>  三角形:</b></p><p><b>  五角星:</b></p><p

27、>  從以上結(jié)果來看,該算法基本得到完美實現(xiàn)。而程序的執(zhí)行時間來看,生成邊表的時間(包括分配內(nèi)存、對桶中的結(jié)點(diǎn)進(jìn)行排序等)遠(yuǎn)比填充像素點(diǎn)的時間要長。因此,該算法的效率雖然很高,但對于表的維護(hù)和排序開銷太大,它適合軟件實現(xiàn)而不適合硬件實現(xiàn)。</p><p><b>  五、總結(jié)</b></p><p>  通過本次課程設(shè)計,我掌握了多邊形的填充算法,了解了Open

28、GL的運(yùn)行結(jié)構(gòu),熟悉了很多OpenGL的函數(shù),對OpenGL編程也產(chǎn)生的濃厚的興趣。同時也鞏固了對計算機(jī)圖形學(xué)知識的掌握,鍛煉了我對手實驗的能力,看清了自己的水平,認(rèn)識到了自己的不足。</p><p>  在本次課程設(shè)計中,存在一些不足之處。比如對邊界的處理,課本上的說法模糊不清,在網(wǎng)上也沒有找到相應(yīng)的解答,我只能根據(jù)自己的理解來試著解決;這方面也存在沒有及時和老師溝通的原因。從這一點(diǎn)上,我認(rèn)識到理論和實踐的差別

29、,我們應(yīng)該多實踐才能真正掌握理論。</p><p>  還有就是完全填充后的多邊形,邊緣有“鋸齒”現(xiàn)象,不知道是我程序的原因還是算法的問題。或許對于多邊形的填充算法還應(yīng)該處理“鋸齒”。</p><p><b>  六、源代碼</b></p><p>  //源代碼僅包含文件PolygonFilling.cpp</p><p&

30、gt;  #include <stdio.h></p><p>  #include <malloc.h></p><p>  #include <gl/glut.h></p><p>  #include <Windows.h></p><p>  #define EPSILON 0.0000

31、01 //最小浮點(diǎn)數(shù)</p><p><b>  //點(diǎn)結(jié)構(gòu)體</b></p><p>  struct Point</p><p><b>  {</b></p><p>  int x; //x坐標(biāo)</p><p>  int y;

32、//y坐標(biāo)</p><p><b>  };</b></p><p><b>  //線結(jié)構(gòu)體</b></p><p>  struct Line</p><p><b>  {</b></p><p>  Point high_point;

33、 //高端點(diǎn)</p><p>  Point low_point; //低端點(diǎn)</p><p>  int is_active; //是否為有效邊,水平邊(0),非水平邊(1)</p><p>  double inverse_k; //斜率k的倒數(shù)</p><p><b>  }

34、;</b></p><p><b>  //邊結(jié)點(diǎn)</b></p><p>  struct EdgeNode</p><p><b>  {</b></p><p>  double x; //掃描線與邊交點(diǎn)的x坐標(biāo)(邊的低端點(diǎn)的x坐標(biāo))</p>

35、<p>  int y_max; //邊的高端點(diǎn)的y坐標(biāo)ymax</p><p>  double inverse_k; //斜率k的倒數(shù)</p><p>  EdgeNode *next; //下一個邊結(jié)點(diǎn)的指針</p><p><b>  };</b></p><

36、;p><b>  //有效邊表</b></p><p>  struct ActiveEdgeTable</p><p><b>  {</b></p><p>  int y; //掃描線y</p><p>  EdgeNode *head; /

37、/邊鏈表的頭指針</p><p><b>  };</b></p><p><b>  //桶結(jié)點(diǎn)</b></p><p>  typedef struct Bucket</p><p><b>  {</b></p><p>  int y;

38、 //掃描線y</p><p>  EdgeNode *head; //邊鏈表的頭指針</p><p>  Bucket *next; //下一個桶的指針</p><p>  } EdgeTable;</p><p>  int compare(Point p1, Point p2);</

39、p><p>  Line* create_lines(Point points[], int n);</p><p>  Point get_lowest_point(Line lines[], int n);</p><p>  Point get_highest_point(Line lines[], int n);</p><p>  vo

40、id swap(Line &l1, Line &l2);</p><p>  void sort(Line lines[], int n);</p><p>  EdgeTable* create_edge_table(Line lines[], int n);</p><p>  ActiveEdgeTable* init_active_table

41、(EdgeTable *edge_table);</p><p>  void delete_edge(ActiveEdgeTable *active_table, int y_max);</p><p>  void add_edge(ActiveEdgeTable *active_table, EdgeNode edge);</p><p>  ActiveEd

42、geTable* update_active_table(ActiveEdgeTable *active_table, EdgeTable *edge_table);</p><p>  void DrawPolygon(Point points, int n);</p><p>  void DrawGrid(int x, int y);</p><p>  vo

43、id Fill(Point points[], int n);</p><p>  void Initial();</p><p>  void Display();</p><p>  int main(int argc, char* argv[])</p><p><b>  {</b></p><

44、;p>  glutInit(&argc, argv);</p><p>  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);</p><p>  glutInitWindowSize(400, 300);</p><p>  glutInitWindowPosition(100, 120);</p>

45、<p>  glutCreateWindow("Polygon Filling");</p><p>  glutDisplayFunc(Display);</p><p>  Initial();</p><p>  glutMainLoop();</p><p><b>  return 0;&l

46、t;/b></p><p><b>  }</b></p><p>  //比較2個點(diǎn)的高度</p><p>  int compare(Point p1, Point p2)</p><p><b>  {</b></p><p>  if (p1.y > p2

47、.y)</p><p><b>  return 1;</b></p><p>  else if (p1.y == p2.y)</p><p><b>  return 0;</b></p><p>  return -1;</p><p><b>  }<

48、/b></p><p>  //由點(diǎn)數(shù)組生成線段數(shù)組</p><p>  Line* create_lines(Point points[], int n)</p><p><b>  {</b></p><p>  Line *lines = (Line*)malloc(n * sizeof(Line));<

49、;/p><p>  for (int i = 0; i < n; ++i)</p><p><b>  {</b></p><p>  Point p1 = points[i];</p><p>  Point p2 = points[(i + 1) % n];</p><p>  int re

50、sult = compare(p1, p2);</p><p>  if (result == 0)</p><p>  lines[i].is_active = 0;</p><p><b>  else</b></p><p>  lines[i].is_active = 1;</p><p>

51、;  lines[i].high_point = result > 0 ? p1 : p2;</p><p>  lines[i].low_point = result < 0 ? p1 : p2;</p><p>  lines[i].inverse_k = (double)(p2.x - p1.x) / (double)(p2.y - p1.y);</p>&

52、lt;p><b>  }</b></p><p>  return lines;</p><p><b>  }</b></p><p>  //獲取線數(shù)組中最低的端點(diǎn)</p><p>  Point get_lowest_point(Line lines[], int n)</p>

53、;<p><b>  {</b></p><p>  Point lowest_point = lines[0].low_point;</p><p>  for (int i = 1; i < n; ++i)</p><p><b>  {</b></p><p>  Poin

54、t low_point = lines[i].low_point;</p><p>  if (compare(lowest_point, low_point) > 0)</p><p>  lowest_point = low_point;</p><p><b>  }</b></p><p>  return

55、 lowest_point;</p><p><b>  }</b></p><p>  //獲取線數(shù)組中最高的端點(diǎn)</p><p>  Point get_highest_point(Line lines[], int n)</p><p><b>  {</b></p><p

56、>  Point highest_point = lines[0].high_point;</p><p>  for (int i = 1; i < n; ++i)</p><p><b>  {</b></p><p>  Point high_point = lines[i].high_point;</p>&l

57、t;p>  if (compare(highest_point, high_point) < 0)</p><p>  highest_point = high_point;</p><p><b>  }</b></p><p>  return highest_point;</p><p><b&g

58、t;  }</b></p><p>  //交換2個Line對象</p><p>  void swap(Line &l1, Line &l2)</p><p><b>  {</b></p><p>  Line temp = l1;</p><p><b>

59、;  l1 = l2;</b></p><p>  l2 = temp;</p><p><b>  }</b></p><p>  //對線數(shù)組進(jìn)行排序</p><p>  void sort(Line lines[], int n)</p><p><b>  {<

60、/b></p><p>  //先按低端點(diǎn)的y坐標(biāo)進(jìn)行升序排序</p><p>  for (int i = 0; i < n; ++i)</p><p><b>  {</b></p><p>  int min_index = i;</p><p>  for (int j = i

61、 + 1; j < n; ++j)</p><p><b>  {</b></p><p>  if (lines[j].low_point.y < lines[min_index].low_point.y)</p><p>  min_index = j;</p><p><b>  }</

62、b></p><p>  swap(lines[i], lines[min_index]);</p><p><b>  }</b></p><p>  //再將有序數(shù)組按低端點(diǎn)的x坐標(biāo)升序排列,若x坐標(biāo)相等,按inverse_k升序</p><p>  for (int i = 0; i < n; ++i)

63、</p><p><b>  {</b></p><p>  int min_index = i;</p><p>  for (int j = i + 1; lines[j].low_point.y == lines[i].low_point.y; ++j)</p><p><b>  {</b>

64、</p><p>  if (lines[j].low_point.x < lines[min_index].low_point.x)</p><p>  min_index = j;</p><p><b>  }</b></p><p>  swap(lines[i], lines[min_index]);&l

65、t;/p><p>  if (i > 0 && lines[i].low_point.x == lines[i - 1].low_point.x)</p><p><b>  {</b></p><p>  if (lines[i].is_active == 1 && lines[i - 1].is_activ

66、e == 1)</p><p><b>  {</b></p><p>  if (lines[i].inverse_k < lines[i - 1].inverse_k)</p><p>  swap(lines[i], lines[i - 1]);</p><p><b>  }</b>&

67、lt;/p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  //創(chuàng)建一個邊表</b></p><p>  EdgeTable* create_e

68、dge_table(Line lines[], int n)</p><p><b>  {</b></p><p>  EdgeTable *edge_table = (EdgeTable*)malloc(sizeof(EdgeTable));</p><p>  edge_table->head = NULL;</p>

69、<p>  edge_table->next = NULL;</p><p>  sort(lines, n);</p><p>  Point lowest_point = get_lowest_point(lines, n);</p><p>  Point highest_point = get_highest_point(lines, n);

70、</p><p>  EdgeTable *s = edge_table;</p><p>  for (int i = lowest_point.y; i <= highest_point.y; ++i)</p><p><b>  {</b></p><p>  Bucket *bucket = (Bucket

71、*)malloc(sizeof(Bucket));</p><p>  bucket->y = i;</p><p>  bucket->next = NULL;</p><p>  bucket->head = (EdgeNode*)malloc(sizeof(EdgeNode));</p><p>  bucket-&g

72、t;head->next = NULL;</p><p>  EdgeNode *p = bucket->head;</p><p>  for (int j = 0; j < n; ++j)</p><p><b>  {</b></p><p>  if (lines[j].is_active ==

73、 0)</p><p><b>  continue;</b></p><p>  if (lines[j].low_point.y == i)</p><p><b>  {</b></p><p>  EdgeNode *q = (EdgeNode*)malloc(sizeof(EdgeNode

74、));</p><p>  q->x = lines[j].low_point.x;</p><p>  q->y_max = lines[j].high_point.y;</p><p>  q->inverse_k = lines[j].inverse_k;</p><p>  q->next = NULL;<

75、;/p><p>  p->next = q;</p><p><b>  p = q;</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  s->next = bucket;</p&g

76、t;<p>  s = bucket;</p><p><b>  }</b></p><p>  return edge_table;</p><p><b>  }</b></p><p>  //從邊表中取出第一個不為空的桶初始化有效邊表</p><p>

77、  ActiveEdgeTable* init_active_table(EdgeTable *edge_table)</p><p><b>  {</b></p><p>  ActiveEdgeTable *active_table = (ActiveEdgeTable*)malloc(sizeof(ActiveEdgeTable));</p>&

78、lt;p>  active_table->y = edge_table->next->y;</p><p>  active_table->head = (EdgeNode*)malloc(sizeof(EdgeNode));</p><p>  active_table->head->next = NULL;</p><p&g

79、t;  EdgeNode *p = edge_table->next->head;</p><p>  EdgeNode *q = active_table->head;</p><p>  while (p->next != NULL)</p><p><b>  {</b></p><p> 

80、 EdgeNode *s = (EdgeNode*)malloc(sizeof(EdgeNode));</p><p>  s->x = p->next->x;</p><p>  s->y_max = p->next->y_max;</p><p>  s->inverse_k = p->next->inver

81、se_k;</p><p>  s->next = NULL;</p><p>  q->next = s;</p><p><b>  q = s;</b></p><p>  p = p->next;</p><p><b>  }</b></p&

82、gt;<p>  return active_table;</p><p><b>  }</b></p><p>  //從有效邊表中刪除指定y_max的邊結(jié)點(diǎn)</p><p>  void delete_edge(ActiveEdgeTable *active_table, int y_max)</p><

83、p><b>  {</b></p><p>  EdgeNode *p = active_table->head;</p><p>  while (p->next != NULL)</p><p><b>  {</b></p><p>  EdgeNode *q = p->

84、;next;</p><p>  if (q->y_max == y_max)</p><p><b>  {</b></p><p>  p->next = q->next;</p><p><b>  free(q);</b></p><p><b

85、>  }</b></p><p><b>  else</b></p><p>  p = p->next;</p><p><b>  }</b></p><p><b>  }</b></p><p>  //將一個邊結(jié)點(diǎn)按次

86、序添加到有效邊表中</p><p>  void add_edge(ActiveEdgeTable *active_table, EdgeNode edge)</p><p><b>  {</b></p><p>  EdgeNode *t = (EdgeNode*)malloc(sizeof(EdgeNode));</p>&

87、lt;p>  t->x = edge.x;</p><p>  t->y_max = edge.y_max;</p><p>  t->inverse_k = edge.inverse_k;</p><p>  t->next = NULL;</p><p>  EdgeNode *p = active_tabl

88、e->head;</p><p>  while (p->next != NULL)</p><p><b>  {</b></p><p>  EdgeNode *q = p->next;</p><p>  if ((edge.x < q->x) || (edge.x == q->

89、x && edge.inverse_k < q->inverse_k))</p><p><b>  {</b></p><p>  p->next = t;</p><p>  t->next = q;</p><p><b>  return;</b>&l

90、t;/p><p><b>  }</b></p><p>  p = p->next;</p><p><b>  }</b></p><p>  p->next = t;</p><p><b>  }</b></p><p

91、>  //更新有效邊表,并與邊表中對應(yīng)的桶合并</p><p>  ActiveEdgeTable* update_active_table(ActiveEdgeTable *active_table, EdgeTable *edge_table)</p><p><b>  {</b></p><p><b>  //更新掃描

92、線y</b></p><p>  ++active_table->y;</p><p>  //刪除y=ymax的邊</p><p>  delete_edge(active_table, active_table->y);</p><p>  //更新邊結(jié)點(diǎn)的數(shù)據(jù)</p><p>  Edge

93、Node *p = active_table->head->next;</p><p>  while (p != NULL)</p><p><b>  {</b></p><p>  p->x += p->inverse_k;</p><p>  p = p->next;</p&g

94、t;<p><b>  }</b></p><p>  //找到邊表中對應(yīng)的桶</p><p>  EdgeTable *q = edge_table;</p><p>  while ((q = q->next) != NULL && q->y != active_table->y);</

95、p><p>  //如果找到,則進(jìn)行合并</p><p>  if (q != NULL)</p><p><b>  {</b></p><p>  EdgeNode *s = q->head;</p><p>  while ((s = s->next) != NULL)</p&

96、gt;<p><b>  {</b></p><p>  add_edge(active_table, *s);</p><p><b>  }</b></p><p><b>  }</b></p><p>  return active_table;</

97、p><p><b>  }</b></p><p>  //畫出多邊形的邊框</p><p>  void DrawPolygon(Point points[], int n)</p><p><b>  {</b></p><p>  glBegin(GL_LINE_LOOP)

98、;</p><p>  for (int i = 0; i < n; ++i)</p><p>  glVertex2i(points[i].x, points[i].y);</p><p><b>  glEnd();</b></p><p><b>  }</b></p>&

99、lt;p>  //畫出x * y的網(wǎng)格</p><p>  void DrawGrid(int x, int y)</p><p><b>  {</b></p><p>  glBegin(GL_LINES);</p><p><b>  //橫線</b></p><p&

100、gt;  for (int i = 0; i <= y; ++i)</p><p><b>  {</b></p><p>  glVertex2d(0, i);</p><p>  glVertex2d(x, i);</p><p><b>  }</b></p>&l

101、t;p><b>  //豎線</b></p><p>  for (int i = 0; i <= x; ++i)</p><p><b>  {</b></p><p>  glVertex2d(i, 0);</p><p>  glVertex2d(i, y);</p>

102、<p><b>  }</b></p><p><b>  glEnd();</b></p><p><b>  }</b></p><p>  //用指定的像素大小填充多邊形</p><p>  void Fill(Point points[], int n)&l

103、t;/p><p><b>  {</b></p><p>  Line *lines = create_lines(points, n);</p><p>  EdgeTable *edge_table = create_edge_table(lines, n);</p><p>  ActiveEdgeTable *act

104、ive_table = init_active_table(edge_table);</p><p>  while (active_table->head->next != NULL)</p><p><b>  {</b></p><p>  EdgeNode *p = active_table->head;</p&

105、gt;<p>  int b = -1;</p><p>  while (p->next != NULL)</p><p><b>  {</b></p><p>  if (b > 0)</p><p><b>  {</b></p><p> 

106、 int left = p->x;</p><p>  int right = p->next->x;</p><p>  //如果不是局部最低點(diǎn),則進(jìn)行邊界處理</p><p>  if (!(p->x - p->next->x >= -EPSILON && p->x - p->next->

107、;x <= EPSILON))</p><p><b>  {</b></p><p><b>  //處理左邊界</b></p><p>  if (!(p->x - left >= -EPSILON && p->x - left <= EPSILON))</p>

108、<p>  left += 1;</p><p><b>  //處理右邊界</b></p><p>  if (p->next->x - right >= -EPSILON && p->next->x - right <= EPSILON)</p><p>  right -=

109、 1;</p><p><b>  }</b></p><p>  for (int i = left; i <= right; ++i)</p><p><b>  {</b></p><p>  glBegin(GL_POINTS);</p><p>  glVer

110、tex2d(i, active_table->y);</p><p><b>  glEnd();</b></p><p>  glFlush();</p><p>  Sleep(50);</p><p><b>  }</b></p><p><b>  

111、}</b></p><p>  p = p->next;</p><p><b>  b = -b;</b></p><p><b>  }</b></p><p>  active_table = update_active_table(active_table, edge_ta

112、ble);</p><p><b>  }</b></p><p><b>  }</b></p><p>  //初始化窗口,x和y指定窗口的坐標(biāo)大小</p><p>  void Initial()</p><p><b>  {</b></p

113、><p>  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);</p><p>  glMatrixMode(GL_PROJECTION);</p><p>  gluOrtho2D(0.0, 20.0, 0.0, 15.0);</p><p><b>  }</b></p><

114、p>  //窗口的顯示回調(diào)函數(shù)</p><p>  void Display()</p><p><b>  {</b></p><p>  //使用當(dāng)前背景色填充窗口</p><p>  glClear(GL_COLOR_BUFFER_BIT);</p><p>  //使用灰色畫出網(wǎng)格線

115、</p><p>  glColor3f(0.75f, 0.75f, 0.75f);</p><p>  DrawGrid(20, 14);</p><p>  glFlush();</p><p>  //多邊形的頂點(diǎn)坐標(biāo)</p><p>  Point points[] = { { 3, 1 },{ 6, 5 },

116、{ 8, 1 },{ 12, 9 },{ 7, 8 },{ 3, 12 },{ 1, 7 } };</p><p><b>  //計算頂點(diǎn)個數(shù)</b></p><p>  int n = sizeof(points) / sizeof(Point);</p><p>  //使用黑色畫出多邊形的邊框</p><p> 

117、 glColor3f(0.0f, 0.0f, 0.0f);</p><p>  DrawPolygon(points, n);</p><p>  glFlush();</p><p><b>  //指定點(diǎn)大小</b></p><p>  glPointSize(6.0f);</p><p>

118、  //使用紅色填充多邊形</p><p>  glColor3f(1.0f, 0.0f, 1.0f);</p><p>  Fill(points, n);</p><p>  glFlush();</p><p><b>  }</b></p><p><b>  參考文獻(xiàn)</

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論