2012/10/30

自分のための「基盤地図情報からshapefile」(1)

GISを日常的に使っている人で、「基盤地図情報」を知らない人は居まい。
日本全国の基本的なGISデータは、ここで入手するのが一般的。
最近では、OSMの方を利用している人も多いようであるが...。

基盤地図情報は、GISの国際標準ISO19100シリーズ」という標準に準拠していて、
国土地理院からは、XML形式のファイルをダウンロードして利用できる。
まぁ、ここまでは、どこにでも書いている話。

2012年10月30日現在、ダウンロード可能なXMLファイルは、
GML形式(ISO19136)と、符号化規則「附属書8」形式(ISO19118)の二種類の形式で、
何れかの形式のものをダウンロードして変換しGISソフトで利用する。

この変換には、通常、国土地理院の「基盤地図情報閲覧コンバートソフト」を使うが、
実は、このツールは、Windows専用であり、Mac ユーザとUbuntuユーザは苦労する。
ということで、今回は、OSに依存しないツールの開発を試みる

今回は、Ubuntu上で、Pythonを使って変換する方法を考えてみる。
大雑把な流れは、次の通り。
  1. 最初にXMLの要素をパースする。
  2. 基盤地図情報クラスをインスタンス化する。
  3. shapefile に変換する。
2.は必ずしも必要は無いが、再利用を考えるとこの方が良い。
問題は、shapefile に変換する部分であるが、この部分に関しては、
pyshp というライブラリを使う。とりあえず、インストール。

インストールは、easy_install というツールを利用するのが便利であるが、
このツールを利用するためには、予め、python-setuptools が必要となる。
念の為に、このツールのインストール方法もメモしておく。

sudo apt-get install python-setuptools
sudo easy_install pyshp

さて、実は、 pyshp というライブラリ、日本語が入ると色々とエラーが発生し、
上手く、shapefile に変換することができない。
そこで、インストールしたソースを修正し、日本語に対応できるようにする

まず、インストールされているソースを開く。
バージョンが変わっているかもしれない。注意する。
とりあえず、この記事の執筆時点では、以下のパスの下に存在していた。

/usr/local/lib/python2.7/dist-packages/

もちろん、インストールの仕方によって場所は異なる可能性がある。
まぁ、この記事を読んでいる人であれば、余計な話か。
とにかく、編集する。「vi」と言いたいところであるが「gedit」での編集。

sudo gedit /usr/local/lib/python2.7/dist-packages/pyshp-1.1.4-py2.7.egg/shapefile.py

最初に修正するべき箇所は、エンコーディングのオマジナイ。
とにかく、以下の二行を、ソースの先頭に入れておく。

#!/usr/bin/python
# -*- coding: utf-8 -*-

次に、エラー回避を行うためのコードを追加。376行目辺りとなるか?
def __dbfRecords(self): という関数の部分を修正する。
size = int(size) の後ろに、value = str(value.encode("utf-8")) を追加するだけ。

ようするに、エンコーディングエラーの対策
とりあえず、以下のようになる。

def __dbfRecords(self):
"""Writes the dbf records."""
f = self.__getFileObj(self.dbf)
for record in self.records:
   if not self.fields[0][0].startswith("Deletion"):
f.write(b(' ')) # deletion flag
   for (fieldName, fieldType, size, dec), value in zip(self.fields, record):
fieldType = fieldType.upper()
size = int(size)
value = str(value.encode("utf-8"))
if fieldType.upper() == "N":
   value = str(value).rjust(size)
elif fieldType == 'L':
   value = str(value)[0].upper()
else:
   value = str(value)[:size].ljust(size)
assert len(value) == size
value = b(value)
f.write(value)

これで準備完了。あとは、変換するためのプログラムを書くだけ。
自分でコーディング人は、ここまでの情報があれば良いかもしれない。
ということで、次回は、実際にコーディングをしてみる。

1 件のコメント:

  1. なにやら、他にも色々な方法があるようですね。
    以下のような情報提供を頂きました。

    以下から==========================
    FOSS4G を活用した衛星データ利用のためのオープン・リソースの構築
    リンク先:http://www.osgeo.jp/foss4g-mext/

    返信削除