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)+ ...
随机推荐
- 细说python类2——类动态添加方法和slots(转)
先说一下类添加属性方法和实例添加属性和方法的区别, 类添加属性属于加了一个以类为全局的属性(据说叫静态属性),那么以后类的每一个实例化,都具有这个属性.给类加一个方法也如此,以后类的每一个实例化都具备 ...
- RestTemplate之GET和POST调用和异步回调
get方式 String url = "http://hostname:port/v1.0/data/data"; HttpHeaders headers = new HttpHe ...
- GBK转UTF8
shell 脚本自动GBK转UTF8 for i in `find . -name "*.java"`; do iconv -f gbk -t utf-8 $i > $i.n ...
- Matlab quad
1x3−2x−5dx, (from 0 to 1) write a function myfun that computes theintegrand: function y = myfun(x) y ...
- jquery动态添加元素无法触发绑定的事件的解决方案
方法一:绑定live事件(live事件只在jquery1.9以下才支持,高版本不支持). //jquery 1.9(不包括1.9)以下可以 $(".btn").live(" ...
- [Python设计模式] 第16章 上班,干活,下班,加班——状态模式
github地址:https://github.com/cheesezh/python_design_patterns 题目 用代码模拟一天的工作状态,上午状态好,中午想睡觉,下午渐恢复,加班苦煎熬. ...
- mybatis --- 如何相互转换逗号分隔的字符串和List
如果程序员想实现某种功能,有两条路可以走.一条就是自己实现,一条就是调用别人的实现,别人的实现就是所谓的API.而且大多数情况下,好多“别人”都 实现了这个功能.程序员有不得不在这其中选择.大部分情况 ...
- method.invoke(...)反射点
import java.lang.reflect.Method; import java.util.Arrays; /** * @Author: hoobey * @Description: * @D ...
- emacs 集成astyle
https://stackoverflow.com/questions/8115460/emacs-save-excursion-not-restoring-point https://github. ...
- windows10开启wst子系统
需求描述: 在玩docker发现需要linux运行玩转,直接在vmware虚拟机上跑 ,性能有损耗.想直接在windows下运行docker 问题解决: windows10的wst子系统可以安装lin ...