Grass Gis 峽谷堰塞湖預測模型r.lake剖析--湖心灌水洪泛算法

Grass Gis 是20世紀80年代初,美國軍方建築工程研究實驗室(USA/CERL)的Bill Gorgan負責遴選一款具有土地管理、環境規劃、環境評估的GIS軟件。它有400多個地質分析模塊,今天我們剖析一下r.lake算法。


1. 堰塞湖預測建模r.lake能做什麼

如下圖1左爲一張地形柵格圖,也是最常見的2D平面圖。從圖中可以看到許多的凹地盆地,當有山洪暴雨時就會形成堰塞湖。 Grass Gis 的r.lake就是能夠預測堰塞湖形狀大小的模塊。例如,在圖1左所示的紅色圓圈位置開始注水當水位海拔高度爲113.4米時,形成的堰塞湖的位置形狀如圖1右所示。Grass可以形成動畫動態展示不斷的提高水位後堰塞湖形態的變化。


我國長江三峽大壩水位設計海拔185米,蓄水庫區淹沒129座城鎮,淹沒耕地1.94萬公頃東起宜昌,西至重慶662.9Km沿長江兩岸分水嶺範圍。在設計時就需要對185米高湖所能淹沒的地區有非常精確的預測,如果沿岸有缺口造成計劃外的地區被淹沒就需要處理缺口。


Grass Gis 的r.lake 就可以完成這個事情,它的核心算法就是“湖心灌水洪泛算法“,它模擬了水在一點不斷湧出時淹沒了周邊地區。



圖1 堰塞湖預測模型演示


2. 數據降維簡化模型

當一個點開始蓄水時,周邊山嶺的高度和形態都可以阻擋洪水的進一步蔓延,就像一個圍欄一樣。那怎樣才能根據水位的海拔高度找出這些圍欄的位置?首先想到的是三維建模以及空間關係計算等複雜的方式,其實不然。所有複雜的三維空間計算都要降維到二維平面計算,簡化計算。


一個地區的遙感影像被處理成高程圖也就是柵格圖後,就變成了一個標準的M*N的數字矩陣。矩陣的每個點對於地圖上的一個矩形區域,該點的值就是該區域的平均高度。圖1就是這樣的一個二維柵格圖,只是每個像素被賦予不同的灰度顏色展現出來。一個複雜的三維地勢圖化簡爲矩陣後就變成了如圖2a所示的二維數組,圖中的數字爲某塊土地的海拔。


圖2 柵格地圖數據矩陣 (上圖excel設計底稿下載)


當要求堰塞湖水位海拔9米時,滿足條件的區域如圖2b所示的三塊區域。這樣問題好像看起來非常簡單了, 就是把數組遍歷一遍找出<=9的區域不就行了?但是複雜的問題來了,當洪水爆發點在 6C 點,那9米的水只能在紅色區域聚集成堰塞湖,黃色和藍色都不應該被淹沒,因爲水被紅色區域周圍20多米高的地勢擋住了。


現在的問題已經被簡化成了一個簡單的數據結構算法了。以 6C 點逐漸嚮往擴張,就像湖心有洪水不斷湧出直到把周圍的相鄰8個格子中低於9米的區域淹沒。6C爲湖心的周邊5B,5C,5D,6B,6D,7B,7C,7D被淹沒了。接着以它們爲湖心重複相同的操作,嘗試淹沒周圍的8個鄰居區域。不斷重複直到沒有新的可淹沒區域被找到。這個算法很簡單,就不給出代碼了。


3. 以一個或多個堰塞湖區爲洪水點

 Grass Gis 的r.lake提供了更爲複雜的建模。不是以某個點爲洪水發生地,而是以某個湖區在湧出洪水,甚至多個湖區一起湧出。這樣每次都以上一輪模擬輸出的湖區爲下次模擬計算的輸入,不斷增高湖水高度,達到動畫效果輸出。


這個算法思想和上面單點的算法相似,只是每輪需要掃描M*N個像素點,每次是旁邊8個區域只要有一個有水的點就試圖向自己淹沒,直到一輪沒有新的擴張點就停下來。

</pre><p><pre name="code" class="cpp">int pases = (int)(rows * cols) / 2;
int  water_level = .... // 輸入的要求的湖面海拔高度
int *in_terran; // row * col 輸入的柵格地圖,數值爲地勢的海拔高度
int *in_wanter; // row * col 輸入的已經有水的湖區矩陣. 0無水,>0 爲湖水平面到湖底的深度
int *out_water; // row * col 輸出計算完畢的湖區矩陣. 初始爲0無水,>0 爲湖水平面到湖底的深度
copy_seed_water(in_wanter, out_water); // 初始輸出湖區爲輸入湖區
int water_window[3][3]; // 某點爲中心的3*3矩陣窗口,該窗口沿着地圖每個點移動一遍爲一趟

for (pass = 0; pass < pases; pass++) 
{
	curcount = 0;
	/* 每個點掃描 */
	for (row = 0; row < rows; row++) 
	{
	    for (col = 0; col < cols; col++) 
		{
			//該點爲中心去3*3矩陣
			load_neibour_window_values(out_water, water_window, rows, cols, row, col); 
			//該點周圍8個鄰居是否有水往自己這邊淹沒
			if (is_near_water(water_window) == 1) 
			{
				if (in_terran[row][col] < water_level) 
				{
					// 該地勢低,被淹沒
					out_water[row][col] =  water_level - in_terran[row][col];
					curcount++;
				 }
				 else 
				 {
					out_water[row][col] = 0;	/* 該地勢比湖水面高 */
				 }
			}
	    }
	}
	if (curcount == lastcount)
	    break;		/* 沒有發現新的淹沒點,完成. */
	lastcount = curcount;
	curcount = 0;
	}
}

return out_water;



4. Grass Gis平臺提供的服務支持

上面的算法沒有看到任何Grass Gis 平臺API的使用。其實柵格數據的輸入,輸出和圖形化顯示都是透明的交給了grass 平臺了。向湖區的梯度漸變顏色表的建立就是調用API並綁定湖區地圖的,但是開發人員並不知道該顏色表是怎樣存儲並綁定的。它提供的功能包括:

  • 各種地質地圖數據文件在內存中的直接訪問
  • 處理完成的地質數據向grass數據庫的內存直接寫
  • 地質地圖顏色表的生成並綁定
  • 多個地質地圖的三維疊加顯示
  • 統一管理用戶設定的的數據空間範圍
所以使用Grass Gis 平臺的優勢就是使用它的數據存儲基礎服務,用戶關心的空間範圍和顯示服務,把所有精力都集中在算法本身上面。對地址空間的處理操作並不提供現成的服務。

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。



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