• geotrellis使用(三十二)大量GeoTiff文件实时发布TMS服务


    前言

    在上一篇文章中我讲了如何直接将Geotiff文件发布为TMS服务,在其中只讲了单幅Geotiff的操作,其实单幅这种量级的数据对Geotrellis来说就是杀鸡焉用牛刀,Geotrellis针对的是大数据量的操作。在进行完单幅Geotiff的操作后,就去出差了一周,这一周也没闲着,稍有空隙便在思索这个问题,并抽空写那么两行,回来一调试果然可以,于是就有了本文。下面我来介绍如何对大量Geotiff实时进行TMS服务化操作。

    一、总体效果

    上次使用的是北京首都国际机场影像数据,这次我又下载了部分北京市区影像数据,来看一下总体显示效果。

    二、实现方案

    总体思路如下:

    1. 判断当前请求瓦片的范围。
    2. 判断在此范围下有无Tiff文件。
    3. 若有则切割此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文件我们才需要进行切割,否则不进行操作,那么这里就牵涉三点:

    1. 获取所有需要切割的Tiff文件。
    2. 获取Tiff文件空间范围。
    3. 将上面得到的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

  • 相关阅读:
    3星|《土地制度与中国发展》:建国以来土地政策研究与分析,数据有点旧,观点都见过
    3星|《AI极简经济学》:AI的预测、决策、战略等方面的应用案例介绍
    4星|《哈佛商业评论》2018年第12期:海尔取消科层制比较成功
    房企大裁员;争议贺建奎;破产阴影下的ofo:4星|《财经》第29期
    3星|《数据资本时代》:数据会导致资本贬值,缺数据和实例证明
    3星|徐远《城里的房子》:国内一线城市核心区域的房价还会持续上涨
    5星|《伟大创意的诞生:创新自然史》:开放连接意外错误催生创意
    2星|《流量营销》:微信营销资料汇编,缺乏实战经验
    4星|《对赌:信息不足时如何做出高明决策》:赌徒概率思维最优
    5星|《大江大河》:改革开放前30年的商海故事(严重剧透)
  • 原文地址:https://www.cnblogs.com/shoufengwei/p/7496883.html
Copyright © 2020-2023  润新知