在上篇博客(geotrellis使用初探)中簡單介紹了geotrellis-chatta-demo的大致工作流程,但是有一個重要的問題就是此demo如何調取數據進行瓦片切割分析處理等並未說明,經過幾天的調試、分析、源代碼研讀終於大致搞明白了其數據調取方式,下面簡單介紹。
經過調試發現系統第一次調用數據的過程就是系統啟動的時候調用了initCache方法,明顯可以看出此方法是進行了數據緩存,那必然牽扯到數據的調取,整個過程清晰明了,只新建了一個RasterSource類,並調用了相關方法。明顯數據調取過程應當是使用了RasterSource類,RasterSource是一個object類,新建過程調用了其一個apply方法:
def apply(name: String): RasterSource =
RasterSource(LoadRasterDefinition(LayerId(name)), None)
此方法其實調用了另一個方法
def apply(rasterDef: Op[RasterDefinition], targetExtent: Option[RasterExtent]): RasterSource = { val (rd, tileOps) = targetExtent match { case reOp @ Some(re) => ( rasterDef.map(_.withRasterExtent(re)), rasterDef.map { rd => Seq(LoadRaster(rd.layerId, reOp)) } ) case None => ( rasterDef, rasterDef.map { rd => (for(tileRow <- 0 until rd.tileLayout.layoutRows; tileCol <- 0 until rd.tileLayout.layoutCols) yield { LoadTile(rd.layerId, tileCol, tileRow) }) } ) } new RasterSource(rd, tileOps) }
由此可以看出LoadRasterDefinition(LayerId(name))完成的就是獲取一個Op[RasterDefinition]對象。
通過此方法經過N步的追蹤之后終於在DataSource類中找到了這么一個方法
def getRasterLayer(name:String):Option[RasterLayer] = layers.get(name)
有戲,看方法名字就知道是獲得柵格層,那么主要就在layers身上了,layers怎么來的呢,上面有定義
private def initDirectory(d:File) { val skipDirectories = mutable.Set[String]() for(f <- d.listFiles .filter(_.isFile) .filter(_.getPath.endsWith(".json"))) { // It's a JSON file // which may contain layer metadata, // or we just ignore it. RasterLayer.fromFile(f) match { case Success(layer) => layers(layer.info.id.name) = layer // Skip the tile directory if it's a tiled raster. layer match { case tl:TileSetRasterLayer => skipDirectories.add(new File(tl.tileDirPath).getAbsolutePath) case _ => } case Failure(e) => System.err.println(s"[ERROR] Skipping ${f.getPath}: $e") } } // Recurse through subdirectories. If a directory was marked // as containing a tile set, skip it. for(subdir <- d.listFiles .filter(_.isDirectory) .filter(f => !skipDirectories.contains(f.getAbsolutePath))) { initDirectory(subdir) } }
看到這個是不是就豁然開朗了,原來這里是直接掃描給定的文件夾下的所有json文件,那么這個路徑是怎么傳進來的呢?找了半天未能找到何時傳入了d(即數據路徑),不過改變demo中的data文件夾的名字發現報錯,並未能成功加載數據,說明是某個地方傳入了該文件夾,然后通過查找log發現是GeoTrellis類中報的錯,通過分析可以看出其默認獲取resource文件夾中的application.conf中的
geotrellis.catalog配置信息,該信息的值為data/catalog.json,此文件具體存在,其中內容如下
{
"catalog": "Catalog of Chattanooga data",
"stores": [
{
"store": "chatta:albers",
"params": {
"type": "fs",
"path": "arg_albers",
"cacheAll": "yes"
}
},
{
"store": "chatta:wm",
"params": {
"type": "fs",
"path": "arg_wm",
"cacheAll": "yes"
}
}
]
}
由此可以看出該文件完成了Catalog類和DataSource類定義的實例,而上文中講到框架正是通過此類來加載數據。
這應當就是GeoTrellis框架讀取數據的方式,即在application.conf配置一個catalog.json文件的地址,然后在catalog.json文件記錄具體的DataSource信息,通過此信息來獲取數據。
通過分析使用GeoTrellis框架下的多個demo可以發現均有catalog的蹤跡,這應當是GeoTrellis讀取數據的機制,catlog具體的工作模式還需后續繼續研讀源代碼。
本文講的比較亂,只是讀demo的一點心得,后續如果有更好的想法也會隨時進行修改完善。
下一步准備在此demo的基礎上實現實時切割dem數據進行顯示,后續心得會在總結之后繼續發布到博客中。
相關鏈接:
一、geotrellis使用初探
二、geotrellis使用(二)geotrellis-chatta-demo以及geotrellis框架數據讀取方式初探