国土数値地理情報から白地図を作る。1


ネットにある地図では緯度経度を正確に作図するという用途には向いていません。国土地理院のデータから高精度に描画する地図を作成する方法を紹介します。他の緯度経度データと合わせてデータビジュアライゼーションで活用することを目的としています。また専用のGISソフトウェアではなくPHPとAdobe Illustratorでの処理を前提としています。

1 データの入手先

データは国土数値地理情報から入手します。国土地理情報のダウンロードサイト
ここにある行政区域のデータを使います。行政区域データは各都道府県毎にダウンロードできます。市区町村の名称と境界線のデータがXML形式で入っています。このXMLを読み取り境界線を画面に描画するためのプログラムをPHPで作成します。描画はSVG形式で書き出します。SVGは座標を記述したテキストデータの様な物でブラウザでの表示やIllustratorなどのグラフィックソフトでも開く事ができます。

2 データのダウンロードと保存

47都道府県のデータをダウンロードします。北から番号順になっています。ダウンロードしたデータを解凍するとフォルダが出来上がります。そのフォルダを開くと下図のようなファイルが入っています。

この中で拡張子がxmlのファイルが目的のデータが入ったファイルです。このファイルから座標を読み取り描画を行います。

3.ダウンロードしたXMLの仕組み

PHPではxmlを読み取るための仕組みがあります。ネットにも色々とサンプルがあります。そこらへんを参考にコードを書いてあげます。それほど難しくはありませんがダウンロードしたデータは名前空間付きのデータになっています。名前空間が付いているとちょっと手間が増えます。

まずはデータが入っているXMLをみてみます。つぎのようなタグの中にデータが入っています。

ざっくりと説明すると<ksj:Dataset>〜</ksj:Dataset>にデータが入っています。データは3つの種類に分かれています。
<gml:Curve gml:id=”cv0_0″>が座標データ
<gml:Surface gml:id=”sf0″>がサーフェスの説明
<ksj:AdministrativeBoundary gml:id=”gy0″>が行政区域名が入った部分。
例えば上記の例では<ksj:AdministrativeBoundary gml:id=”gy0″>を見ると秋田県、秋田市という事がわかります。そして<ksj:bounds xlink:href=”#sf0″/>に#sf0とあるので、サーフェスはsf0を見れば良いとわかります。そこで<gml:Surface gml:id=”sf0″>を見ると<gml:curveMember xlink:href=”#cv0_0″/>でcv0_0とあるので、座標(緯度、東経)はcv0_0を見ます。そこに<gml:posList>〜 </gml:posList>として

が入っているとなります。緯度と東経が文字列で並んでいます。この部分は改行コードで区切ってあり緯度と東経の区切りは半角スペース区切りです。ちなみにこの場所はどこなのかGoogle Mapで確認すると

ここになってます。google map上では表示されない小さな島(岩?)のようです。数値情報地図はここまで細かいところまで載っています。

4.座標データの取り出し

さてここからPHPでデータを取り出す方法に入ります。まずはダウンロードしたXMLファイルから座標データを読み出すためにファイルを開きます。

でXMLファイルを読み込みます。$loadXMLはxmlファイルのファイル名(ファイルパス)です。これで変数$domにXMLの全体が入ります。

つぎにksjの部分を取り出します。ここらへんの方法はサンプルが色々とサイトにも紹介されていますが名前空間付きだとなんか処理が違う様で混乱しました。とりあえず*で指定して中身を取り出します。

次に上記の1行で変数$rootにksjの中身を代入します。ここから名前空間付きのXMLデータを処理します。次のforeachループで名前空間Curveのデータをとりだします。座標データが欲しいだけなので他のデータは使いません。

このループでCurveごとのデータが取り出せます。ループの中では

として改行コードで配列にして緯度と東経のデータを取り出します。配列$dataArrayに文字列で緯度東経が入ります。そこから緯度東経を納めるための配列$coordinateに値を入れます。その時に前後にスペースやタブがあると邪魔なのでtrimで綺麗な文字列にしておきます。

配列$coordinateは2次元の配列ですが、最初の添え字で島もしくは市区町村の境界線、2番目の添え字が座標データの並びになります。

5.緯度経度の取り出し

$coordinateには文字列で緯度経度が入っています。これをスペース区切りで取り出すと緯度と経度(東経)になります。

そしてその文字列を数値(float)に変換します。数値への変換は投影の計算のところでやっています。

6.地図の投影

平面の地図を作るためにメルカトル図法で投影します。投影するまえに作図の範囲を40cm x 40cm。仮のスクリーンサイズを4000 x 4000pxとしています。ブラウザで表示するためにはpxが重要ですが今回はIllustratorなどで扱うので適当にしています。縮尺を求めるために日本全体を描画するために日本の最大サイズ(緯度経度)を求めておきます。

縦方向、横方向の縮尺を求めてその大きい方を描画の時の倍率$multipleとして使います。

7. メルカトル図法の計算

上記の地図の投影でもすでに出てきていますが緯度経度から座標に計算する部分は次の様な計算になります。

ここで$xと$yが描画する座標になります。

8.SVGファイルの作成

SVGファイルは中身はテキストファイルなので座標をsvgのルールで書き出して作ります。polylineで座標を書き出してます。

 

9.Finder上でのファイルの配置

phpのプログラムとXMLの配置は次の様にします。

フォルダにダウンロードしたフォルダが入っています。

下の階層はこんな感じ

10.コードとスクリプトの起動

プログラム全文は次の通りです。
plotPrefData.php

 

このコードをplotPrefData.phpという名前で保存しておきます。

phpの起動にはターミナルが必要になります。
下図では省略していますがcdコマンドで作業中のフォルダ(ディレクトリ)に移動します。
cd でスペースを入れて目的のディレクトリのパスを入力してreturnキー。ディレクトリのパスを入力するのが面倒な時にはFinderからフォルダをターミナルにドラッグ&ドロップでファイルパスに入力が出来ます。

php ./plotPrefData.php とターミナルに入力してリターンキーで作成したphpのスクリプトが動きます。

11.作成したSVGファイル

無事に処理が終了すれば同じフォルダにhokkaido.svgという画像ファイルがつくれれているはずです。この画像ファイルは41.6MBあり開くにはかなり時間がかかります。ブラウザで開いてしばらく反応がありませんが、じっとまっててください。

Illustratorではデータ数がありすぎて開くまで20分くらいかかりました。また、すべての行政区域の境界線が入っているので用途によっては使いにくいものになります。また下図では択捉島の一部が欠けています。これはIllustratorのパスの制限によるものです。ベジェ曲線の点が30,000点以上になると図形が表示されないようです。下図はIllustratorのアウトライン表示。

非常に細かい部分まで入っています。下図はえりも岬の先端部分。

 

とりあえずダウンロードしたデータを描画してSVGファイルにすることはできました。使いやすくするために以下の事を行います。
・県境以外の行政区域の区切り線を削除する。
・描画時にデータサイズを調整できるようにする。
・3万点以上のデータへの対応。

続きは次回で。