🌐

ShapefileからGeoJSONへの変換について

2023/10/12に公開

ShapefileからGeoJSONへの変換について

はじめに

アイディオットCTOの小倉です。
今回は、以前の記事で触れましたShapefileからGeoJSONへの変換についてお話します。

変換における課題

mapboxで利用するためのShapefileからGeoJSONを作成する際に、下記の課題があります。

  • 文字コードの変換
  • 座標系の変換

文字コードについて

ShapefileはShift-JISでエンコードされているものがあります。
単にGeoJSONに変換してmapboxで利用すると文字化けしてしまうため、
UTF-8に変換する必要があります。

座標系について

Shapefileは座標系を指定することができます。
しかし、mapboxではWGS84の座標系を利用する必要があります。

WGS84とは

「WGS84」は「World Geodetic System 1984」の略で、地球の形と大きさをモデル化するためのジオデティック・データモデルの一つです。
このシステムは、地球上の任意の点の位置を正確に特定するための基準となるもので、GPS等に採用されています。

WGS84は、以下のような特徴を持っています

  • 楕円体の定義: 地球を楕円体としてモデル化し、主軸と短軸の長さを定義します。
  • 原点: WGS84の原点は、質量の中心とされる地球の重心です。
  • 方向: 地球の回転軸に関連する北極、赤道、グリニッジ子午線を基準とします。
  • 高度: 海面を基準とした高度を定義します。

WGS84の座標系を使用することで、地球上の任意の場所の緯度、経度、高度を一貫して表現することが可能となります。

変換について

OpenJUMPなどのGISを利用して文字コードや座標系の変換ができます。
ツールを利用した変換方法については、今回の記事は触れません。

今回は、CLIを利用した変換方法を紹介します。

事前準備

nodeがインストールされていることが前提です。
動作確認ができているnodeと各ライブラリのバージョンは以下の通りです。
パッケージはnpmでインストールしてください。

  • node: v19.0.0
  • shapefile: v0.6.6 LINK
    • ShapefileからGeoJSONへの変換と、文字コードの変換に利用します。
  • proj4: v2.9.0 LINK
    • 座標系の変換に利用します。

またShapefileはshpファイルとprjファイルなどを同じディレクトリに配置してください。

Shift-JISからUTF-8へ文字コードの変換し、GeoJSONで出力する

以下のコマンドでUTF-8のGeoJSONファイルに変換ができます。

$ shp2json --encoding Shift-JIS '{入力shpファイルパス}' -o '{出力先GeoJSONファイルパス}'

(例)
$ shp2json --encoding Shift-JIS 'data.shp' -o 'data.geojson'

GeoJSONの座標系をWGS84に変換する

prjファイルを参照し、GeoJSONの座標系を変換していきます。

まず変換処理を行うnodeのスクリプトを作成します。

geoJsonCoordSystemConverter.js

const fs = require('fs')
const proj4 = require('proj4')

// prjファイルから取得した投影法を入力
const firstProjection = process.argv[2]
const secondProjection = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs '

// GeoJSONファイルを読み込む
const geoJsonFilePath = process.argv[3]
const geojson = JSON.parse(fs.readFileSync(geoJsonFilePath, 'utf8'))

// 座標系変換関数
function convertCoordinates(coordinates) {
  return coordinates.map(coordinate => {
    if (Array.isArray(coordinate[0])) {
      return convertCoordinates(coordinate)
    } else {
      return proj4(firstProjection, secondProjection, coordinate)
    }
  })
}

// それぞれのFeatureの座標系を変換する
geojson.features.forEach(feature => {
  feature.geometry.coordinates = convertCoordinates(feature.geometry.coordinates)
})

// GeoJSONファイルに書き込む
const convertedFilePath = process.argv[4]
fs.writeFileSync(convertedFilePath, JSON.stringify(geojson))

以下のコマンドで、引数にprj内のテキストとGeoJSONファイルのパスを指定してスクリプトを実行し、座標系を変換したGoeJsonファイルを出力します。

$ node geoJsonCoordSystemConverter.js "$(cat {prjファイルパス})" '{入力GeoJSONファイルパス}' '{出力先GeoJSONファイルパス}'

(例)
$ node geoJsonCoordSystemConverter.js "$(cat data.prj)" 'data.geojson' 'data-converted.geojson'

まとめ

今回は、ShapefileからGeoJSONへの変換についてお話しました。

今回の記事が少しでもお役にたてればと思います。
よりスマートな方法があれば、ぜひコメントなどいただけますと幸いです。

アイディオットではGISを開発したいエンジニアを募集中!

AI・データ利活用をリードし、世界にインパクトを与えるプロダクトを開発しませんか?

アイディオットでは、今後の事業拡大及びプロダクト開発を担っていただけるエンジニアチームの強化を行っております。
さらに会社の成長を加速させるため、フロントエンドエンジニア、バックエンドエンジニア、インフラエンジニアのメンバーを募集しております!
日本を代表する企業様へ自社プロダクトを活用した、新規事業コンサルティング、開発にご興味のある方はお気軽にご連絡ください。

【リクルートページ】
https://aidiot.jp/recruit/
【募集ポジション一覧】
https://open.talentio.com/r/1/c/aidiot/homes/3925
【採用についてのお問合せ先】
株式会社アイディオット 採用担当:大島
メールアドレス:recruit@aidiot.jp

今回の記事の参考サイト

Discussion