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

目录

  1. 前言
  2. 需求说明
  3. 实现方案
  4. 总结

一、前言

       最近一段时间比较忙,没能继续推进Geotrellis项目开发,周末和这两天抽空又实现了一个功能——导出自定义的Tiff文件。又恰巧碰上今天这么重要的日子,当然要写点东西来纪念一下,所以就有了这篇文章,闲话莫说,进入正题。

二、需求说明

       很多时候我们需要从一块(或者很多块)大的Tiff中根据需要截取一部分数据,并且需要采用某种采样方式转成特定的投影,并转成需要的数据类型。当然有人会说这个很容易,用GDAL的gdaltransform等可以很容易的实现此功能,GDAL是很强大,但是前提是你的数据不能太大并且只能处理单块栅格数据。正因为有这些问题,所以我实现了使用Geotrellis来实现该功能,下面我就为大家分析实现方法。

之前讲了很多数据处理方式,其中。

三、实现方案

1.前台界面

       前台就是一个简单的地图控件,外加几个选择器。地图控件主要为了浏览区域以及手工选取想要导出的Tiff的范围,选择器主要选择目标投影方式、数据类型以及采样方式。根据用户的选择将请求采用ajax的方式发送到后台进行处理。这块不是本文的重点,不在这里具体介绍。

2.数据导入

       要想处理大数据或者处理多块栅格数据就不能直接处理栅格数据,可以先将栅格数据导入到Accumulo中,当然导入之后是一块块的瓦片,这部分在geotrellis使用(三)geotrellis数据处理过程分析一文中已经进行了详细介绍,这里还是要说明的是参数layoutScheme一定要选择floating,这样在Accumulo中保存的就是原始只是切割而未经过其他处理的数据。

3.读取数据

       Accumulo中已经存储了需要的数据,并且后台接收到了前台用户选择的区域范围以及投影方式、数据类型、采样方式,这样我们就可以开始实现读取需要的数据,简单的说就是从Accumulo中取出与用户选定区域有交集的数据(瓦片),实现代码如下:

val raster = reader.read[SpatialKey, Tile, TileLayerMetadata[SpatialKey]](layerId)
val masked = raster.mask(polygon)

       是不是很容易,就这两句话,其中reader是AccumuloLayerReader实例,layerId表示读取的层,polygon是用户选取的范围。首先从Accumulo中读出该层数据,然后与polygon做一个mask,得到的结果就是用户想要导出的数据。

4.数据转换

4.1 得到结果瓦片数据

       首先将上述得到的瓦片集做一个拼接,这样就会得到一个大的瓦片,代码也很简单,如下:

val stitch = masked.stitch
val tile = stitch.tile

4.2 得到最终结果

       之后要做的就是根据采样类型、投影方式以及数据类型将上述tile进行转换,代码如下:

val rep = tile.reproject(extent, srcCRS, dstCRS, method).tile
val res = rep.convert(cellType)

       其中extent是瓦片的范围,可以用上述拼接对象stitch的stitch.extent得到,srcCRS是原始数据的投影类型,可以通过上述raster对象的raster.metadata.crs得到,dstCRS表示目标投影方式,即用户想要的投影方式,同样method表示采样方法,cellType表示数据类型,这三个的获取方式我会重点介绍。

4.3 获取dstCRS、resampleMethod、cellType

       首先可以肯定的是前端传来的这三个参数都是字符串型的,这就要求后台将字符串转成相应的类型。

       投影方式我这里投了个懒,传递的是EPSG CODE,EPSG是投影方式的一种数字编码,具体请见:http://www.epsg.org/。总之每一个EPSG编码对应了一种投影方式,像常见的经纬度投影的编码是4326,WebMercator的编码是3857。有了这个编码之后就可以很容易的得到投影方式,代码如下:

try{
CRS.fromEpsgCode(epsg)
}
catch {
case _ => CRS.fromEpsgCode(3857)
}

       采样方式和数据类型就稍显麻烦,我这里采用了反射的方式获取对应实例,我将反射的代码进行了封装,代码如下L:

def getClassName(name: String, hasEndWith$: Boolean) = {
var className = name
if (hasEndWith$) {
if (!className.endsWith("$"))
className += "$"
}
else {
if (className.endsWith("$"))
className = className.substring(0, className.length - 1)
}
className
} def getClassFor[T: ClassTag](name: String, hasEndWith$: Boolean) = {
val className = getClassName(name, hasEndWith$)
Try[Class[_ <: T]]({
val c = Class.forName(className, false, getClass.getClassLoader).asInstanceOf[Class[_ <: T]]
val t = implicitly[ClassTag[T]].runtimeClass
if (t.isAssignableFrom(c)) c else throw new ClassCastException(t + " is not assignable from " + c)
})
} def getInstanceByReflact[T: ClassTag](name: String) = {
val classTry = getClassFor[T](name, true) recoverWith { case _ => getClassFor[T](name, false) }
classTry flatMap{
c =>
Try{
val module = c.getDeclaredField("MODULE$") //通过获得变量"MODULE$"来初始化
module.setAccessible(true)
val t = implicitly[ClassTag[T]].runtimeClass
module.get(null) match {
case null => throw new NullPointerException
case x if !t.isInstance(x) => throw new ClassCastException(name + " is not a subtype of " + t)
case x: T => x
}
} recover{ case i: InvocationTargetException if i.getTargetException ne null => throw i.getTargetException }
}

       这段代码看上去很复杂,其实是做了很多判断加强程序稳定性用的的,主要功能就是一个类的全名(包含包名)创建其实例。

       有了上述代码之后就可以将前台传来的字符串直接转换为相应的实例,获取采样方式的代码如下:

val resample = s"geotrellis.raster.resample.${resampleStr}"
val method = getInstanceByReflact[ResampleMethod](resample)
if(method.isSuccess) {
println(method.get.toString)
method.get
}
else {
Bilinear
}

       前台只需传入采样方式名称即可,如Bilinear,这样就会自动获取其实例。

       获取数据类型同理,代码如下:

val className = getCellTypeClassName(dataTypeStr)
val cellType = getInstanceByReflact[CellType](className)
if(cellType.isSuccess) {
cellType.get
}
else {
ByteConstantNoDataCellType
}

       这样就可实现获取用户想要的投影方式、采样方法以及数据类型。

四、总结

       以上就是使用Geotrellis实现导出定制的GeoTiff的方法,由于时间紧,可能还有很多没有注意的细节,会在后续中进一步研究,并更新该文或者另设新篇。在这里我也呼吁大家都来撰写技术博客,一来提高自己,进行技术总结;二来真的是可以帮助别人。最近在工作中碰到很多莫名其妙的BUG,但是基本都在一番搜索之后在别人的博客中找到了解决方案,所以在此也感谢那些愿意写博客的人,希望大家都能加入进来。

geotrellis使用(十四)导出定制的GeoTiff的更多相关文章

  1. SpringBoot入门教程(十四)导出Excel

    用JavaPOI导出Excel时,我们会考虑到Excel版本及数据量的问题.针对不同的Excel版本,要采用不同的工具类.HSSFWorkbook:是操作Excel2003以前(包括2003)的版本, ...

  2. geotrellis使用(四)geotrellis数据处理部分细节

    前面写了几篇博客介绍了Geotrellis的简单使用,具体链接在文后,今天我主要介绍一下Geotrellis在数据处理的过程中需要注意的细节,或者一些简单的经验技巧以供参考. 一.直接操作本地Geot ...

  3. WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇)

    原文:WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]在.NE ...

  4. spring boot 常见三十四问

    Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一 Spring Boot.Spring MVC 和 Spring 有什么区别 ...

  5. 我的MYSQL学习心得(十四) 备份和恢复

    我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...

  6. SNF开发平台WinForm之十四-站内发送系统信息-SNF快速开发平台3.3-Spring.Net.Framework

    1运行效果: 2开发实现: .组装站内信息发送实体对象. SNFService SNFService = new SNFService(); if (this.ucUser.SelectedIds ! ...

  7. 《sed的流艺术之四》-linux命令五分钟系列之二十四

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  8. 从零开始学习PYTHON3讲义(十四)写一个mp3播放器

    <从零开始PYTHON3>第十四讲 通常来说,Python解释执行,运行速度慢,并不适合完整的开发游戏.随着电脑速度的快速提高,这种情况有所好转,但开发游戏仍然不是Python的重点工作. ...

  9. 实验十四 第九组 张燕~杨蓉庆~杨玲 Swing图形界面组件

    实验十四  Swing图形界面组件 8-11-29 理论知识 Swing和MVC设计模式 (1)设计模式(Design pattern)是设计者一种流行的 思考设计问题的方法,是一套被反复使用,多数人 ...

随机推荐

  1. elasticsearch常用的概念整理

    节点node 节点(node)是一个运行着的Elasticsearch实例 集群中一个节点会被选举为主节点(master),它将临时管理集群级别的一些变更,例如新建或删除索引.增加或移除节点等.主节点 ...

  2. 【noip】noip201503求和(市赛后公布)

    3. 求和 难度级别:B: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 题目描述   一条狭长的纸带被均匀划分出了n个格子,格子编号从1到n.每个格子 ...

  3. css确定元素水平居中和垂直居中

    ---恢复内容开始--- 首先,我们在了解如何通过css了解元素水平和垂直居中之前,先要了解下html都有哪些元素,这些元素与偶有哪些分类,因为不同类别的元素的水平垂直居中方法是完全不同的,究其根本当 ...

  4. linux内核分析作业8:理解进程调度时机跟踪分析进程调度与进程切换的过程

    1. 实验目的 选择一个系统调用(13号系统调用time除外),系统调用列表,使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 分析汇编代码调用系统调用的工作过程,特别是参数的传递的方 ...

  5. SQL Server2014 哈希索引原理

    SQL Server2014 哈希索引原理 翻译自:http://www.sqlservercentral.com/blogs/sql-and-sql-only/2015/09/08/hekaton- ...

  6. 性能分析工具-PerfView

    Roslyn的PM(程序经理) Bill Chiles,Roslyn使用纯托管代码开发,但性能超过之前使用C++编写的原生实现,这有什么秘诀呢?他最近写了一篇文章叫做<Essential Per ...

  7. 利用SSH Filesystem实现远程文件系统

         远程文件系统的访问有很多种不同的实现方式,一些常见的连接方式比其它特定情况下的更有用.最著名的一个例子就是微软的通用互联网文件系统(CIFS),它可以容许微软Windows"映射网 ...

  8. 30分钟全面解析-SQL事务+隔离级别+阻塞+死锁

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化.  本系列主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础] ...

  9. JS实战 · 复选框全选操作

    思路: 1.获取被选中checkbox,通过checked属性的状态完成: 2.获取被选中的checkbox的value值: 3.求所有value的和sum: 4.定义span区域存储和sum:   ...

  10. Linux更改用户密码

    登录虚拟机后,使用passwd密令更改用户密码,新密码需要输入两次才能更改成功.不多说,直接上代码 [root@localhost Desktop]# passwd //使用passwd密令 Chan ...