CUI で GIS (2)

by

in

 前回に引き続き、ogr2ogr の紹介です。
 今回は下に示す四国 4 県の県庁所在地の地図を作成します。

 今回使用した元データは次の 2 点です。

 いきなりですが、これらのデータから主題図を作るためのバッチファイルは次のようになります。前回と同様のコマンドラインが散見されますね。

@echo off
setlocal
set OSGEO4W=C:\OSGeo4W
set PATH=%OSGEO4W%\bin;%PATH%
call %OSGEO4W_ROOT%\etc\ini\gdal.bat

if exist *.sqlite del *.sqlite

set SQL=SELECT
set SQL=%SQL% ST_Union(ST_buffer(geometry, 0.0001)) AS geometry,
set SQL=%SQL% SUBSTR(JCODE, 1, 2) AS pref_code,
set SQL=%SQL% KEN AS pref_name
set SQL=%SQL% FROM japan_ver84
set SQL=%SQL% WHERE pref_code BETWEEN '36' AND '39'
set SQL=%SQL% GROUP BY pref_code

ogr2ogr ^
    -nln     prefs ^
    -dialect sqlite ^
    -sql     "%SQL%" ^
    shikoku.sqlite /vsizip/japan_ver84.zip

set SQL=SELECT
set SQL=%SQL% geometry,
set SQL=%SQL% SUBSTR(address, 1, 3) AS city_name
set SQL=%SQL% FROM office_latlon_pref_utf8_20180611
set SQL=%SQL% WHERE pref_cd BETWEEN '36' AND '39'

ogr2ogr ^
    -nln     capitals ^
    -s_srs   EPSG:4326 ^
    -t_srs   EPSG:6668 ^
    -oo      X_POSSIBLE_NAMES=lon ^
    -oo      Y_POSSIBLE_NAMES=lat ^
    -dialect sqlite ^
    -sql     "%SQL%" ^
    -update ^
    shikoku.sqlite office_latlon_pref_utf8_20180611.csv

 ogr2ogr が 2 回使用されていますが、1 回目は県境のデータ(prefs)を、2 回目は県庁所在地のデータ(capitals)を作成します。そして両方のデータとも shikoku.sqlite というファイルに出力しています。

県境データの作成

 20 行目の -sql の引数で与えられる SQL 変数は次のようになります(実際はインデント、改行なし)。

SELECT
    ST_Union(ST_buffer(geometry, 0.0001)) AS geometry,
    SUBSTR(JCODE, 1, 2) AS pref_code,
    KEN AS pref_name
FROM japan_ver84
WHERE pref_code BETWEEN '36' AND '39'
GROUP BY pref_code

 前回の問題では ogr2ogr の -clipsrc で元データから必要なデータを抽出しましたが、今回は「四国 4 県」なので都道府県コード(pref_code)で抽出条件を与えています。都道府県コードは元データに含まれている市町村コード(JCODE)の先頭の 2 文字なので、SQLite の SUBSTR 関数でこれを取得しています。
 また、前回は旧主国のデータを現在の構成国名の列挙(WHERE NAME IN (…))して合併処理を行いましたが、今回は pref_code でグルーピング(GROUP BY pref_code)してこれを行っています。

県庁所在地データの作成

 29 行目以下は ogr2ogr で csv 形式のテキストファイルからデータを作成する時の定石です。すなわち

  • 入力データ(source)の座標参照系を -s_srs の引数で、出力データ(target)の引数で与える。引数には EPSG コードを用いる
  • -oo オプションの引数 X_POSSIBLE_NAMES、Y_POSSIBLE_NAMES に対応する csv のカラム名を指定する
  • 既存のファイルに追加する場合は -update を加える

 36 行目の SQL 変数は以下の通りで、四国 4 県の県庁所在地の市名(city_name)はフルの所在地(address)の上 3 文字で得られるのでこうしています。「名古屋市」とかの場合は要変更になります(ヒント CASE … END)。

SELECT
    geometry,
    SUBSTR(address, 1, 3) AS city_name
FROM office_latlon_pref_utf8_20180611
WHERE pref_cd BETWEEN '36' AND '39'

まとめ

 以上、前回指摘した「バッチファイルの再利用」の実例になります。学ぶほどに仕事が楽になるハズです。特に SQL は他の用途にも活用できて超強力です。

 ところで皆さんは「ベクターデータ = シェープファイル」と認識していませんか? もう 1 点、今回主張したいのは「脱・シェープファイル」です。
 ご承知のように、シェープファイルは一つのレイヤーを表現するのに最低でも 3 つのファイル(.shp、.shx、.dbf)を必要とします(実質的には .prj も必須)。この内、属性を収納する .dbf は dBASE という今や殆ど使われていないデータベース管理システム(DBMS)のファイル形式です。その他の前時代的な制約もあり、QGIS は第 3 版から Geopackage を既定のデータ形式に変えています。
 Geopackage は SQLite に対してラスターデータも扱えるようにした拡張形式です。そして SQLite は Android でも使われている普通の DBMS です
 今回の例だと shikoku.sqlite はデータベースで、prefs および capitals は shikoku.sqlite 内のテーブル(GIS の用語では「レイヤー」)です。そして SQLite にあっては幾何情報(geometry)はテーブル内の 1 つの属性に他なりません。シェープファイルより随分スッキリしたと思いませんか。

 皆が慣習に囚われず普通のデータベースを使うようになれば「脱・シェープファイル」が進むと思うのですが如何でしょう。