GEOGRAPHY型ってのがあることをちょっと書いてみる

今回は Advent Calendar 特別企画だ

http://atnd.org/events/23085 参照。
http://d.hatena.ne.jp/waigani/20111210 とか http://d.hatena.ne.jp/wata909/20111211 が先行していて、ハードルが高まっていってるわけですが、気にしたら負け。

なので、いつものに近いようなことを書くことにしました。

ならいっそのこと「いつも通り」と称して、既に書いているエントリの日付を変えとこうかとも思いましたが、いやそんなことしたらさすがにマズいだろと思ったのですが、そんなに見られてないだろうから気づかれない可能性がかなりあるとも踏みましたが、えー、これ、本当に新規のエントリです。本当です。

それと、さすがに完全な個人メモではアレなかんじもするので、ほかの方が読まれるだろうことを、多少は考えて書くことにしました。

ST_Distanceは単純な計算

PostGIS で ST_Distance という、距離を求める関数があるのですが、これは sqrt(Xの差^2+Yの差^2) を出しているだけです。

db=# SELECT ST_Distance('SRID=4326;POINT(1 1)'::geometry, 'SRID=4326;POINT(4 5)'::geometry);
st_distance

                        • -

5
(1 row)

こんなかんじ。

定規を当てて測れない

予備知識なく地理空間を扱い始めると、sqrt(経度差^2+緯度差^2) で正しい距離が出ると思ってたのを正直に告白します。これ実は大変おかしい話です、正座して説教聞かんといかんレベル。

三平方の定理」は中学校でやったと思いますが、その際、「この直角三角形は直角をはさむ辺が3cm, 4cm とします、斜辺の長さはいくらでしょうか、定規を当てて測ってみましょう、5cmですね」みたいなのがあったかも知れない。これ、しれっと言ってますが、平面でないと話が成り立たず、球面だととたんにややこしくなり、定規を当てて測れなくなります。

定規を当てて測れない場合 ST_Distance は使えないことになります。

「一般的な」解決法

じゃあいつまでも ST_Distance が使えんのかと言えばさにあらず、経度・緯度で位置を指すのではなく、いったん平面にプロットして定規をあてて測れるようにしてしまえば良いんです。歪みは必ずでるのですが、十分に小さければ良しとします。

これが投影法*1

日本の陸域の地図では、2500分の1は「平面直角座標系」、25000分の1では「UTM」を使用しています。範囲内であれば、結構ゆがみが少ないので、投影変換して ST_Distance を実行すればOKです。

GEOGRAPHY型

でも、投影法とかを真面目に見ていくのも面倒くさい、経度緯度で示された点の距離がズバッと出れば良いのに…そう思ったあなたにおすすめなのが、PostGISのGEOGRAPHY型です。

SELECT ST_Distance('POINT(0 0)'::geography, 'POINT(90 0)'::geography);
st_distance

                                  • -

10018754.1701286
(1 row)

こんなかんじ。
赤道上で東に90度進んだ際の距離が、特に何も考えずに、メートル単位でズバッと出ます。
前の例と違うところは "::geometry" でなく "::geography" となっているところと、"SRID="が付いていないところ。
前者について、"::"でPostgreSQLの型変換を行っているのですが、GEOMETRY型に変換するのでなくGEOGRAPHY型に変換する、というだけといえばそれだけ。
後者について、GEOGRAPHYは必ず WGS84緯度経度 (EPSG:4326) となります。なので "SRID="を付けなくても "SRID=4326" と考えてくれます。なお、JGD2000 という日本国内の陸域の地図で使用される測地系(測量の基準)と違う(SRID=4612)のですが、かなり近いので、まああんまり気にしないで下さい。

GEOGRAPHY型を使わん場合はかなりある

PostGISにGEOGRAPHYが導入されても、あまり使われていないかも知れません。考えられる理由は次の通りです。

  • 対応する関数が少ないので、使い込むなら GEOMETRY型 を使った方が良い。
  • 投影変換を施しておく(「定規を当てられる」ようにする)方が、GEOGRAPHY型の計算より計算量が小さくなるので、使いまわすなら GEOMETRY型 にした方が良い。

でも実は次のことが一番の理由かも知れないと思ってたりします。

  • 意外と知らないだけかも知れない。

*1:「距離とか誤差がいくら出てもええから、とにかく地図上で行先の方角が正しく出したい」とかいろんな要求があるので、定規をあてて測れるようにするのは、多数ある投影法の一部の話です