位置情報を可視化しよう![PostGIS入門]
最近のプロジェクトにて、Geo系データを扱うことがあり、一部の機能でPostGISを利用しました。PostGISはPostgreSQLの拡張機能として提供されており、SQLを書ければ利用できるため学習コストが低いと感じています。
用語解説
・PostgreSQL:オープンソースのRDBMS。象のマークでおなじみ
・GIS:Geographic Information Systemの略。地図を作るためのソフトウェアの総称
・PostGIS:PostgreSQL上でGISオブジェクトを利用できるようにした拡張機能
今後、Geo系データの利用は増えていく傾向がありそうですので、PostGISを利用したGeo系データの扱い方を紹介します。
PostGISのはじめかた
今回はDockerを使って環境を整えていきたいと思います。
①docker-composeファイルを用意する
version: '3.7'
services:
postgis:
image: mdillon/postgis:11
container_name: postgis
ports:
- 5432:5432
volumes:
- ./docker/postgres/init.d:/docker-entrypoint-initdb.d
- ./docker/postgres/pgdata:/var/lib/postgresql/data
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: root
POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
hostname: postgres
restart: always
user: root
pgadmin4:
image: dpage/pgadmin4
container_name: pgadmin4
ports:
- 8000:80
volumes:
- ./docker/pgadmin4:/var/lib/pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: root
PGADMIN_DEFAULT_PASSWORD: root
hostname: pgadmin4
depends_on:
- postgis
restart: always
②コンテナを起動
docker-compose up -d
③PostGISをインストール
$ psql -h localhost -U root
$ CREATE EXTENSION IF NOT EXISTS postgis;
④テーブルを作成
CREATE TABLE geo_sample (
id integer PRIMARY KEY,
name varchar(255),
geom geometry(POINT, 4326)
);
⑤データを投入
INSERT INTO geo_sample VALUES (1, '表参道駅', ST_GeomFromText('POINT(139.712288 35.664342)',4326));
INSERT INTO geo_sample VALUES (2, '青山一丁目駅', ST_GeomFromText('POINT(139.725146 35.672963)',4326));
INSERT INTO geo_sample VALUES (3, '赤坂駅', ST_GeomFromText('POINT(139.7365419 35.671949)',4326));
知っておきたいキーワード① geometry
PostGISのgeometry型では様々な形を表現することができます。geo_sampleテーブルに出てきた、点を表すPOINTの他にも、線を表すLINESTRINGや図形を表すPOLYGONがあります。また、それらを複合的に保持するMULTIタイプもあります。
画像はWikipediaより引用
https://ja.wikipedia.org/wiki/Well-known_text
知っておきたいキーワード② SRID
SRIDは空間参照系の識別コードです。PostGISにはSRIDが多数登録されているため、用途によって使い分けます。
4326(GPSで得られる位置)、3857(Open Street MapやGoogle MapsなどのWeb地図アプリケーションで利用)、2163(距離をメートルで測るときに利用)などがあります。地図上に描画する目的であれば4326を使えば大丈夫だと思います(この辺についてはあまり詳しくないです)。
知っておきたいキーワード③ WKT
geomety型のデータは、WKT(Well-known text)形式で保存されています。WKTはベクタ形式幾何学オブジェクトを投影法(地図)を基に変換し地図上に表現させるマークアップ言語です。緯度経度とWKTはPostGISの関数により相互に変換可能となっています。
例えば、表参道駅の緯度経度 "139.712288,35.664342"は
"0101000020E6100000AA2A3410CB766140FBAD9D2809D54140"
という形で保存されます。
pgAdminの使い方
PostGISの初期設定はコマンドで実行しましたが、geometry型のオブジェクトを参照する時にはpgAdminが便利です。pgAdminのコンテナも起動済みですので、 以下にアクセスして利用してください。
http://localhost:8000/
こんな感じで利用できます。SRIDは4326を使わないと地図上にマッピングできないので注意してください。
POINTだけでなく、LINESTRINGやPOLYGONも描画可能です。
POSTGISの使い方
ここからいくつか使い方をまとめていきます。その他のPostGISの関数についてはこちらをご参照ください。いくつかはサンプルSQL付きで紹介します。
SRIDを確認する / 変更する
SRIDを確認する:ST_SRID()
select id,name,ST_SRID(geom) from geo_sample;
SRIDを変更する:ST_Transform()
select id,name,ST_SRID(geom),
ST_SRID(ST_Transform(geom,2163)) from geo_sample;
Text to WKT / WKT to Text
WKT to Text:ST_AsText()
select 'ミクロネシア連邦大使館',
ST_AsText('0101000020E610000004BBAB68BD7761409013268C66D54140');
Text to WKT:ST_GeomFromText()
select 'ミクロネシア連邦大使館',
ST_GeomFromText('SRID=4326;POINT(139.7418712 35.667192)');
2点間の距離を求める: ST_Distance()
2点間の距離を求める:ST_Distance() もしくは <->。<->の方が高速らしい。
SRIDには2163(米国ナショナルアトラス正積図法)を利用する。
select a.name || ' to ' || b.name,
ST_Distance(
ST_Transform(a.geom, 2163),
ST_Transform(b.geom, 2163))
from geo_sample a, geo_sample b
where a.name = '表参道駅' and b.name = '青山一丁目駅';
ポリゴンに含まれているか判定する
ポリゴンに含まれているか判定する:ST_Within() 。この辺りからgeo_sampleに含まれていないPOLYGONを利用するのでサンプルSQLはなしです。
LINESTRINGの距離を求める
LINESTRINGの距離を求める:ST_Length()
Polygonの面積を求める
Polygonの面積を求める:ST_Area()
Polygonを結合する
Polygonを結合する:ST_Union()
まとめ
PostGISの機能や使い方について紹介しました。SQLで操作できるため比較的簡単に使い始めることができます。Geo系のデータの利用は今後拡大していくと考えられますので、使えると便利な起動だと思います。
この記事が気に入ったらサポートをしてみませんか?