PostGIS(地理情報システムを実現するための拡張モジュール)

1 PostGIS とは

PostGIS は、地理情報システム(Geographic Information Systems 、GIS)を実現するための PostgreSQL の拡張モジュールです。PostgreSQL 本体と独立にオープンソースソフトウェアとして開発されています。

PostGIS により、専用のデータ型が追加され、GIS オブジェクト、すなわち緯度経度による位置を持った地点や経路線、領域などの要素を格納することができます。また、GIS オブジェクトを操作する多数の関数が追加されます。SQL からテーブルに登録した GIS オブジェクトのデータ演算をしたり、検索条件に使うことができます。さらに、GiST インデックスを使った空間検索や近傍点検索が可能です。

PostGIS はカナダの Refractions Research Inc.で開発され、オープンソースソフトウェアとして様々な開発者の手により開発が続けられています。PostGIS は、OSGeo 財団(The Open Source Geospatial Foundation)のインキュベーションプロジェクトの一つとなっています。2018年 10月確認時の PostGIS 安定板はバージョン 2.5.x で、3.0 が開発中となっています。

2 インストール

PostGIS は C 言語で記述された拡張モジュールです。また GIS オブジェクトを処理するためのライブラリを利用しています。主要な必要ライブラリとして以下があります。

    • GEOS (Geometry Engine, Open Source) – ジオメトリライブラリ

 

    • GDAL (Geospatial Data Abstraction Library) – ラスタ処理

 

  • Proj4 (Cartographic Projections Library) – 投影変換ライブラリ

これらのライブラリは地理情報処理で使われる機能を提供します。PostGIS と同様 OSGeo のプロジェクトページから入手することができます。これらのライブラリを利用するために、さらにデータの入出力のための libXML、JSON-C 等のライブラリが必要です。

必要なライブラリが多数あり、それぞれの対応バージョンも影響するので、ソースコードからインストールするのは、少々手間がかかります。そのため、できあいの構成でも問題なければ、バイナリパッケージを利用することをお勧めします。PostGIS の動作に必要なライブラリは PGDG(PostgreSQL と周辺ソフトウェアのための yum リポジトリサイト)で配布されていますので、PGDG を利用するのが便利でしょう。

本稿では CentOS 6.x または 7.x を想定して、yum コマンドを使って以下の各配布元のリポジトリから、必要となるパッケージを取得できるように yum.repo.d ファイルを設定し、利用することとします。

パッケージ配布元

    • PostgreSQL,PostGIS

http://yum.postgresql.org/
PGDG が提供するバイナリパッケージ

    • Extra Packages for Enterprise Linux (EPEL)

https://fedoraproject.org/wiki/EPEL

Red Hat Enterprise Linux や CentOS でサポートされていないパッケージが配布されています

OS(RHEL,CentOS)側のインストール方法にもよりますが、標準的な構成だとインストールされていない OS 付属のライブラリが必要になることがありますので、各ディストリビューションのサイトや DVD-Media からパッケージが追加導入できるようにして下さい。

PostgreSQL サーバと、(そのバージョンに対応した) PostGIS をインストールします。

# yum install postgresql94-server postgis2_94

なお、PostGIS は Windows 版 PostgreSQL でも利用可能です。PostGIS Web サイトの以下ページにて Windows むけバイナリモジュールが配布されています。これは、一般的な EnterpriseDB 社による Windows むけ PostgreSQL バイナリ配布と組み合わせて使用するようになっています。

    • PostGIS Web サイト

 

3 データベースクラスタの準備

パッケージからインストールした PostgreSQL を使って、データベースクラスタを作成します。この部分は通常の PostgreSQL データベースクラスタを準備するのと変わりはありません。postgresql.conf や pg_hba.conf は必要に応じて調整してください。

$ su - postgres
$ initdb --no-locale --encodig=UTF8

ラスタ処理で使われる GDAL ライブラリで画像フォーマットへの変換機能を使うには、環境変数を設定して postgres を起動する必要があります。必要に応じて postgres 起動時の設定をして下さい。

$ export POSTGIS_GDAL_ENABLED_DRIVERS=ENABLE_ALL
$ pg_ctl start

サーバが起動したら、使用するデータベースに
ここでは PostGIS で利用するデータベースとして “gisdb” を作成して、拡張機能を登録します。

$ createdb gisdb
$ psql gisdb
gisdb=# CREATE EXTENSION postgis;
CREATE EXTENSION
gisdb=# SELECT postgis_version();
            postgis_version
---------------------------------------
 2.2 USE_GEOS=1 USE_PROJ=1 USE_STATS=1

以上で PostGIS の基本機能が利用できるようになりました。

なお、postgisパッケージでは他にも以下の拡張モジュールが提供されます。

    • postgis_topology

 

    • address_standardizer

 

  • postgis_tiger_geocoder

postgis_topology は、点(ノード)とそれらの間の向きを持った経路(エッジ、フェイス)を処理できるトポロジ機能を実現するものです。address_standardizer は住所文字列を解析する関数を提供し、postgis_tiger_geocoder は住所から地点を割り出すジオコーダーの実装です。ただし、これら二つは日本の住所むけには作られていません。

4 geometry データ型

PostGIS では、地図上の様々な要素を扱うことができます。点、線、多角形をあらわす POINT、LINESTRING、POLYGON、また、これらの複数の要素をあらわす MULTIPOINT、MULTISTRING、MULTIPOLYGON といったデータ型が扱えます。ただし、PostgreSQL のデータ型としては共通の geometry 型を使います。ある geometry 型カラムにおける内部的なデータ型は、型の属性として保持されます(以前の PostGIS では別の管理テーブルで保持していました)。

geometry 型のカラムをテーブルに追加するには、専用の関数を使用します。以下の例では t1 テーブルに 2次元の POINT を格納する p1 カラム を追加しています。

gisdb=# CREATE TABLE t1 (id int primary key);

gisdb=# SELECT addGeometryColumn('t1', 'p1', 4326, 'POINT', 2);
             addgeometrycolumn
-------------------------------------------
 public.t1.p1 SRID:4326 TYPE:POINT DIMS:2
(1 row)

gisdb=# d t1
             Table "public.t1"
 Column |         Type         | Modifiers
--------+----------------------+-----------
 id     | integer              | not null
 p1     | geometry(Point,4326) |
Indexes:
    "t1_pkey" PRIMARY KEY, btree (id)

上記の addGeometryColumn の 3 番目の引数 4326 は、SRID (空間参照系の識別子)です。POINT 型は二つの数値のペアで地点を示しますが、この値が何の意味であるのかを SRID 値で識別します。4326 であれば、GPS で使用される WGS84 測地系に基づく緯度・経度であるという意味になります。

geometry 型のデータを与えるには、WKT/WKB 形式、あるいは、3 次元対応や SRID 付記ができるように拡張した EWKT/EWKB 形式を使用します。以下のように関数を通して値を指定します。単に geometry 型カラムを参照するとバイナリ形式( EWKB 形式)の 16 進数表現が返ります。参照時にも関数で変換すると、人間に読みやすいテキスト形式(EWKT形式)になります。

gisdb=# INSERT INTO t1 VALUES (1, ST_GeomFromText('POINT(139 36)',4326));
INSERT 0 1
gisdb=# SELECT * FROM t1;
 id |                         p1
----+----------------------------------------------------
  1 | 0101000020E610000000000000006061400000000000004240
(1 row)
gisdb=# SELECT id, ST_AsText(p1) FROM t1;
 id |   st_astext
----+---------------
  1 | POINT(139 36)
(1 row)

5 SQL を使って演算する

データベースに登録されたジオデータから何を求めるのかは、実際のアプリケーションの目的によって異なります。地理情報として、所在地など位置を示す座標は POINT、道路など経路を示す線分は LINESTRING、区画など範囲を示す領域は POLYGON、といった形で表現され、それらの集合がデータベースのテーブルに収められます。

リレーショナルデータベースシステムならではの処理は、検索条件による抽出や、対象の集合に対する集約や演算といった操作です。PostGIS には GIS 演算を行なう関数や演算子が多数あり、”geometry” と “geometry” の間で演算させることができます。

例えば、地域の店舗所在地の入ったテーブルがあるとして、GPS などから取得された現在値データ POINT(xxx yyy) から、最寄りの店舗を探すには、ST_Transform 関数で緯度経度を平面座標に変換したうえ、距離を返す演算>子 <-> を使って実現できます。先ほど作ったテーブルで記述すると SQL は以下のようになります。SRID を 32654 という東日本エリアに適合した投影座標系に変換してメートル単位の距離を算出しています。

gisdb=# SELECT id,
  ST_Transform(p1, 32654) <->
  ST_Transform(ST_GeomFromText('POINT(139.11234 35.998765)', 4326), 32654)
  AS distance FROM t1 ORDER BY distance ;
 id |     distance
----+------------------
  1 | 10129.7747482435
(1 row)

この SQL はインデックスを利用して高速に実行することが可能です。以下のように SRID 変換を加えた関数インデックスを gist 方式で作成します。テストするために、t1 にランダムなデータを追加しておきます。EXPLAIN を付けて検索の SQL を実行すると、インデックスが使われていることがわかります。

gisdb=# CREATE INDEX ON t1 USING gist (ST_Transform(p1, 32654));
CREATE INDEX

gisdb=# INSERT INTO t1 SELECT g, ST_GeomFromText(
  'POINT(' || 139 + random() || ' ' || 36 + random() || ')' ,4326)
  FROM generate_series(2, 1000) as g;
INSERT 0 999

gisdb=# explain SELECT id,
  ST_Transform(p1, 32654) <->
  ST_Transform(ST_GeomFromText('POINT(139.11234 35.998765)', 4326), 32654)
  AS distance FROM t1 ORDER BY distance ;
                                                   QUERY PLAN
----------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.14..0.58 rows=5 width=36)
   ->  Index Scan using t1_st_transform_idx on t1  (cost=0.14..86.64 rows=1000 width=36)
         Order By: (st_transform(p1, 32654) <-> '01010000208E7F00006E9E77C405221441A764D69719684E41'::geometry)
(3 rows)

矩形範囲(四角形の範囲、バウンディングボックスと呼ばれます)の検索にも gist インデックスが使えます。以下の例は緯度経度で指定した四角形に含まれる地点を返します。Box2D 関数で矩形を構成して、&& 演算子で重なりがあるかを調べます。今度は緯度経度のまま演算しているので、インデックスは、関数無しに作成しています。

gisdb=# CREATE INDEX ON t1 USING gist (p1);
CREATE INDEX

gisdb=# SELECT id, ST_AsText(p1) FROM t1 WHERE
  p1 &&
  Box2D(ST_GeomFromText('LINESTRING(139.5 36.5, 139.6 36.6)', 4326));
 id
-----
  11
 323
 503
 663
 669
 683
 804
(7 rows)

6 データの編集

PostGIS はデータベースシステムとして、保存されているデータを操作することができますが、その結果を分かりやすく表示する機能はありません。GIS データは、それ単体で見れば数値の羅列でしかなく、人間に取っては把握しにくい物です。

地理情報の表示と操作は GUI ツールを使うのが良いでしょう。GIS データを扱うプログラムでは、バックエンドデータベースとして PostGIS に対応している物があります。フリー&オープンソースソフトウェアでは QGIS というツールが便利です。

7 地理情報データの入手

日本国内の情報なら、国土交通省・国土地理院が提供している地理空間情報ライブラリなどが利用できます。

データは shape 形式で提供されているので、PostGIS 用に変換して利用することになります。PostGIS には変換するための shp2pgsql コマンドが付属しています。

8 まとめ

PostGIS は広く使われている PostgreSQL で地理情報を扱う基盤といえます。本格的な地図に連動したシステムを開発する場合には、専用のミドルウェアやプラットフォームソフトウェアを使うことが多く、それらの足回りとして、PostGIS が使われています。

一方で、それらの専用のミドルウェアを使うほどでもないけれども、データに位置情報を含めて、距離や範囲に基づいた検索をしたいという場合には、PostGIS を直接利用する方法も十分魅力的です。

PostGIS に関する情報収集には、PostGIS Web サイトの他、OSGeo 財団 (The Open Source Geospatial Foundation )の Web サイトからもメーリングリストや過去の講演資料など関連する資料を探すことができます。また、少し古いですが Let’s postgres に入門記事があります。以下にリンクを示します。