首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >geotrellis使用(四十二)将 Shp 文件转为 GeoJson

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

作者头像
魏守峰
发布2018-09-21 17:20:27
1.2K0
发布2018-09-21 17:20:27
举报
文章被收录于专栏:点滴积累点滴积累

前言

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

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

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

话不多说,开始今天的主题,今天主要介绍如何将 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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-08-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、实现方式
    • 1.1 理论分析
      • 1.2 具体实现
      • 二、换种姿势
      • 三、总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档