文章版權由作者李曉暉和博客園共有,若轉載請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/
1.背景
在之前的博客中,我分別介紹了基於網格的空間索引(http://www.cnblogs.com/naaoveGIS/p/5148185.html)以及四叉樹和網格結合的聯合索引(http://www.cnblogs.com/naaoveGIS/p/6641449.html),要解決的問題均是判斷一個點落在了面圖層中的哪個面要素中。單從算法層面上分析,以上兩種索引均有一些弊端:
a.網格索引由於對整個空間進行網格划分,如果划分粒度太細容易出現索引冗余,如果划分粒度太大則索引效率又大幅度下降。
b.四叉樹索引同樣存在一個圖元標識被多個區域所關聯,相應地存儲在多個葉子節點上,這樣就存在索引的冗余,與網格索引存在同樣的弊端。
為進一步優化索引,我們決定采用R樹來進行優化。
2.R樹介紹
R樹主要運用空間分割的理念,即采用MBR(Minimal Bounding Rectangle,最小邊界矩形)的方法,從葉子結點開始用矩形(rectangle)將空間框起來,結點越往上,框住的空間就越大,以此對空間進行分割:
所有的原始空間要素均是葉節點,這樣便不會出現如四叉樹索引和網格索引中出現的空間要素被多個索引段指引,進而出現大量冗余索引的問題。
3.基於JTS的具體實現
JTS中提供了構建索引的方法,其可以構建四叉樹索引、R樹索引、KD索引等。這里,我們直接使用JTS來構建R樹索引。
JTS的介紹:https://en.wikipedia.org/wiki/JTS_Topology_Suite
JTS的源碼下載:https://sourceforge.net/projects/jts-topo-suite/?source=navbar
3.1R樹的構建
利用GT讀取到本地的SHP,獲取到所有的要素集,然后遍歷要素將envelope和要素信息一一插入至StrTree中,構建R樹:
3.2基於R樹的查詢
將查詢的空間條件構造成一個Envelope在R樹中查詢,對查詢出來的結果再次進行點面關系判斷:
4.優化
在我們之前的兩種索引方法中,我們均將索引文件保存到了本地,每次調用時去加載索引,如此IO是一個很大的瓶頸。現在我們創建一個容器,將StrTree保存至該容器中。查詢時,直接從內存中獲取到該樹。
5.效率對比
5.1查詢效率對比
在測試數據中選中一個特殊點(多個多邊形的交接處):
分別對使用的三種索引進行了性能對比:
a.本地網格索引:
b.本地混合索引(四叉樹與網格索引整合):
c.內存R樹索引:
可見查詢效率快了一倍左右。
5.2索引構建效率對比
樣本數據有2000多個面要素,之前的兩種索引均使用本地工具構建,時間大約是1S上下(沒有具體統計)。現在使用JTS構建R樹索引,效率為:
5.3占用的內存效率
此索引的優化中,我們將數據全部存入了內存。這里必須觀察內存的占用量有多大。
一般監控內存有兩種方式,通過工具查看或者代碼段編寫。代碼段編寫可以通過應用SizeOf.jar實現,工具查看可以通過jvisualvm實現:
原始的本地SHP數據大小為:3.8M。
網格索引大小為:4.4M。
混合索引文件的大小為:8.4M。
而讀入內存中的R樹索引的大小為:4.3M。
由於我們存儲了要素所包含的所有信息,理論上,如果我們將存儲信息進一步減少,內存占用會更小。目前來看,SHP數據本身的大小,會跟存入內存的信息大小有直接關系。
6.總結
目前索引方式任然有幾點不足:
a.索引構建中的要素獲取方式為本地SHP讀取,需要擴展成對第三方服務數據的支持。
b.當R數查詢命中只有一個要素時,因為最小矩形的范圍是大於等於實際要素范圍的,所以還要進行一次點面判斷。如此,當圖層要素個數本身不多時,建立索引不一定可以加速。
-----歡迎轉載,但保留版權,請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/
如果您覺得本文確實幫助了您,可以微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^