前言
在上一篇文章中我講了如何直接將Geotiff文件發布為TMS服務,在其中只講了單幅Geotiff的操作,其實單幅這種量級的數據對Geotrellis來說就是殺雞焉用牛刀,Geotrellis針對的是大數據量的操作。在進行完單幅Geotiff的操作后,就去出差了一周,這一周也沒閑着,稍有空隙便在思索這個問題,並抽空寫那么兩行,回來一調試果然可以,於是就有了本文。下面我來介紹如何對大量Geotiff實時進行TMS服務化操作。
一、總體效果
上次使用的是北京首都國際機場影像數據,這次我又下載了部分北京市區影像數據,來看一下總體顯示效果。
二、實現方案
總體思路如下:
- 判斷當前請求瓦片的范圍。
- 判斷在此范圍下有無Tiff文件。
- 若有則切割此Tiff文件並返回對應的瓦片。
2.1 判斷當前請求瓦片范圍
每次請求,前台會向后台發送一個需要的瓦片編號,包含zoom、x、y,根據這三個值以及當前地圖的投影方式我們就能算出此瓦片的空間范圍。代碼如下:
val key = SpatialKey(x, y)
val layoutScheme = ZoomedLayoutScheme(crs, tileSize = 256)
val layout = layoutScheme.levelForZoom(zoom)
val extent = MapKeyTransform(crs, LayoutLevel(zoom, layout.layout))(key)
其中crs表示地圖投影,多為WebMercator,最終得到的extent即位該瓦片在此投影下的空間范圍。
2.2 判斷在此范圍下有無Tiff文件
顯而易見,如果此范圍下有Tiff文件我們才需要進行切割,否則不進行操作,那么這里就牽涉三點:
- 獲取所有需要切割的Tiff文件。
- 獲取Tiff文件空間范圍。
- 將上面得到的extent與每一幅tiff的范圍進行相交判斷,若有交集則切割此瓦片。
- 獲取所有tiff文件。
文件存儲在HDFS中,傳入路徑,獲取其下所有文件即可。代碼如下:
val hdfsPath = new org.apache.hadoop.fs.Path(path)
val fs = FileSystem.get(new Configuration())
val files = fs.listStatus(hdfsPath)
其中path為HDFS中的目錄路徑。這樣就能得到該路徑下所有文件。
- 獲取Tiff文件空間范圍。
每一個Tiff文件都有一個范圍, 普通方式可以直接讀取Tiff文件的角點坐標等信息,在此我使用Geotrellis的方式來讀取。代碼如下:
val rdd = HadoopGeoTiffRDD.spatialMultiband(path)
val sm = rdd
.map { case (key, grid) =>
val ProjectedExtent(extent, crs) = key.getComponent[ProjectedExtent]
// Bounds are return to set the non-spatial dimensions of the KeyBounds;
// the spatial KeyBounds are set outside this call.
val boundsKey = key.translate(SpatialKey(0,0))
val cellSize = CellSize(extent, grid.cols, grid.rows)
HashMap(crs -> RasterCollection(crs, grid.cellType, cellSize, extent, KeyBounds(boundsKey, boundsKey), 1))
}
.reduce { (m1, m2) => m1.merged(m2){ case ((k,v1), (_,v2)) => (k,v1 combine v2) } }
.values.toSeq.head
val layoutScheme = ZoomedLayoutScheme(crs, tileSize = 256)
val layoutDefinition = layoutScheme.levelForZoom(zoom).layout
val tiffExtent = TileLayerMetadata[SpatialKey](
sm.cellType,
layoutDefinition,
sm.extent,
sm.crs,
sm.bounds.setSpatialBounds(layoutDefinition.mapTransform(sm.extent))
).extent
path為tiff文件路徑,這樣便能獲得當前tiff的空間范圍。
- 判斷瓦片與tiff是否相交。
extent.intersects(tiffExtent)
2.3 返回瓦片
在判斷此瓦片下有tiff文件后即可采用上一篇文章中講述的方式進行切割並返回瓦片。
三、總結
本文簡單講述了如何使用Geotrellis將大量Geotiff文件發布為TMS服務,針對大批量的數據才是Geotrellis的核心所在,然而只有也只要掌握了對單一數據的處理將能很快實現大批量的數據,所以“大數據”其實並沒有那么可怕。
Geotrellis系列文章鏈接地址http://www.cnblogs.com/shoufengwei/p/5619419.html