コマンドラインでshpファイルやGeoJSONファイルをTopoJSONファイルに変換するチュートリアルです。各コマンドの解説はこちらへ。
※2017年4月12日追記
2017年4月にTopoJSON v3がリリースされました。このチュートリアルで使うコマンドラインに関してはv2とv3で差異はないので記事タイトルを「TopoJSON v2 チュートリアルその1」から「TopoJSON v2, v3 チュートリアルその1」に変更しました。
前提となる環境
- Node.js(というかnpmが使える環境)
TopoJSONのインストール
$ npm install -g topojson shapefile
npmでtopojson
とshapefile
をインストールします。-g
オプションをつけてグローバルにインストールします。
データのダウンロード
チュートリアル用の作業ディレクトリを作り、その中に元のデータを格納するフォルダと、生成したデータを格納するフォルダを適当な名前で作成してください。
ここではとりあえず「data」と「dist」とします。
今回は国土交通省国土政策局国土情報課が提供する国土数値情報のデータを利用します。
国土数値情報ダウンロードサービスのホームページに行って、GML(JPGIS2.1)シェープファイル形式を選択し、2.政策区域 > 行政区域のデータを選択してください。
とりあえず一つ、好きな都道府県を選択してください。
このチュートリアルでは茨城県の平成28年のデータを利用します。
N03-160101_08_GML.zip 1.96MB
ダウンロードしたzipファイルを解凍し、先ほど作成したdataフォルダに入れます。
shpファイルの入ったフォルダは5.5MBです(茨城県平成28年の場合)。
N03-160101_08_GML 5.5MB
.
├── data
│ └── N03-160101_08_GML
│ ├── KS-META-N03-16_08_160101.xml
│ ├── N03-16_08_160101.dbf
│ ├── N03-16_08_160101.prj
│ ├── N03-16_08_160101.shp
│ ├── N03-16_08_160101.shx
│ └── N03-16_08_160101.xml
└── dist
shpファイルをGeoJSONファイルに変換
さて、準備は整いました。まずはshp2json
コマンドでshpファイルをGeoJSONファイルに変換してみましょう。
$ shp2json --encoding "Shift-JIS" ./data/N03-160101_08_GML/N03-20160101.shp > ./dist/ibaraki_h28.geojson
国土数値情報の文字コードはShift-JISなので、オプションで--encoding "Shift-JIS"
を忘れずに設定してください。
さて、distフォルダに茨城県の行政区域データのGeoJSONファイルが生成されたはずです。この時点ではGeoJSONファイルのサイズは3.4MBあります。
ibaraki_h28.geojson 3.4MB
GeoJSONファイルをTopoJSONファイルに変換
このGeoJSONファイルをgeo2topo
コマンドでTopoJSONファイルに変換します。
$ geo2topo -q 1e6 ibaraki=./dist/ibaraki_h28.geojson > ./dist/ibaraki_h28.topojson
ibarakiはTopoJSONファイルの中のオブジェクト名です。ここではibarakiとしましたが任意の名称を設定してください。
ibaraki_h28.topojson 745KB
TopoJSONファイルをd3.jsで表示した例です。
詳しい説明は省きますが、ポリゴンとメッシュを表示しています。
各市町村のポリゴンにマウスを乗せると、マウスが乗ったポリゴンは水色に、隣接するポリゴンはシルバーに塗られます。
shpファイルからTopoJSONに直接変換
GeoJSONファイルを作成せずに、パイプを使って直接shpファイルからTopoJSONファイルに変換することも可能です。
$ shp2json --encoding "Shift-JIS" ./data/N03-160101_08_GML/N03-20160101.shp \
| geo2topo -q 1e6 > ./dist/ibaraki_h28.topojson
このとき作成されたTopoJSONファイルでは、オブジェクト名が"-"
になってしまいます。オブジェクト名が"-"
になるのが嫌な場合は、こういう書き方で回避することができます。
$ geo2topo -q 1e6 ibaraki=<( shp2json --encoding "Shift-JIS" ./data/N03-160101_08_GML/N03-20160101.shp ) \
> ./dist/ibaraki_h28.topojson
geo2topo
の-q
オプションについて
geo2topo
コマンドの-q
--quantization
オプションは非常に重要です。これを設定しなかった場合どうなるか、確認してみましょう。
ibaraki_h28_A.topojson
GeoJSONをTopoJSONに変換するときに量子化をおこなった例
$ geo2topo -q 1e6 ibaraki=./dist/ibaraki_h28.geojson > ./dist/ibaraki_h28_A.topojson
ibaraki_h28_B.topojson
GeoJSONをTopoJSONに変換してから量子化をおこなった例
$ geo2topo ibaraki=./dist/ibaraki_h28.geojson \
| topoquantize 1e6 > ./dist/ibaraki_h28_B.topojson
2つのTopoJSONファイルの地物とメッシュ(後述します)を表示した地図です。一見どちらも変わらないように見えますが、変換の際に量子化をおこなっていないibaraki_h28_B.topojsonでは、茨城県の一番北西に位置する大子町のポリゴンが他のどのポリゴンとも隣接していません。元のGeoJSONファイルが、隣接する二つのポリゴンの座標の間に微小な誤差を持つ場合、適切な隣接判定をおこなってくれないのです。
これを防ぐために、geo2topo
を実行する際には必ず-q --quantization
オプションをつけましょう。
TopoJSONを簡素化する
先ほど作成したTopoJSONファイルのサイズは745KBです。GeoJSONファイルが3.4MBだったことを考えると、これでも十分サイズは小さくなりましたが、toposimplify
コマンドを使うことでTopoJSONのサイズをより小さくすることができます。
$ toposimplify -P 0.05 -f ./dist/ibaraki_h28.topojson \
> ./dist/ibaraki_h28_simplified.topojson
ibaraki_h28_simplified.topojson 61KB
何とTopoJSONファイルは61KBになりました。最初のshpファイルが5.5MBあったので、おおよそ1/100になりました。
-P 0.05
とすることでarcsの数を元のデータの約5%まで削減しています。(詳しくはTopoJSONコマンド解説の記事へ)
こんなに削って大丈夫なの?と思われる方!是非次のデモページをご覧ください!
このズームレベルでは、今までのものと違いをほとんど感じることはないと思います。
またTopoJSONを簡略化するということはパスを簡略化するということなので、パンやズームなど地図上の動作も非常に軽くなります。
データにどの程度の正確性を求めるかはケースバイケースなので、その辺りは考慮しながら閾値を設定する必要があります。元の行政区域データでは沖にある小島やヘッドランドもしっかり再現されていますが、今回のように全県を表示する場合はディテールにこだわる必要はありません。がっつり削ってしまいましょう。
先ほどの例ではGeoJSONからTopoJSONに変換したものを改めて簡略化しましたが、パイプを使ってコマンドを繋げることでshpファイルやGeoJSONファイルから直接簡略化されたTopoJSONファイルを作成することができます。
GeoJSONから直接変換する場合
$ geo2topo -q 1e6 ibaraki=./dist/ibaraki_h28.geojson \
| toposimplify -P 0.05 -f > ./dist/ibaraki_h28_simplified.topojson
shpファイルから直接変換する場合
$ geo2topo -q 1e6 ibaraki=<( shp2json --encoding "Shift-JIS" ./data/N03-160101_08_GML/N03-20160101.shp ) \
| toposimplify -P 0.05 -f > ./dist/ibaraki_h28_simplified.topojson
TopoJSONの地物を結合する
一つの地物として扱いたい複数のポリゴン、例えば行政区域のデータで言うと飛び地や島嶼部をtopomerge
コマンドでマージするとひとまとまりの地物として扱うことができます。
$ topomerge pref=ibaraki -k 'd.properties.N03_004' < ./dist/ibaraki_h28_simplified.topojson > ./dist/ibaraki_h28_merge.topojson
このデモページでは違いがあまりわからなかったかと思います。
次に表示するデモページではtopomerge
をしたものとそうでないもの二つの地図を表示します。地図は境町にある坂東市の飛び地と、坂東市にある境町の飛び地付近にズームしています。
各ポリゴンにマウスを乗せたときに、周辺のポリゴンの色がどのように変化するか確認してください。
右側の市区町村ごとにマージをおこなった例では、飛び地のポリゴンにマウスオーバーしたときに本土のポリゴンも同様に水色に変化するはずです。このように、topomerge
コマンドを使えば複数のポリゴンをひとまとまりの地物として扱うことができます。
コマンドラインでTopoJSONファイルを生成する際の基本形を国土数値情報のデータを使って実践してみました。