geotrellis使用(十七)使用缓冲区分析的方式解决单瓦片计算边缘值问题

Geotrellis系列文章连接地址http://www.cnblogs.com/shoufengwei/p/5619419.htmlhtml

目录

  1. 前言
  2. 需求分析
  3. 实现方案
  4. 总结

1、前言

       最近真的是日理千机,可是再忙也要抽出时间进行总结。上一篇文章讲了使用缓冲区分析的方式解决投影变换中边缘数据值计算的问题(见geotrellis使用(十六)使用缓冲区分析的方式解决投影变换中边缘数据值计算的问题)。实际中每每还有一种需求就是对单个瓦片进行操做,好比求坡度等,若是这时候直接计算,一样会出现边缘值计算的问题,这种状况也可使用上一篇文章中讲到的方法进行处理。算法

2、需求分析

       假如咱们想在前台地图中实时显示坡度图像,有两种方式:第一种是在DEM数据导入Accumulo以前先求坡度(可使用传统的GDAl、也可使用Geotrellis),而后再导入;第二种是直接将DEM数据导入Accumulo中,后台实时计算每幅瓦片的坡度,而后渲染到前台。两种方式各有各的好处,采用第一种方式,总体处理简单,显示的速度快,可是Accumulo中要存两份数据。第二种方式,实现起来稍显复杂,显示的速度稍慢,可是Accumulo中只存了一份数据。因为Geotrellis基于Spark集群,因此若是集群足够优秀,处理速度不是很重要的问题,可是若是咱们须要对同一个数据进行多种操做,或者根据用户的需求来进行操做,那么就没有办法完成数据的预处理工做,只能进行实时计算,若是计算只针对瓦片中的单一像素则还不涉及到边缘值的问题,而若是须要进行插值采样等操做(如求坡度、山影等),这时候就会出现上文中讲到的瓦片边缘值计算的问题。本文就为你们讲解如何使用缓冲区分析的方式解决单瓦片计算边缘值问题。函数

3、实现方案

       至于求坡度等的具体算法不在这里介绍,都是很成熟的算法,而且Geotrellis中也已经实现了一些算法,只需调用相应的函数便可。有关缓冲区分析等也在以前的文章介绍过屡次,不在这里赘述。优化

1.数据读取scala

       此处读的数据为没有进行过任何处理的原始DEM数据,具体读写数据也在以前的文章中介绍过,详情见geotrellis使用(三)geotrellis数据处理过程分析等文章。code

       可是此处不一样的是咱们为了完成边缘值计算,就须要将单幅瓦片周围的八幅瓦片同时读入,即须要读9幅瓦片,这个咱们只须要根据当前瓦片的key值算出周围瓦片key值,而后逐一读取便可。获取9幅瓦片key值的代码以下:htm

val keys = 
for (i <- -1 to 1; j <- -1 to 1)
    yield {
        val col = key.col + i
        val row = key.row + j
        SpatialKey(col, row)
      }

       逐一读取瓦片代码以下:blog

val tiles =
keys.map { k =>
  tileReader.reader[SpatialKey, Tile](layerId).read(k)
}

       其中tileReader为AccumuloValueReader实例,layerId包含当前数据存放layer以及层级zoom。ip

       将9幅瓦片拼接成1幅瓦片代码以下:ci

val pairs = keys zip tiles
val pieces = pairs.map { case (key, tile) => tile ->((key.col - mincol) * 256, (key.row - minrow) * 256) }
implicitly[Stitcher[Tile]].stitch(pieces, 256 * 3, 256 * 3)

       其中mincol为keys中的col最小值,minrow为keys中的row最小值,循环遍历keys便可求出。这样就实现了将9幅瓦片拼成1幅,完成数据读取工做。

2.瓦片处理

       上一步获得了拼接好的“大瓦片”,这里在Geotrellis中与以前的“小瓦片”同样的都是Tile实例,采用与以前数据处理相同的处理方式便可,惟一须要注意的是瓦片不在是256*256,而变成了原来的3倍。处理完以后原来边缘值计算有问题的地方,这样就被巧妙的避开了。

3.裁剪结果

       数据处理完以后下一步要作的就是将瓦片从新裁剪成256*256。实现代码以下:

val startcol = tile.cols / 2 - 256 / 2
val startrow = tile.rows / 2 - 256 / 2
val endcol = tile.cols / 2 + 256 / 2 - 1
val endrow = tile.rows / 2 + 256 / 2 - 1
tile.crop(startcol, startrow, endcol, endrow)

       由于要从“大瓦片”的中间取出256*256像素,因此须要按照上面的公式求出开始以及结束的像素偏移。这样就获得了边缘值没有问题的瓦片。

4、总结

       以上就是经过使用缓冲区分析的方式解决单瓦片计算边缘值问题。有些地方还能够优化,好比取的时候不要取9幅瓦片,只取比当前瓦片稍微向外扩展几个像素值等,具体由读者自行思考。

相关文章
相关标签/搜索