ITに関するさまざまなトピックを紹介するサイトです
このコンテンツはお使いのブラウザには対応しておりません。
新しいバージョンのブラウザでアクセスしてください。

OpenStreetMapの地図情報からタイル画像を生成する


OpenStreetMap(© OpenStreetMap contributors)は、アカウント登録すれば誰でも編集することができ、自由に利用できる地図です。
OpenStreetMapの地図を自分のWebページに組み込むこともできます。
Web地図サービスを提供するためには、地図情報をタイル状の画像として表示させる必要がありますが、その最も単純な構成として、あらかじめ地図情報をレンダリングしてタイル画像ファイルを生成しておき、それをWebサーバに静的に配置しておく方式があります。
ここでは、OpenStreetMapの地図情報を取得してタイル画像ファイルを生成するための環境構築とその処理手順について説明します。
OpenStreetMapのデータは、Open Data Commons Open Database License (ODbL)の下にライセンスされています。
今回はWindows環境で実行しました。利用した各プロダクトのバージョンは以下の通りです。
プロダクト バージョン
Windows7 Professional 64bit
スタックビルダ 3.1.1
PostgreSQL 9.3.0 (Windows 64bit)
PostGIS 2.1.0
osm2pgsql git rev af61cae663
Python 2.7.5 (Windows 32bit)
Mapnik 2.2.0
  このページのコンテンツは、2013年10月における動作確認に基づいて作成しています。
特定の環境においてのみ動作確認しているため、記載通りの結果にならない可能性があることをご了承ください。

OpenStreetMapの地図情報取得

Planet.osmというOpenStreetMapのデータベースのスナップショットがあり、このデータを取得することが可能です。
このデータは更新履歴のない最新の情報のみを含んでおり、週1回のペースで更新されているようです。
ダウンロードできるデータはXML形式で、拡張子は".osm"となっています。
2011年7月の時点の情報によると、全世界のデータは250GBにもなり、bzip2圧縮しても14GBあるそうです。
タイル画像を生成することを考えると、広いエリアを対象とするのはリソース面でかなり厳しくなりますが、限られた狭い地域だけを対象とするなら容量を抑えられます。
ダウンロード用にはミラーサイトもあり、エリアを限定した部分抽出に対応したサイトもあります。
ここでは、部分抽出に対応している以下のミラーサイトを利用しました。
あらかじめたくさんの都市のエリアが定義されていて、簡単にダウンロードできるようにもなっていますが、特定の地域を自分で選択するためには「Select your own region」のリンクをクリックします。
最初に「Help」ウィンドウがポップアップ表示されます。
以下がメインの操作画面です。
Planet.osmデータ抽出操作画面は操作パネルと地図で構成されています。
BBBike.orgのPlanet.osmデータ抽出操作画面
左側に操作パネルがあり、右に地図が表示されています。
まず、地図をドラッグしたり、拡大・縮小して、おおまかに目的のエリアを表示させてください。
それから、地図の右端の上の方にある小さい「+」をクリックして、レイヤを「OSM Mapnik」に切り替えてください。
操作パネルの「here」ボタンをクリックすると、地図に境界ボックスが重ねて表示されるので、対象エリアを微調整してください。
操作パネルの右側に対象エリアの面積、ダウンロードファイルサイズとファイル生成に要する目安の時間が表示されるので、参考にしてください。
操作パネル右上の「show lnglat」をクリックすると、境界ボックスの東西南北の緯度・経度の座標が表示されます。地図を表示させる処理を実装する時や、再度同じエリアの最新データを取得する際に使用しますので、記録しておいてください。
必要事項を入力して、「extract」ボタンをクリックします。
ここでは、ほぼ東京都文京区をカバーするエリアを指定しました。ファイル形式には「OSM XML」のgzip圧縮を指定しました。

ファイルの生成処理が完了すると、ダウンロードリンクが記載されたメールが送られてきます。
ダウンロードは48時間以内可能となっています。
上記のエリアを指定してダウンロードしたファイルはgzip圧縮で約2MBでした。
なお、後の処理でデータベースにロードする際、gzip圧縮されたままのファイルを入力ファイルに指定できるので、解凍する必要はありません。

PostGISデータベースの構築

PostGISは、PostgreSQLを拡張した空間データベースです。 取得したPlanet.osmのデータは、まずこのデータベースに変換してロードすることになります。
PostgreSQLのインストーラには、拡張モジュールやツールをインストールするスタックビルダが付属していて、PostGISも簡単にインストールすることができるようになっています。
以下のサイトからインストーラをダウンロードしてください。
EnterpriseDB Download PostgreSQL
ここでは、Windowsの64bit版(postgresql-9.3.0-1-windows-x64.exe)をダウンロードしました。
インストーラを起動して、PostgreSQLをインストールし、完了画面で続けてスタックビルダを起動する指定をして、PostGIS拡張モジュールをインストールするという流れになります。
以下のサイトに非常に詳しく手順が説明されているので、参考にしてください。
バージョンが異なるので、若干異なる部分もあります。
インストール対象のPostgreSQLは「PostgreSQL 9.3(x64) on port 5432」になります。(ポート番号には「5432」を指定しました)
「Spatial Extensions」のカテゴリから選択するPostGIS拡張モジュールは「PostGIS 2.1 Bundle for PostgreSQL 9.3 (64bit) v2.1.0」でした。
ライセンス許諾画面の次のコンポーネント選択画面では、デフォルトで「Create spatial database」にチェックが入っていないので、チェックを入れてください。(後で作業することもできますが、ここではまとめて作成します)
PostGIS用のデータベース名のデフォルトは「postgis_21_sample」と表示されます。ここでは「postgis_21」としました。

データベースの構成も異なります。
PostGISのバージョン2.1ではテンプレートデータベースは作成されなくなったようです。
「pgAdmin III」を起動すると、オブジェクトブラウザにPostgreSQLのオブジェクトが階層構造で表示されます。インストールしたPostGISデータベースも確認できます。
「pgAdmin III」によるPostGISデータベース構成の表示画面
PostGIS用データベースにスーパーユーザで接続するのはよくないので、専用のユーザを作成しました。
postgisというログインロールを作成し、postgis_21データベースのオーナーを「postgis」に変更しておきます。

データベースへの地図情報のロード

1)osm2pgsqlのダウンロード

Planet.osmから取得した地図データを変換して、PostGISデータベースにロードするには、osm2pgsqlというコマンドラインツールを使います。
以下のサイトからosm2pgsql.zipをダウンロードしてください。
OpenStreetMap Wiki Osm2pgsql
「Installation」のセクションの「Windows」の「Binary」の項のところにダウンロードリンクがあります。
ダウンロードしたら、ZIP圧縮を展開します。
ここでは「C:¥osm2pgsql」に展開したとします。

2)スタイルファイルの設定

osm2pgsqlコマンドは、その動作を制御するスタイルファイルというものを使用します。
ところが、ZIP圧縮を展開してもそんなファイルは入っていないので、別のところから取ってくる必要があります。
以下のサイトからdefault.styleファイルを取得してください。
openstreetmap/osm2pgsql · GitHub osm2pgsql/default.style
osm2pgsqlのファイルはGitHubで管理されています。
GitHubを利用して、リポジトリを取得してもよいでしょう。(詳細手順の説明は割愛します)

取得したファイルをそのまま使用するとエラーとなってしまったので、編集が必要でした。
元のファイルを残して、名前を変更してコピーします。
ここでは「C:¥workspace¥my.style」に配置したとします。

そして、"phstore"というフラグが設定してある151行目から156行目をコメントアウトします。
#way         abandoned:aeroway       text    phstore
#way         abandoned:amenity       text    phstore
#way         abandoned:building      text    phstore
#way         abandoned:landuse       text    phstore
#way         abandoned:power         text    phstore
#way         area:highway            text    phstore
先頭に"#"記号を入れるとコメント行になります。
phstoreフラグは、osm2pgsqlをhstoreモードで実行する時に設定することができます。
hstoreというのはkey/valueのペアで値をカラムに格納するPostgreSQLの拡張データ型です。
osm2pgsqlをhstoreモードで実行すると、phstoreフラグが設定された情報がhstoreデータ型のカラムに格納されます。
hstoreモードで実行すると、最終的に生成されるタイル画像にどのような影響があるかは調べきれていません。Wikiページに「めったに使われないタグのために・・・」という記述があったので、大きな影響はないのではないかと思います。

3)環境変数の設定

osm2pgsqlコマンドのパスとPostGISデータベース接続ユーザのパスワードを環境変数に設定します。
環境変数 設定値
Path C:¥osm2pgsql¥x64(既存のPath定義に追加)
pgpassword {postgisユーザのパスワード}
osm2pgsqlコマンドを実行する際には、PostGISデータベースへ接続するユーザとパスワードを指定する必要があります。
osm2pgsqlコマンドのヘルプには「-Wまたは--passwordオプションを指定するとパスワードプロンプトが強制表示される」と記述されています。
しかし、実行してみるとそのオプションは無効になっているようで、エラーになってしまいました!(ユーザオプションは使えました)
パスワードはpgpassword環境変数に設定しておくと、そこから読み取られる仕組みもあるということでした。 パスワードを環境変数に設定するようなことはしたくなかったのですが、仕方なく設定しました。(ユーザ環境変数を利用しました)

4)コマンド実行

osm2pgsqlコマンドを実行します。
ここでは、スタイルファイルを配置した「C:¥workspace」を作業ディレクトリとし、Planet.osmから取得した地図データも「tokyo-bunkyo.osm.gz」という名称でこのディレクトリに配置したとします。
以下のようにオプションを指定して、コマンドを実行します。
C:¥workspace>osm2pgsql -d postgis_21 -S C:¥workspace¥my.style -U postgis -H localhost -P 5432 tokyo-bunkyo.osm.gz
各オプションに設定する値は以下の通りです。
オプション 設定値
-d PostGISデータベース名
-S スタイルファイルのパス
-U 接続するPostGISデータベースのユーザ名
-H 接続するPostGISデータベースのホスト名
-P PostGISデータベースへの接続ポート番号

正常にコマンド実行が終了すると、テーブルが自動的に作成され、地図データが変換されてロードされます。
「pgAdmin III」のオブジェクトブラウザで、postgis_21データベースに5つのテーブルが作成されたことを確認することができます。
PostGISデータベースに作成されたテーブルの表示画面

Pythonのインストール

最終的にはPythonスクリプトでタイル画像を生成するので、Pythonをインストールする必要があります。
この次にインストールするMapnikが対応しているPythonのバージョンが2.7なので、必ずこのバージョンをインストールしてください。
64bit版にも対応していないので、32bit版を選びます。
Python.org Download Python
ここでは「Python 2.7.5 Windows Installer」をダウンロードして、インストールしました。
インストール先のフォルダに「C:¥Python27」を指定したとします。
Pythonコマンドのパスを環境変数に設定しておきます。
環境変数 設定値
Path C:¥Python27(既存のPath定義に追加)

Mapnikのセットアップ

1)Mapnikのダウンロード

Mapnikはオープンソースの地図レンダリングツールです。 PythonスクリプトからMapnikの機能を呼び出して、地図のタイル画像を生成することになります。
以下のサイトからMapnikをダウンロードしてください。
  MapnikのリソースがGitHubに移行したようなので、ダウンロードURLが変わってしまいました。
以前の情報を取り消し、新しい情報を追記しています。
ここでは「Windows 32 bit Package」のリンクからmapnik-win-v2.2.0.zipをダウンロードしました。
(「http://mapnik.s3.amazonaws.com/dist/v2.2.0/mapnik-win-v2.2.0.zip」のリンクからmapnik-win-v2.2.0.zipをダウンロードします。)
ZIP圧縮を展開します。
展開したフォルダを「C:¥mapnik-v2.2.0」にしたとします。

2)環境変数の設定

MapnikコマンドのパスとPythonスクリプト用のパスを環境変数に設定します。
環境変数 設定値
MAPNIK_HOME C:¥mapnik-v2.2.0
Path %MAPNIK_HOME%¥bin
%MAPNIK_HOME%¥lib
(既存のPath定義に追加)
PYTHONPATH %MAPNIK_HOME%¥python¥2.7¥site-packages
(既存定義があれば追加、なければ環境変数新規追加)

3)c++デモ実行テスト

  Pythonスクリプトが動けば問題ないので、この作業ステップは省略しても構いません。
動作確認のために、デモを実行してみます。まずは、c++のデモです。
コマンドプロンプトを起動して、以下のコマンドを実行します。
>cd C:¥mapnik-v2.2.0¥demo¥c++
>rundemo ../..
デモの実行が成功すると、png、jpg、tif、pdf、svgなどの形式の地図の画像ファイルが生成されます。

4)Pythonデモ実行テスト

次は、Pythonのデモです。
コマンドプロンプトを起動して、以下のコマンドを実行します。
>cd C:¥mapnik-v2.2.0¥demo¥python
>python rundemo.py
デモの実行が成功すると、png、jpg、tif、pdf、svgなどの形式の地図の画像ファイルが生成されます。

5)OSM標準Mapnikスタイルファイルの取得

Pythonスクリプトなどを含んだOSM標準Mapnikスタイルファイルをダウンロードします。
ダウンロードしたら、ZIP圧縮を展開します。
ここでは「C:¥mapnik-stylesheets-master」に展開したとします。

ここに必要なファイルがすべて揃っているわけではなく、別途海岸線のShapefilesをダウンロードする必要があります。
Linux環境であれば、get-coastlines.shスクリプトを実行すれば一発でセットアップできそうでしたが、Windows環境なので手動で作業する必要があります。(Cygwinなど、シェルスクリプト実行環境があれば利用してください)
手動で作業する場合は、READMEファイルの「Downloading the Coastlines Shapefiles」セクションに記述されている内容が参考になります。
ZIP圧縮以外に、tgz、bz2の圧縮ファイルも解凍する必要があるので、それらに対応した解凍ツールがインストールされていなければ、あらかじめインストールしてください。
以下の5つの圧縮ファイルをダウンロードします。
world_boundaries-spherical.tgz圧縮ファイルを解凍し、生成された「world_boundaries」フォルダを「mapnik-stylesheets-master」フォルダにフォルダごと配置します。
processed_p.tar.bz2圧縮ファイルを解凍し、生成された「processed_p」フォルダの中のファイルを「world_boundaries」フォルダに配置します。フォルダごと配置するのではないので、注意してください。
同様に、shoreline_300.tar.bz2圧縮ファイルを解凍し、ファイルのみを「world_boundaries」フォルダに配置します。
ne_10m_populated_places.zip圧縮ファイルもne_110m_admin_0_boundary_lines_land.zip圧縮ファイルも、同様にファイルのみ取り出して「world_boundaries」フォルダに配置します。
「mapnik-stylesheets-master」フォルダの「world_boundaries」フォルダは、以下のような構成になります。
「world_boundaries」フォルダの直下に境界線情報ファイルなどが配置されています。
「world_boundaries」フォルダの構成

6)Mapnikスタイルの設定

generate_xml.pyというPythonスクリプトファイルを使用して、構築中の環境に合わせたMapnikスタイルファイルというXML形式の設定ファイルを生成します。
新たに生成するスタイルファイルのファイル名を「my_osm.xml」とします。
generate_xml.pyには、テンプレートXMLファイル名、出力XMLファイル名、各種パラメータを引数として渡します。
テンプレートXMLファイルにはosm.xmlファイルを指定します。
以下のようにパラメータを指定して、スクリプトを実行します。
C:¥mapnik-stylesheets-master>generate_xml.py osm.xml my_osm.xml --host localhost --port 5432 --dbname postgis_21 --user postgis --password {パスワード}
各パラメータに設定する値は以下の通りです。
パラメータ 設定値
--host 接続するPostGISデータベースのホスト名
--port PostGISデータベースへの接続ポート番号
--dbname PostGISデータベース名
--user 接続するPostGISデータベースのユーザ名
--password 接続するPostGISデータベースユーザのパスワード

タイル画像生成処理

長い準備段階を経て、やっとタイル画像を生成する処理を実行する段階に来ました。
「mapnik-stylesheets-master」フォルダの中にgenerate_tiles.pyというPythonスクリプトファイルがあり、このスクリプトを実行してタイル画像を生成します。
このファイルをそのまま実行すると、世界やミュンヘンを対象エリアとした地図のタイル画像を生成します。ファイル内のコメントにも記述されているように、対象エリアを指定するためにはPythonスクリプトのこの部分を書き換える必要があります。
その他に環境変数の設定も必要なのですが、どうせスクリプトファイルを書き換えなければならないので、環境変数を参照している部分をリテラルで指定してしまうことにしました。

まず、元のファイルを残して、新しいファイルをコピーします。ここでは「generate_tiles-bunkyo.py」というファイル名でコピーしました。
環境変数参照部分の書き換えは、194行目、196行目、200行目になります。
194行目から200行目の書き換え前は、以下のようになっています。
home = os.environ['HOME']
try:
	mapfile = os.environ['MAPNIK_MAP_FILE']
except KeyError:
	mapfile = home + "/svn.openstreetmap.org/applications/rendering/mapnik/osm-local.xml"
try:
	tile_dir = os.environ['MAPNIK_TILE_DIR']
書き換え後は以下のようになります。
home = "C:¥mapnik-stylesheets-master"
try:
	mapfile = "my_osm.xml"
except KeyError:
	mapfile = home + "/svn.openstreetmap.org/applications/rendering/mapnik/osm-local.xml"
try:
	tile_dir = "tiles/"
正常に動作する限り、home変数は使用されませんが、元のままでは「HOME」環境変数が設定されていないと、スクリプトがエラー終了してしまうので、適当に設定します。
mapfile変数には、先ほど生成したMapnikスタイルファイル「my_osm.xml」を指定します。
tile_dir変数に「tiles/」と指定したので、生成されるタイル画像は「tiles」フォルダに保存されます。

そして、213行目以下のコードをすべて削除して、保持している地図情報を対象エリアとしてタイル画像を生成する処理を記述します。
minZoom = 15
maxZoom = 17
bbox = (139.7277, 35.6969, 139.7779, 35.7372)
render_tiles(bbox, mapfile, tile_dir, minZoom, maxZoom, "Bunkyo-ku")
minZoomとmaxZommでズームレベルのレンジを指定します。
bboxには、対象エリアの境界となる座標を指定します。
一番最初にPlanet.osmから地図情報を取得した時に指定した境界ボックスの座標を指定してください。
順番は、Left(西の境界の経度)、lower(南の境界の緯度)、Right(東の境界の経度)、top(北の境界の緯度)の順です。
render_tiles関数がタイル画像生成処理を実行する関数になります。最後に指定する地図名は任意ですが、日本語を指定するとエラーになるようなので注意してください。

ついにタイル画像を生成する時が来ました。
「generate_tiles-bunkyo.py」スクリプトを実行してください。パラメータはありません。
成功すれば、「tiles」フォルダにタイル画像が生成されます。
タイル画像ファイルのディレクトリとファイル名は、以下のような構成になっています。
tiles/{ズームレベル}/{X座標}/{Y座標}.png
生成したタイル画像を使用して、実際に地図をWebページに表示させる方法については、このサイト内の以下のページをご覧ください。

当サイトでは、第三者配信による広告サービスを利用しています。 このような広告配信事業者は、ユーザーの興味に応じた商品やサービスの広告を表示するため、当サイトや他サイトへのアクセスに関する情報(氏名、住所、メール アドレス、電話番号は含まれません)を使用することがあります。 このプロセスの詳細やこのような情報が広告配信事業者に使用されないようにする方法については、こちらをクリックしてください。