1. 程式人生 > >計算機圖形學 學習筆記(二):多邊形掃描轉換:X掃描線演算法 和 改進的X掃描線演算法

計算機圖形學 學習筆記(二):多邊形掃描轉換:X掃描線演算法 和 改進的X掃描線演算法

光柵圖形學演算法

2.4 多邊形掃描轉換-X掃描線演算法

多邊形的掃描轉換和區域填充這個問題是怎麼樣在離散的畫素集上表示一個連續的二維圖形

多邊形有兩種重要的表示方法:頂點表示和點陣表示

這裡寫圖片描述

頂點表示

頂點表示是用多邊形的頂點序列來表示多邊形。

優點:這種表示直觀、幾何意義強。佔記憶體少、易於進行幾何變化

缺點:但由於它沒有明確指出哪些畫素在多邊形內,故不能直接用於面著色

點陣表示

點陣表示是用位於多邊形內的畫素幾何來刻畫多邊形。

這種表示丟失了許多幾何資訊(如邊界、頂點等),但它卻是光柵顯示系統時所需的表示形式

這涉及到兩個問題:第一個問題是如果知道邊界,能否求出哪些畫素在多邊形內?(可以)

第二個問題是知道多邊形內部的畫素,反過來如何求出邊界?(不行)

光柵圖形的一個基本問題是把多邊形的頂點表示轉化為點陣表示。這種轉換稱為多邊形的掃描轉換

現在的問題是,知道多邊形的邊界,如何找到多邊形內部的點,即把多邊形內部填上顏色。

X-掃描線演算法

X-掃面線演算法填充多邊形的基本思想是按掃描線順序,計算掃描線與多邊形的相交區間,再用要求的顏色顯示這些區間的畫素,即完成填充工作。

這裡寫圖片描述

區間的端點可以通過計算掃描線與多邊形邊界線的交點獲得。

演算法的核心是按X遞增順序排列交點的X座標序列。

由此,可得到X-掃描線演算法步驟如下:

(1)確定多邊形所佔用的最大掃描線數,得到多邊形頂點的最小和最大y值

(2)從y=y(min)到y=(ymax),每次用一條掃描線進行填充

(3)對一條掃描線填充的過程可以分為四個步驟

  1. 求交:計算掃描線與多邊形各邊的交點
  2. 排序:把所有交點按遞增順序進行排序
  3. 交點配對:第一個與第二個,第三個與第四個
  4. 區間填色:把這些相交區間內的畫素置成不同於背景色的填充色

當掃描線與多邊形頂點相交時,交點的取捨問題(交點的個數應保證為偶數個)

這裡寫圖片描述

解決方案:
(1)若共享頂點的兩條邊分別落在掃描線的兩邊,交點只算一個
(2)若共享頂點的兩條邊在掃描線的同一邊,這時交點作為零個或兩個

檢查共享頂點的兩條邊的另外兩個端點的y值,按這兩個y值中大於交點y值的個數來決定交點數

為了計算每條掃描線與多邊形各邊的交點,最簡單的方法是把多邊形的所有邊放在一個表中。在處理每條掃描線時,按順序從表中取出所有的邊,分別與掃描線相交。

這個演算法效率低,為什麼?

關鍵問題是求交!而求交是很可怕的,求交的計算量是非常大的

2.5 多邊形掃描轉換-改進的X掃描線演算法

掃描轉換演算法重要意義是提出了圖形學裡兩個重要的思想

(1)掃描線:當處理圖形影象時按一條條掃描線處理
(2)增量的思想

求交點的時候能不能也採取增量的方法?每條掃描線的y值都知道,關鍵是求x的值。x是什麼?

可以從三個方面考慮加以改進:

(1)在處理一條掃描線時,僅對與它相交的多邊形的邊(有效邊)進行求交運算。

這裡寫圖片描述
針對這條藍色的掃描線,僅僅只有P1P4,P2P3這條邊與它相交,因此這兩條是有效邊。在處理這條掃面線時,和它不相交的邊就可以不考慮了。

(2)考慮掃描線的連貫性

這裡寫圖片描述
藍色的是當前的掃描線,紅色是下一條掃描線。可以看出:當前掃描線與各邊的交點順序與下一條掃描線與各邊的交點順序很可能相同或非常相似。

(3)考慮多邊形的連貫性

這裡寫圖片描述

即當某條邊與當前掃描線相交時,它很可能也下一條掃描線相交。

為了避免求交運算,需要引進一套特殊的資料結構。

活性邊表(AET):

(1)活性邊表(AET):把與當前掃描線相交的邊稱為活性邊,並把它們按與掃描線交點 x 座標遞增的順序 存放在一個連結串列 中。

這裡寫圖片描述
針對這條藍色的掃描線,P1P4,P2P3被稱為活性邊。

(2)活性邊表中的結點內容(一個結點在資料結構裡可用結構來表示)
這裡寫圖片描述

隨著掃描線的移動,掃描線與多邊形的交點和上一次交點是相關的,這意味著我們可以用增量來計算下一次掃描線的位置。

接下來證明下增量的值是多少

這裡寫圖片描述
這裡寫圖片描述

增量的計算方式即斜率的倒數。

例子:

這裡寫圖片描述

為了方便活性邊表的建立與更新,需要構造一個特殊的資料結構即新邊表(NET),用來存放多邊形的邊的資訊,分為4個步驟

(1)首先構造一個縱向連結串列,連結串列的長度為多邊形所佔有的最大掃描線數,連結串列的每個結點,稱為一個吊桶,對應多邊形覆蓋的每一條掃描線
(2)新邊表(NET)掛在與該邊低端 y 值相同的掃描線桶中。也就是說,存放在該掃描線第一次出現的邊。
這裡寫圖片描述

下面看一個新邊表(NET)的例子:

這裡寫圖片描述

可以看出這個多邊形有10條掃描線,因此連結串列的長度為10。結點為1的地方,存放了第一條掃描線(y=1)經過的兩條邊 P1P2,P1P6 的資訊。

這裡寫圖片描述

每做一次新的掃描線時,要對已有的邊進行三個處理:

  1. 檢視是否是被除掉(我們只針對活性邊進行處理)
  2. 如果不被去除(那麼說明是活性邊),就要對它的資料進行更新。所謂更新資料就是要更新它的 x 值,即:x+1/k
  3. 看看有沒有新的邊進來,新的邊在新邊表(NET)中,可以插入排序插進來

這個演算法過程中沒有求交,因為計算x值時,只計算了x的增量(即1/k),大大提高了效率。

演算法描述

虛擬碼:

void polyfill(多邊形 polygon,int  color)
{
    for(各條掃描線 i)
    {
        初始化 新邊表頭指標NET[i];
        把y(min)=i 的邊放進 新邊表NET[i];       
    }
    y=最低掃描線號;
    初始化 活性邊表AET 為空;
    for(各條掃描線i)
    {
        把新邊表NET[i]中的邊結點用插入排序法插入 活性邊表AET中,使之按 x 座標定增順序排列;
        遍歷活性邊表AET,把配對交點區間(左閉區間右開區間)上的畫素(x,y) 用 putpixel(x,y,color) 改寫畫素顏色值;
        遍歷活性邊表AET,把y(max)=i 的結點從 活性邊表AET中刪除,並把 y(max)>i 結點的 x值 遞增 Δx;
        若允許多邊形的邊自相交,則用氣泡排序法對 活性邊表AET 重新排序;
    }
}

多邊形掃描轉換演算法小結

掃描線法可以實現已知任意多邊形域邊界的填充

該填充演算法(多邊形掃描轉換演算法)是按掃描線的順序,計算掃描線與待填充區域的相交區間,再用要求的顏色顯示這些區間的畫素,即完成填充工作。

為了提高演算法效率:

  1. 我們引入了增量的思想
  2. 引入了連貫性思想
  3. 構建了一套特殊的資料結構(活性邊表AET ,新邊表 NET)

多邊形掃描轉換演算法缺點:這裡區間的端點通過計算掃描線與多邊形邊界的交點獲得。所以待填充區域的邊界線必須實現知道,因此它的缺點是無法實現對未知邊界的區域填充。

解決這個問題的有幾種演算法:邊緣填充演算法,柵欄填充演算法,邊界標誌演算法

多邊形掃描轉換-邊緣填充演算法

基本思想是按任意順序處理多邊形的每條邊。在處理每條邊時,首先求出該邊與掃描線的交點,然後將每一條掃描線上交點右方的所有畫素取補。多邊形的所有邊處理完畢之後,填充即完成。

例子:

這裡寫圖片描述

邊緣填充演算法,演算法簡單。但對於複雜圖形,每一畫素可能被訪問多次,輸入量和輸出量比有效邊演算法大得多。

為了減少邊緣填充法訪問畫素的次數,可以採用柵欄填充演算法。

多邊形掃描轉換-柵欄填充演算法

柵欄指的是一條過多邊形頂點且與掃描線垂直的直線。它把多邊形分為兩半。在處理每條邊與掃描線的交點時,將交點與柵欄之間的畫素取補。

多邊形掃描轉換-邊界標誌演算法

幀緩衝器中對多邊形的每條邊進行直線掃描轉換,亦即對多邊形邊界所經過的畫素當上標誌。然後再採用和掃描線演算法類似的方法將位於多邊形內的各個區段著上所需的顏色。

由於邊界標誌演算法不必建立維護邊表以及對它進行排序,所以邊界標誌演算法更適合硬體實現,它的執行速度比有序邊表演算法快一至兩個數量級。