专栏首页点滴积累geotrellis使用(四十二)将 Shp 文件转为 GeoJson

geotrellis使用(四十二)将 Shp 文件转为 GeoJson

前言

一个多月没有写博客了,今天尝试着动笔写点。

原因很多,最重要的原因是我转行了。是的,我离开了开发岗位,走向了开发的天敌-产品经理。虽然名义上是产品经理,但是干的事情也很杂,除了不写代码,其他的都干,经常还要加个小班,所以就没那么多时间研究技术上的东西,机械键盘上已经落下了一层薄薄的灰尘。但是自己确实又爱码农这一行,上班看着同事畅快的敲着代码,心里就有点痒,所以下班没事仍旧自己瞎捉摸,这不就总结出来今天这篇文章。

关于产品经理和研发的关系我还真得多说一句,虽然二者是天敌,但是一个懂研发的产品经理很容易和研发打交道,相互之间有很多的共同话题,每次项目来的时候我脑海中大概知道如何解决这件事情,甚至我还要帮项目对接的公司解决开发上的问题。。。

话不多说,开始今天的主题,今天主要介绍如何将 Shp 文件转为 GeoJson,这在 QGIS、ArcGIS 等专业软件中很容易实现,只需要点个按钮就行了,本文正是来研究这点个按钮背后发生的故事。本文是在使用 GeoTrellis 中碰到的,所以仍旧归入此博客集中,当然其中的框架等也都是基于 GeoTrellis 的。

一、实现方式

1.1 理论分析

其实这个过程逻辑上比较简单,首先将 Shp 文件读入内存,再分别读出空间属性和普通属性,将二者组合起来按照 GeoJson 文件的格式写入即可。

1.2 具体实现

  1. 读 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 对象的集合。

  1. 将内容转为 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 方法即可。

  1. 转为 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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 安装 Accumulo——突破自己,就是成长

    前言 在我刚开始接触分布式集群的时候,是自己在几台虚拟机中手动安装的 Hadoop 和 Spark ,所以当时对 Hadoop 的配置有个简单的印象 ,但是后面...

    魏守峰
  • OpenStack(企业私有云)万里长征第二步——使用Fuel部署

    一、前言 最近一直在使用DevStack来安装OpenStack,注意一直二字,部署了一遍又一遍,操作系统怕是安装了不下上百次,有时是为了验证新的方案,有时是安...

    魏守峰
  • 编程的思想性——议编程与“武功”的一致性

    一、缘起        最近做了一件事情,将写好的scala程序中稍显混乱和不雅的代码进行了重构(系列博客见http://www.cnblogs.com/sho...

    魏守峰
  • 使用Azure DevOps Pipeline实现.Net Core程序的CI

    上次介绍了Azure Application Insights,实现了.net core程序的监控功能。这次让我们来看看Azure DevOps Pipelin...

    kklldog
  • 表格搞定 Asp.net Web 状态管理

     最近在网上搜罗了 ASP.NET WEB 状态管理方面的一些内容,终于把这些内容整合总结了一下。 1. 希望自己通过整理,能够掌握一些,为自己投资。 2. 以...

    数据分析
  • centos7.2(1511版本)上安装pyspider

    censtos是服务器常用的操作系统,本例以centos7.2最小化版安装为例安装

    拓荒者
  • Hyperledger Fabric和VSCode的IBM区块链扩展开发智能合约

    了解使用IBM Blockchain Platform的VSCode扩展来简化开发,测试和部署智能合约的过程。完成本教程后,你将了解如何使用VSCode在本地H...

    笔阁
  • 谷歌微软等科技巨头的面试题 你能答对几道?

    苹果 1. 如果你有几百万用户,每个用户都会发生数百笔交易,这些交易存在于数十种产品中。你该如何把这些用户细分成有意义的几类? 微软 1. 描述一个你曾经参与的...

    企鹅号小编
  • Linux下Nginx编译安装

    yum -y install gcc gcc-c++ autoconf automake yum -y install zlib zlib-devel ope...

    用户2929716
  • SqlServer表死锁的解决方法

    前些天写一个存储过程,存储过程中使用了事务,后来我把一些代码注释掉来进行调试找错,突然发现一张表被锁住了,原来是创建事务的代码忘记注释掉。本文表锁住了的解决方法...

    跟着阿笨一起玩NET

扫码关注云+社区

领取腾讯云代金券