geotrellis使用(四十二)將 Shp 檔案轉為 GeoJson

來源:互聯網
上載者:User
前言

一個多月沒有寫部落格了,今天嘗試著動筆寫點。

原因很多,最重要的原因是我轉行了。是的,我離開了開發崗位,走向了開發的天敵-產品經理。雖然名義上是產品經理,但是乾的事情也很雜,除了不寫代碼,其他的都幹,經常還要加個小班,所以就沒那麼多時間研究技術上的東西,機械鍵盤上已經落下了一層薄薄的灰塵。但是自己確實又愛碼農這一行,上班看著同事暢快的敲著代碼,心裡就有點癢,所以下班沒事仍舊自己瞎捉摸,這不就總結出來今天這篇文章。

關於產品經理和研發的關係我還真得多說一句,雖然二者是天敵,但是一個懂研發的產品經理很容易和研發打交道,相互之間有很多的共同話題,每次項目來的時候我腦海中大概知道如何解決這件事情,甚至我還要幫項目對接的公司解決開發上的問題。。。

話不多說,開始今天的主題,今天主要介紹如何將 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 dumpsgeojson = 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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.