geotrellis使用(四十二)将 Shp 文件转为 GeoJson
前言
一个多月没有写博客了,今天尝试着动笔写点。
原因很多,最重要的原因是我转行了。是的,我离开了开发岗位,走向了开发的天敌-产品经理。虽然名义上是产品经理,但是干的事情也很杂,除了不写代码,其他的都干,经常还要加个小班,所以就没那么多时间研究技术上的东西,机械键盘上已经落下了一层薄薄的灰尘。但是自己确实又爱码农这一行,上班看着同事畅快的敲着代码,心里就有点痒,所以下班没事仍旧自己瞎捉摸,这不就总结出来今天这篇文章。
关于产品经理和研发的关系我还真得多说一句,虽然二者是天敌,但是一个懂研发的产品经理很容易和研发打交道,相互之间有很多的共同话题,每次项目来的时候我脑海中大概知道如何解决这件事情,甚至我还要帮项目对接的公司解决开发上的问题。。。
话不多说,开始今天的主题,今天主要介绍如何将 Shp 文件转为 GeoJson,这在 QGIS、ArcGIS 等专业软件中很容易实现,只需要点个按钮就行了,本文正是来研究这点个按钮背后发生的故事。本文是在使用 GeoTrellis 中碰到的,所以仍旧归入此博客集中,当然其中的框架等也都是基于 GeoTrellis 的。
一、实现方式
1.1 理论分析
其实这个过程逻辑上比较简单,首先将 Shp 文件读入内存,再分别读出空间属性和普通属性,将二者组合起来按照 GeoJson 文件的格式写入即可。
1.2 具体实现
- 读 Shp 文件
只需要一行代码即可解决:
val datas = ShapeFileReader.readSimpleFeatures(path)
这是 GeoTrellis 封装好的读 Shp文件的方法,但是此种方式存在一个问题,无法设置读 Shp 文件时的编码方式,如果 Shp 文件不是 UTF-8 编码会存在乱码的问题,简单改造一下源码即可实现:
val datas = {
val file = new File(path)
val shpDataStore = new ShapefileDataStore(path.getFileUrl())
shpDataStore.setCharset(Charset.forName(charsetName))
val ftItr = shpDataStore.getFeatureSource.getFeatures.features
try {
val simpleFeatures = mutable.ListBuffer[SimpleFeature]()
while (ftItr.hasNext) simpleFeatures += ftItr.next()
simpleFeatures
} finally {
ftItr.close
shpDataStore.dispose()
}
这样就能够读出 Shp 文件中的所有内容,空间属性附带普通属性,最终是 SimpleFeature 对象的集合。
- 将内容转为 Feature
所谓 Feature 其实就是空间属性和普通属性的结合。
def parseAttribute(sf: SimpleFeature) = {
import scala.collection.JavaConversions._
sf.getProperties.drop(1).map { p =>
val attr = sf.getAttribute(p.getName)
p.getName.toString -> (if (attr == null) "" else attr.toString)
}.toMap
}
def getGeometryFromSimpleFeature(sf: SimpleFeature) = {
val original = sf.getDefaultGeometryProperty.getValue
Geometry(original.asInstanceOf[com.vividsolutions.jts.geom.Geometry])
}
def toFeature(sf: SimpleFeature) = {
Feature(getGeometryFromSimpleFeature(sf), parseAttribute(sf))
}
以上方法能将单个 SimpleFeature 对象转为 Feature 对象,整个集合只需要实现一下 map 方法即可。
- 转为 GeoJson
在上一步中,肯定有同学很好奇,为什么要将从 Shp 中读出的 SimpleFeature 对象转为 Feature 对象,原因就在于有了 Feature 对象,我们就可以很简单的将其转为 GeoJson。GeoTrellis 内置了一个将 Feature 集合转为 GeoJson 的隐式方法,如下:
implicit class FeaturesToGeoJson[G <: Geometry, D: JsonWriter](features: Traversable[Feature[G, D]]) {
def toGeoJson(): String = {
JsonFeatureCollection(features).toJson.compactPrint
}
}
所以可以直接将第二步中得到的 Feature 集合转为 GeoJson,如下:
import geotrellis.vector.io.json.Implicits._
val geojson = features.toGeoJson()
最后只需要将 geojson 对象写入文件即可。
二、换种姿势
以上代码看上去轻描淡写,确实我折腾了好长时间才整出来。此处我又要插一句,有很多同学通过各种方式咨询我关于 GeoTrellis 使用的问题,我在这里要做一下声明:
首先,我知道的基本都毫无保留的写在博客里了,关于技术点问我和看我的博客差不多,我希望与大家一起探讨实现思路等方面的问题;
其次,就算问我,你是不是也得把问题描述清楚,有些同学截几句代码就要问我为什么跑不通,对不起,首先我不知道你从哪篇文章中截出的,其次我也不知道你要做什么事情,所以我真的无法回答;
第三,文章中的代码都是针对当时 GeoTrellis 版本而言的,你看到的时候可能已经更新了,可能会存在跑不通的情况,但是一般不存在,并且几时存在简单修改一下应该就可以,并且无需转牛角尖的问我类似 1TB Tiff 如何处理的问题,我的文章只提供技术方法,不做科学研究。
当然我非常感谢大家对我的认同和支持,这也是我持续写此博客集的动力之一(以后可能越来越少了,产品。。。都是产品惹的祸)。
言归正传,当我用 Scala 折腾了几天出来之后,一拍脑袋,不禁要骂自己几句,为什么我不直接拿 python 实现此功能呢?赶紧研究了一下,发现几行代码就搞定:
from geopandas import *
shpdata = GeoDataFrame.from_file(path)
features = [shpdata.__geo_interface__]
from json import dumps
geojson = open("demo.json", "w")
geojson.write(dumps({"type": "FeatureCollection", \
"features": features}, indent=2) + "\n")
geojson.close()
具体思路同上面分析,此处不具体展开,感兴趣的可以自行研究。
就像前面看到的一篇文章中讲到的,强大的不是 python 而是库,是的,一种语言用的人多了,自然库也就丰富了,而我们普通人可以选择为自己喜欢的语言贡献库,同时我们也不能死守一种语言,应该具体问题具体分析,找到最适合解决问题的语言,当然每一件事情都是学习的过程,都不会白费。
三、总结
本文介绍了两种语言下实现 Shp 转为 GeoJson 的方式,主要是分析解决问题的思路。
Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html
geotrellis使用(四十二)将 Shp 文件转为 GeoJson的更多相关文章
- salesforce 零基础学习(四十二)简单文件上传下载
项目中,常常需要用到文件的上传和下载,上传和下载功能实际上是对Document对象进行insert和查询操作.本篇演示简单的文件上传和下载,理论上文件上传后应该将ID作为操作表的字段存储,这里只演示文 ...
- NeHe OpenGL教程 第四十二课:多重视口
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 网站开发进阶(四十二)巧用clear:both
网站开发进阶(四十二)巧用clear:both 前言 我们在制作网页中用div+css或者称xhtml+css都会遇到一些很诡异的情况,明明布局正确,但是整个画面却混乱起来了,有时候在IE6下看的很正 ...
- Gradle 1.12用户指南翻译——第四十二章. Announce插件
本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- SQL注入之Sqli-labs系列第四十一关(基于堆叠注入的盲注)和四十二关四十三关四十四关四十五关
0x1普通测试方式 (1)输入and1=1和and1=2测试,返回错误,证明存在注入 (2)union select联合查询 (3)查询表名 (4)其他 payload: ,( ,( 0x2 堆叠注入 ...
- “全栈2019”Java第四十二章:静态代码块与初始化顺序
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 第十二章 Python文件操作【转】
12.1 open() open()函数作用是打开文件,返回一个文件对象. 用法格式:open(name[, mode[, buffering[,encoding]]]) -> file obj ...
- 第四十二个知识点:看看你的C代码为蒙哥马利乘法,你能确定它可能在哪里泄漏侧信道路吗?
第四十二个知识点:看看你的C代码为蒙哥马利乘法,你能确定它可能在哪里泄漏侧信道路吗? 几个月前(回到3月份),您可能还记得我在这个系列的52件东西中发布了第23件(可以在这里找到).这篇文章的标题是& ...
- abp(net core)+easyui+efcore实现仓储管理系统——入库管理之六(四十二)
abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...
随机推荐
- C#_02.14_基础五_.NET类
C#_02.14_基础五_.NET类 一.类实例: 我们前面说过类是一个模板,我们通过类创建一个又一个的实例,通常情况下类当中的变量是每一个实例都各有一份的,互相不影响,而静态字段是除外的,静态字段是 ...
- Delphi 之弹出气泡消息提示
//h:窗体中控件的句柄(用在某个控件上提示消息)(要调用的控件句柄) //text:要提示的文本 //cap:提示框上的标题 //IconType:提示框上显示的图标(共三个值.1.2.3分别为提示 ...
- win32下使用相对exe文件的绝对路径资源
在使用VC++进行开发时,如果按F5进行Debug时,当前相对资源是相对工程的vcxproj的文件夹目录,而直接双击运行exe时,资源是相对exe的文件夹目录.为了兼容这二者,最好使用绝对路径,这样无 ...
- Logical Volume Manager (LVM)
LVM 是一种可用在Linux内核的逻辑分卷管理器:可用于管理磁盘驱动器或其他类似的大容量存储设备. 本文提供如何在 Arch Linux 中配置和使用 Logical Volume Manager ...
- golang 对结构体进行格式化输出
可以使用 `return fmt.Sprintf("%+v", *conf) ` 来打印结构体,包括结构体的key值.但是由于结构体内容较多,都在一行,所以希望可以格式化输出结构体 ...
- 微信小程序WebSocket报错:Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received
Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was ...
- Fiddler Composer 模拟post请求
在模拟post请求的时候,发现服务器端无法接收post参数 发现原来的请求表头的设置问题加上表头 Content-Type: application/x-www-form-urlencoded 后正常
- CentOS7 使用yum命令安装Java SDK(openjdk)
CentOS 6.X 和 7.X 自带有OpenJDK runtime environment (openjdk).它是一个在linux上实现开源的java 平台. 安装方式: 1.输入以下命令,以 ...
- numpy累积
numpy累积有两类函数:np.cumxxxxx和np.ufunc.accumulate() import numpy as np a = np.arange(1, 5) print(np.cumpr ...
- [转]Linux Shell 1>/dev/null 2>&1 含义
shell中可能经常能看到:echo log > /dev/null 2>&1 命令的结果可以通过%>的形式来定义输出 /dev/null :代表空设备文件> :代表 ...