geotrellis使用(三十一)使用geotrellis直接将GeoTiff发布为TMS服务
前言
传统上我们需要先将Tiff中存储的影像等数据先切割成瓦片,而后再对外提供服务。这样的好处是服务器响应快,典型的用空间来换时间的操作。然而这样造成的问题是空间的巨大浪费,一般情况下均需要存储1-18级左右的瓦片数据。我一直在思考有没有办法不存储瓦片而直接发布TMS服务,当然这样响应速度肯定是要受一点影响,但是基于Geotrellis的分布式计算对这一点提供了巨大帮助,大大缩短了瓦片临时切割(存储于内存中)所用的时间。而且这样不仅仅是节省了存储空间的问题,何况我们有时可能只是为了查看数据情况(大量的Tiff文件,无法或者不方便逐一打开),这时不需要事先切割,就能查看大量Tiff文件的数据情况,并且可以逐级缩放。本文介绍如何基于Geotrellis直接将Geotiff发布为TMS服务。
一、效果预览
闲话不多说,先来看一下效果。我从Google地图上下载了北京首都国际机场部分影像图,并将其拼接成了Tiff文件(不是多此一举,只是为了演示效果)。而后通过Geotrellis成功将其加载到了Leaftlet地图中。效果如下图:

二、实现方案
其实总体说起来也很简单。主要是读取Tiff文件,并将其根据瓦片编号切割成256*256的小块并附带key(row,col)信息,这样我们就能根据前台发送的key值信息查找后返回相应的瓦片。
2.1 读取Geotiff文件
使用Spark读取Geotiff文件,并将其转成RDD。代码如下:
val path = new org.apache.hadoop.fs.Path(filePath)
val rdd = HadoopGeoTiffRDD.spatialMultiband(path)
其中filePath表示tiff文件的存放位置,最好是将tiff文件存储于HDFS中,第二行便得到了需要的rdd,其类型为RDD[(ProjectedExtent, MultibandTile)],其实此处已经完成了Geotiff的读取和瓦片的切割两步功能。
2.2 为RDD赋key编码
这一步较复杂。首先获取rdd的属性信息并生成TileLayerMetadata,然后为rdd赋此metadata信息并完成查找。在此简单叙述之,代码如下:
- 第一步获取KeyBounds、空间范围、数据类型、数据精度等信息。
val sms = 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
- 获取当前请求层级的瓦片布局信息
val layoutScheme = ZoomedLayoutScheme(WebMercator, tileSize = 256)
val layout = layoutScheme.levelForZoom(zoom)
此处表示的是采用通用的TMS编号信息,投影才用墨卡托,瓦片大小为256。
- 为rdd赋key属性信息
val sm = sms.head
val metadata = TileLayerMetadata[SpatialKey](
sm.cellType,
layout.layout,
sm.extent,
sm.crs,
sm.bounds.setSpatialBounds(layout.layout.mapTransform(sm.extent))
)
val layoutRdd = rdd.tileToLayout(metadata, resampleMethod)
val contextRDD = new ContextRDD(layoutRdd, metadata)
resampleMethod为采样方式。
- 根据瓦片编号进行查找
val tile = contextRDD.lookup(SpatialKey(col, row))
找到该瓦片后即可才用前面博客中讲述过的方式将其发送到前台,油leftlet进行渲染。
三、总结
本文简单讲述了如何使用Geotrellis直接将Geotiff发布为TMS服务,操作较为繁琐,对Geotrellis的综合性知识要求较高。
Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html
geotrellis使用(三十一)使用geotrellis直接将GeoTiff发布为TMS服务的更多相关文章
- geotrellis使用(三十二)大量GeoTiff文件实时进行TMS服务
前言 在上一篇文章中我讲了如何直接将Geotiff文件发布为TMS服务,在其中只讲了单幅Geotiff的操作,其实单幅这种量级的数据对Geotrellis来说就是杀鸡焉用牛刀,Geotrellis针对 ...
- geotrellis使用(三十二)大量GeoTiff文件实时发布TMS服务
前言 在上一篇文章中我讲了如何直接将Geotiff文件发布为TMS服务,在其中只讲了单幅Geotiff的操作,其实单幅这种量级的数据对Geotrellis来说就是杀鸡焉用牛刀,Geotrellis针对 ...
- geotrellis使用(四)geotrellis数据处理部分细节
前面写了几篇博客介绍了Geotrellis的简单使用,具体链接在文后,今天我主要介绍一下Geotrellis在数据处理的过程中需要注意的细节,或者一些简单的经验技巧以供参考. 一.直接操作本地Geot ...
- Bootstrap <基础三十一>插件概览
在前面布局组件中所讨论到的组件仅仅是个开始.Bootstrap 自带 12 种 jQuery 插件,扩展了功能,可以给站点添加更多的互动.即使不是一名高级的 JavaScript 开发人员,也可以着手 ...
- COJ969 WZJ的数据结构(负三十一)
WZJ的数据结构(负三十一) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 A国有两个主基站,供给全国的资源.定义一个主基站 ...
- NeHe OpenGL教程 第三十一课:加载模型
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 三十一、Java图形化界面设计——布局管理器之GridLayout(网格布局)
摘自http://blog.csdn.net/liujun13579/article/details/7772491 三十一.Java图形化界面设计--布局管理器之GridLayout(网格布局) 网 ...
- JAVA之旅(三十一)——JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件
JAVA之旅(三十一)--JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件 有段时间没有更新JAVA了,我们今天来说一下JAVA中的图形化界面,也就是GUI ...
- Java进阶(三十一) Web服务调用
Java进阶(三十一) Web服务调用 前言 有朋友问了一个问题:如何调用已知的音乐服务接口,服务文档如下: https://www.evernote.com/shard/s744/sh/c37cd5 ...
随机推荐
- RxSwift 系列(九) -- 那些难以理解的概念
前言 看完本系列前面几篇之后,估计大家也还是有点懵逼,本系列前八篇也都是参考RxSwift官方文档和一些概念做的解读.上几篇文章概念性的东西有点多,一时也是很难全部记住,大家脑子里面知道有这么个概念就 ...
- Java多线程缓存器简单实现
package com.charles.utils; import java.util.HashMap; import java.util.Map; import java.util.concurre ...
- (转)java反射机制及简单工厂模式
第一步,定义一个接口类 package factory.face; /** * 接口,为了保证返回的对象可以统一用 Product接受 * @author Administrator */ publi ...
- MVC 路由设置伪静态
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/ ...
- Apache Kafka - 介绍
原文地址地址: http://blogxinxiucan.sh1.newtouch.com/2017/07/12/Apache-Kafka-介绍/ Apache Kafka教程 之 Apache Ka ...
- 网关(Gatesvr) 设计(1)
Gate解决的问题: 1.用户在服务端的实例可以在不同的进程中,也可以移动到同一个进程中.2.用户只需要与服务端建立有限条连接,即可以访问到任意服务进程.这个连接的数量不会随服务进程的数量增长而线性增 ...
- ORACLE - 用户和角色的权限管理
在ORACLE中,创建用户后需要授权才能使用. 一.用户管理 1. 用户和角色信息查询 --查询所有用户 SQL> select * from dba_users; --经授予的用户或角色的系统 ...
- Uva 122 树的层次遍历 Trees on the level lrj白书 p149
是否可以把树上结点的编号,然后把二叉树存储在数组中呢?很遗憾如果结点在一条链上,那将是2^256个结点 所以需要采用动态结构 首先要读取结点,建立二叉树addnode()+read_input()承担 ...
- JavaScript:int string 相互转化
A.把int型转换成string型 (1) var x=100 a = x.toString() (2) var x=100; a = x +&quo ...
- ORA-01036: 非法的变量名/编号 解决方案
今天又一次遇到了 ORA-01036: 非法的变量名/编号 的问题,之前在项目中也遇见过这个问题,但是具体怎么解决的忘记了,今天又是遇见了,花了半个小时才解决.我今天遇到的情况是这样的: 存储过程中有 ...