geotrellis使用(十四)导出定制的GeoTiff
Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html
目录
一、前言
最近一段时间比较忙,没能继续推进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的更多相关文章
- SpringBoot入门教程(十四)导出Excel
用JavaPOI导出Excel时,我们会考虑到Excel版本及数据量的问题.针对不同的Excel版本,要采用不同的工具类.HSSFWorkbook:是操作Excel2003以前(包括2003)的版本, ...
- geotrellis使用(四)geotrellis数据处理部分细节
前面写了几篇博客介绍了Geotrellis的简单使用,具体链接在文后,今天我主要介绍一下Geotrellis在数据处理的过程中需要注意的细节,或者一些简单的经验技巧以供参考. 一.直接操作本地Geot ...
- WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇)
原文:WCF技术剖析之十四:泛型数据契约和集合数据契约(下篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]在.NE ...
- spring boot 常见三十四问
Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一 Spring Boot.Spring MVC 和 Spring 有什么区别 ...
- 我的MYSQL学习心得(十四) 备份和恢复
我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...
- SNF开发平台WinForm之十四-站内发送系统信息-SNF快速开发平台3.3-Spring.Net.Framework
1运行效果: 2开发实现: .组装站内信息发送实体对象. SNFService SNFService = new SNFService(); if (this.ucUser.SelectedIds ! ...
- 《sed的流艺术之四》-linux命令五分钟系列之二十四
本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...
- 从零开始学习PYTHON3讲义(十四)写一个mp3播放器
<从零开始PYTHON3>第十四讲 通常来说,Python解释执行,运行速度慢,并不适合完整的开发游戏.随着电脑速度的快速提高,这种情况有所好转,但开发游戏仍然不是Python的重点工作. ...
- 实验十四 第九组 张燕~杨蓉庆~杨玲 Swing图形界面组件
实验十四 Swing图形界面组件 8-11-29 理论知识 Swing和MVC设计模式 (1)设计模式(Design pattern)是设计者一种流行的 思考设计问题的方法,是一套被反复使用,多数人 ...
随机推荐
- 理解AUC
本文主要讨论了auc的实际意义,并给出了auc的常规计算方法及其证明 转载请注明出处:http://www.cnblogs.com/van19/p/5494908.html 1 ROC曲线和auc 从 ...
- java web(六)多个请求对应一个Servlet
概要: 提交请求的常用方式有两种,get/post , 运行程序后被请求,在加载执行web.xml文件时通过该文件中的映射关系找到即将要执行的Servlet; 而在要执行的Servlet文件中可通过反 ...
- iOS 添加中文支持的操作
1.选择工程菜单,这里要选中Project,而不是Targets 2.点击Info菜单, 下拉到最后,看到Localizations. 点击+号. 3.选择中文 chinese-simplif ...
- Android中数据存储(一)
国庆没有给国家添堵,没有勾搭妹子,乖乖的写着自己的博客..... 本文将为大家介绍Android中数据存储的五种方式,数据存储可是非常重要的知识哦. 一,文件存储数据 ①在ROM存储数据 关于在ROM ...
- Oracle CDC配置案例
异步部署 1. 环境的配置准备 1.1. 数据库版本 SQL> select * from v$version; BANNER ------------------------------ ...
- MySQL5.6 GTID新特性实践
MySQL5.6 GTID新特性实践 GTID简介 搭建 实验一:如果slave所需要事务对应的GTID在master上已经被purge了 实验二:忽略purged的部分,强行同步 本文将简单介绍基于 ...
- Algorithm | Binary Search
花了半天把二分查找的几种都写了一遍.验证了一下.二分查找的正确编写的关键就是,确保循环的初始.循环不变式能够保证一致. 可以先从循环里面确定循环不变式,然后再推导初始条件,最后根据循环不变式的内容推导 ...
- EF遇到的一些问题
环境:EntityFramework 版本号:4.1.0.0 问题一:“数据读取器与指定的“.......”不兼容.某个类型为“...”的成员在同名的数据读取器中没有对应的列.”. 使用方式:rep. ...
- 从Facebook跑来阿里的赵海平大叔,你要干啥?
赵海平在今年三月份来到阿里,听毕玄(他现任主管)说去年五六月份就跟赵海平聊上了.有人问:为啥 BAT 三大巨头,你看中了阿里巴巴?在今天现场达一千多人的分享中赵海平给出了回复:“因为百度和腾讯没找我呗 ...
- [.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上)
[.net 面向对象程序设计进阶] (16) 多线程(Multithreading)(一) 利用多线程提高程序性能(上) 本节导读: 随着硬件和网络的高速发展,为多线程(Multithreading) ...