在光柵圖形中,區域是由【相連的】像素組成的集合,這些像素具備【相同的】屬性值或者它們位於某邊界線的內部
一、光柵圖形的一個基本問題是把多邊形的頂點表示轉換爲點陣表示。這種轉換成爲多邊形的掃描轉換。
二、多邊形的掃描轉換與區域填充問題是怎樣在離散的像素集上表示一個連續的二維圖形。
三、多邊形有兩種重要的表示方法:算法
(1)頂點表示:用多邊形的定點序列來表示多邊形
優勢:直觀、幾何意義強、佔內存少、易於進行幾何變換
缺點:沒有明確指出那些象素在多邊形內,故不能直接用於上色
(2)點陣表示:是用位於多邊形內的象素集合來刻畫多邊形
缺點:丟失了許多幾何信息(eg:邊界、頂點等)數組
可是【點陣表示是光柵顯示系統顯示時所需的表現形式。】數據結構
多邊形的掃描轉換就是把多邊形的頂點表示轉換爲點陣表示,即從多邊形的給定邊界出發,求出位於其內部的各個像素,並將幀緩衝器內的各個對應元素設置相應的灰度或顏色。實際上就是多邊形內的區域的着色過程。
spa
四、多邊形分類3d
X掃描線算法填充多邊形的基本思想是按掃描線順序,計算掃描線與多邊形的相交區間,再用要求的顏色顯示這些區間的象素,即完成填充工做。指針
區間的端點能夠經過計算掃描線與多邊形邊界線的交點得到。code
如掃描線y=3與多邊形的邊界相交於4點(2,3)、(4,3)、(7,3)、(9,3)blog
這四個點定義了掃描線從x=2到x=4,從x=7到x=9兩個落在多邊形內的區間,該區間內像素應取填充色。排序
算法的核心是按x遞增順序排列交點的x座標序列。由此可獲得掃描線算法步驟以下:ip
算法步驟:
1.肯定多邊形所佔有的最大掃描線數,獲得多邊形定點的最小最大值(ymin和ymax);
2.從ymin到ymax每次用一條掃描線進行填充;
3.對一條掃描線填充的過程分爲四個步驟:
a)求交點;
b)把全部交點按遞增順序排序;
c)交點配對(第一個和第二個,第三個和第四個);
d)區間填色。把相交區間內的像素置成多邊形的顏色,相交區間外的像素置成背景色。
掃描線與多邊形頂點相交時,交點的取捨問題【交點應保證爲偶數個】
交點問題的處理:
爲了計算每條掃描線與多邊形各邊的交點,最簡單的方法是把多邊形的全部邊放在一個表中。在處理每條掃描線的時候,按順序從表中取出全部的邊,分別與掃描線求交。
但這個算法效率很低
由於關鍵問題是求交! 求交是很可怕的,求交的計算量很是大。‘
排序、配對、填色老是要的!
掃描轉換算法重要的意義是提出了圖形學裏兩個重要的思想:
(1)掃描線:當處理圖形圖像時按一條條掃描線處理
(2)增量的思想。
已經知道X-掃描線算法效率低是由於求交麻煩,那求教點的時候可否也採用增量思想,每條掃描線的y值都知道,關鍵是求x值。
能夠從三個方面改進:
一、在處理一條掃描線時,僅對與它相交的多邊形的邊(有效邊)進行求交運算。
二、考慮掃描線的連貫性,也就是當前掃描線與各邊交點順序與下一條掃描線邊與各邊的交點順序極可能相同或很是類似。
三、考慮多邊形的連貫性,即當某條邊與掃描線相交時它極可能與下一條掃描線也相交。
爲了不求交運算,須要引進一套特殊的數據結構
數據結構:
把當前掃描線相交的邊稱爲活性邊,並把它們按與掃描線交點x座標遞增的順序存放在一個鏈表中。
上圖中P4P一、P3P2是活性邊,P4P三、P1P2是非活性邊
x:當前掃描線與邊的交點座標
Δx:從當前掃描線到下一條掃描線間x的增量
ymax:該邊所交的最高掃描線的座標值
next:指向下一條邊的指針
另外,須要知道一條邊什麼時候再也不與下一條掃描線相交,以便及時把它從有效邊表中刪除出去,避免下一步進行無謂的計算。
一個具體的例子:
爲了方便活性邊表的創建與更新,用來存放多邊形的邊的信息,分爲4個步驟
1.構造一個縱向鏈表,長度爲多邊形所佔有的最大掃描線數,鏈表的每一個結點稱爲吊桶,對應多邊形覆蓋的每一條掃描線。
2.新邊表(NET)掛在與【該邊低端y值相同】的掃描線桶中。也就是說,存放在該掃描線第一次出現的邊
也就是說,若是某邊的較低端點爲ymin,則該邊就放在掃描線ymin的新邊表中。
注意:水平邊 不放到任何掃描線的NEL中,即水平邊不參與分類。
ymax:該邊的最大值;
xmin:該邊較低點的x座標值xmin;
1/k:該邊的斜率
next:指向下一條具備相同較低端y座標的邊的指針
從上邊的這個NET表裏就知道多邊形是從哪裏開始的
從這個表裏只有一、三、五、7處有邊,從y=1開始作,而1這條線上有兩條邊進來了,而後就把這兩條邊放入活性表來處理。
3.每作一次新的掃描時,要對已有的邊進行三個處理:
1.是否被去除掉;
2.若不被去除掉,就要對它的數據進行更新,x=x+1/k;
3.是否有新的邊進來,新的邊在NET裏,能夠插入排序插進來。
這個算法過程歷來沒有求交,這套數據結構使得你不用求交點!避免了求交運算。
爲提升算法效率:
(1)增量的思想;
(2)連貫性思想;
(3)構建一套特殊的數據結構。
【缺點】這裏的區間端點經過計算掃描線與多邊形邊界的交點得到,因此待填充區域的邊界線必須預先知道,所以它的缺點所在是沒法實現對未知邊界的區域填充。
採用對圖像進行逐位求反的方法,免去對邊排序的工做量。
對顏色M做偶數次求反運算,其結果仍是M,而對M做奇數次求反運算的結果是M的反M 。在光柵圖形中,如某區域已着上值爲M的某種顏色,則上述求反運算獲得的結果是:對區域做偶數次求反運算後,該區域的顏色不變;做奇數次求反運算後,該區域的顏色則變成值爲反M的顏色。
實現:對多邊形P的每一非水平邊上的各像素作向右求反運算便可,見下圖,其中(a)爲給定的多邊形;(b)爲對區域賦初值;(c),(d),(e)和(f)表示逐邊向右求反。
首先用一種特殊的顏色在幀緩衝器中將多邊形的邊界(水平邊的部分邊界除外)勾畫出來。而後再把位於多邊形內的各個像素着上所需的顏色。
步驟1:以值爲boundary-color 的特殊顏色勾畫多邊形P的邊界。設多邊形頂點爲Pi= (xi, yi),0≤i≤n, xi, yi均爲整數;置Pn+1=P0。每一條掃描線上着上這種特殊顏色的點的個數一定是偶數(包括零)。
pixels[ ]是一個整數數組,表示像素的顏色。
public Image boundary() { Image image; for(i=0; i<=n; i++) //多邊形的邊數 { dy=p[i+1].y-p[i].y; dx=(p[i+1].x-p[i].x)/dy; if(dy>0) //水平邊不考慮 { x=p[i].x; } else { x=p[i+1].x; } ymax=(Math.max(p[i].y,p[i+1].y));//肯定邊的上下端 ymin=(Math.min(p[i].y,p[i+1].y)); for (y=ymin+1; y<=ymax ; y++ ) { x=(int)(x+dx+.5); if(pixels[y*w+x]==blue)//邊界顏色藍色 { pixels[y*w+x+1]=blue; } else { pixels[y*w+x]=blue; } } } ImageProducer ip = new MemoryImageSource(w,h,pixels,0,w); //經過MemoryImageSource將數組中的像素產生一個圖像,w,h分別表其寬度和高度 image = createImage(ip); return image; }
步驟2:設in_flag是一布爾變量。對每一條掃描線從左到右進行搜索,若是當前是像素位於多邊形P內,則in_flag=true,須要填上值爲polygon_color的顏色;不然該像素在多邊形P外,須要填上值爲background_color的顏色。
//maxx、maxy、minx、miny是得到的多邊 形最小矩形包圍盒邊界值 public Image interior() { Image image; int maxx=150,minx=20,maxy=120,miny=20,l; for(y = miny - 1 ; y<= maxy ; y++) { in_flag = 0; //多邊形內部標誌變量 for( x = minx - 1; x<=maxx - 1; x++) { l = pixels[y*w+x];//得到當前像素顏色以判斷是不是邊界色 //多邊形邊界顏色blue if (l == blue) { if (in_flag == 0)//若是是邊界,且第一/三次碰到邊界,就置flag爲1,代表其後的象素要置成多邊形的顏色 { in_flag = 1; } else//若是是第二/四次遇到邊界,就置flag爲0,對其後的元素置背景色爲白色。 { in_flag = 0; } } if (in_flag==1) { pixels[y*w+x]=blue; } //在多邊形內部填充色藍色 else { pixels[y*w+x]=white; } } } }