一種高效的基於線性四叉樹編碼的多級網格索引

2021-09-30 07:28:23 字數 2154 閱讀 3375

目前主流gis平台廠商的空間資料庫引擎,用的基本是四叉樹,r樹等索引,主要是供海量的空間資料儲存和顯示用的,以我的理解(我不負責空間資料引擎,了解有限),它們最重要的功能是:傳入乙個正交查詢區域(矩形),快速計算出所有被這個矩形包含的空間物件。這對於一般的應用也都可以滿足。

但是,在空間分析中,最通用的,比如空間查詢,就不是那麼回事了。特別是在大資料量下的,很多時候建空間索引的效果就不明顯。最主要的原因是,gis應有中的真實資料太**了,什麼形狀的都有,特別是面資料,動不動就是成千上萬個點,成百上千個子物件(也就是麵中有小洞),對於這種面,如果只對它們的的最小外包矩形(mbr--minimum bounding rectangle)建立索引,是沒有多大作用的。即使空間物件的mbr相交了,也不能表示他們一定相交。而且,天知道這個麵裡包含了多少個洞,就算是有查詢物件的mbr完全落在被查詢面的mbr中,也不能說明被包含了,如果不小心落在洞裡面的話。

對於空間查詢來說,該功能要非常精確查詢出查詢物件與被查詢物件之間的包含,被包含,相交等空間關係。注意:是非常精確,比如包含查詢,哪怕有一點點邊界相交都不行!這就很麻煩了,如果是大範圍的面查詢面,那只能是將所有與查詢面的mbr相交的被查詢面,乙個乙個的和查詢面進行是否包含的判斷(先判斷兩面邊界是否相交,如果不想交,在判斷內點是否被包含)。當被查詢面特別多時,這將非常耗時間。特別是如果資料不是儲存在本地時,每次都要先將資料讀到本地,分析過程中相當部分時間都在讀資料,cpu佔用率幾乎為0,特別是很多離被查詢面邊界很遠的物件,明顯包含(或相離),也參與運算,太痛苦了。如果能設計一種索引,能準確的「知道」空間資料的資料分布情況以及鄰近關係,這樣,每次在分析時,都能過濾掉大部分與明顯合法/非法的資料,只對那些挨得很近的、需要精確計算的資料進行分析操作,這樣就加快分析速度了。我是出於這種想法,開始做這個多級網格索引的。

在介紹多級網格索引之前,先了解下什麼是網格索引和四叉樹索引。網格索引是最常用的空間索引之一,每次都將所有空間資料集合的mbr劃分為m*m個的網格,對於每個網格,如果有空間物件的邊界經過,則記錄下該空間物件的資訊。大概就這樣,簡單吧~,這種索引是我開發中最常用到的(這兩年工作體會最深的是,在處理大資料量時,越簡單的資料結構往往越高效,更重要的是易於維護)。四叉樹索引是經典的基於mbr的空間索引,我就懶得寫了^_^。它們兩者的最大區別是,網格索引是為空間資料本身建立索引,而四叉樹索引是為空間資料的mbr建立索引!下面是我在網上看到的鏈結,感覺講的很好,簡明扼要的介紹了兩種索引的原理及其在gis中的應用(熟悉gis空間索引的同學可以略過):

網格索引介紹:  

四叉樹索引介紹:

我最初的想法是這樣的:擴充套件網格索引,使之能標示出面對像的內部包含的網格。但是這麼做有個問題,如果面對像特別大,它對應的內部網格就會很多,如果面內部全都用小網格填充的話,將導致索引的儲存空間過大。於是又想,能不能結合四叉樹索引,建立多層網格索引,比如劃分十層網格就是:

第一層 將原資料集mbr劃分為 1*1個網格,

第二層 將原資料集mbr劃分為 2*2個網格,

第三層 將原資料集mbr劃分為 4*4個網格,

第三層 將原資料集mbr劃分為 8*8個網格,

第十層 將原資料集mbr劃分為 1024*1024個網格

對於不同層級的網格索引,使用線性四叉樹編碼進行管理,使得相鄰網格之間可以跨層級查詢,並統一儲存在一維陣列中。對於大的面,如果是邊界經過的網格,用盡可能小的面對像去標示,而對於內部網格,則用盡可能大的網格去填充它,這樣,既達到了同樣的效果,又極大的節省了儲存空間。在做空間查詢時,可以利用物件的網格之間的相互關係,過濾掉沒必要參與運算的網格索引。例如:

如果被查詢物件完全落在查詢面的內部網格中,則肯定被包含;

如果被查詢物件的網格與查詢面的網格沒有交集,則肯定相離;

如果被查詢物件的內部網格(邊界網格)經過查詢物件的邊界網格(內部網格),則肯定相交;

這樣一來,空間查詢的效能就能提高了,畢竟,很多情況下,需要做精確幾何運算的資料,還是不多的。以下就是我的多級網格索引實驗效果截圖。

圖1:簡單面物件

圖2:簡單面物件建立多級網格索引後的效果

圖3:複雜面物件

圖4:複雜面物件建立多級網格索引後的效果

如圖所示,對該複雜面對像建立多級網格索引後,網格的數目並沒有隨著點數的增加而增加,相反,相對於上面的簡單面的網格索引,複雜面的網格數目要更少一些。這是多級網格索引的優點之一:網格索引的大小與空間物件的大小無關,與空間物件的外形有關,它真實反映出空間資料的分布狀況,點越也密集的地方,網格越密,點稀疏的地方網格稀疏。

Python實現 建立四叉樹 的一種方法

我們想要使用一棵四叉樹來儲存乙個n x n的布林值網路。網路中每一格的值只會是真或假。樹的根結點代表整個網路。對於每個結點,它將被分等成四個孩子結點直到這個區域內的值都是相同的.每個結點還有另外兩個布林變數 isleaf和val。isleaf當這個節點是乙個葉子結點時為真。val變數儲存葉子結點所代...

中文編碼的一種用法

這裡通過乙個測試某些ip位址是否為特定 的例子來說明。我們假設該 的編碼用的是gb2312,並通過獲取該 的title作為檢測依據。usr bin env python encoding utf 8 略去獲取網頁的 re.ignorecase title 論壇標題 m re.search title...

一種高效的 vector 四則運算處理方法

這裡假設 vector 的運算定義為對運算元 vector 中相同位置的元素進行運算,最後得到乙個新的 vector。具體來說就是,假如vectord1,d2 則,v1 v2等於。實現這樣的運算看起來並不是很難,乙個非常直觀的做法如下所示 vector operator const vector v...