MySQLで学ぶGIS入門 第29回

地球上の「まっすぐ」を理解してST_Touches()の意外な判定結果の謎を解こう

第29回の今回は、地理座標系における「まっすぐな線」の意味を理解し、一見接しているように見えたポリゴンがST_Touches()でFALSEになる理由と、平面と見なすことで回避する方法について解説します。

坂井 恵 (さかい けい)

6:30

はじめに

前回は、基準ポリゴンの下の辺にぴったり接するように作ったはずのポリゴンが、ST_Touches()で 0(FALSE)と判定される動作を紹介しました。一見接しているように見えるこのポリゴンが接していないというのはどういうことなのか。「まっすぐ」とは何かというテーマを軸に、読み解きます。

前回のおさらい

今回のテーマに関係する2つのポリゴンを示します。@polyが基準ポリゴン、@poly4がその下辺に接するつもりで作った対象のポリゴンです。

mysql> SET @poly = ST_GeomFromText(
    ->   'POLYGON((35 135, 35 135.01, 35.01 135.01, 35.01 135, 35 135))', 6668);

mysql> SET @poly4 = ST_GeomFromText(
    ->   'POLYGON((34.996 135.006, 34.996 135.011, 35 135.011, 35 135.006, 34.996 135.006))', 6668);

青い色の基準ポリゴンに対して、その下辺に赤い色の小さなポリゴンが接しているように見えます。

この2つのポリゴンに対する ST_Touches()とST_Overlaps()の結果です。

mysql> SELECT ST_Touches(@poly, @poly4)    Tch,
    ->        ST_Overlaps(@poly, @poly4)   Ovl;
+------+------+
| Tch  | Ovl  |
+------+------+
|    0 |    1 |
+------+------+
1 row in set (0.000 sec)

「接しているように見える」という直感に反して、この2つのポリゴンは Touch(接触)しておらず、Overlap(重なり)しているという結果を得ました。MySQLが壊れているのでしょうか。いいえ、これには理由があるのです。

 「まっすぐな線」とは何か

その謎を紐解くために、地球上での「まっすぐな線」というものを正しく理解する必要があります。規模を拡大したほうが分かりやすいので、先ほどとは別のシンプルな例を考えてみましょう。

(北緯, 東経)が (35, 135)と(35,179)の2つの点をイメージしてみてください。この2点を結ぶ直線とはどのようなものでしょうか。日本のへそから同じ緯度のまま東のほうにずーっと太平洋のどまんなかまで伸ばした線でしょうか。

上のような線を考えた人は、有名な「東京とニューヨークを結ぶ最短経路は?」という課題を思い出してみてください。そう、カリフォルニアを経由するのではなく、ずっと北にあるアラスカを経由するのが最短距離になりますよね。なので、先ほどの2点を結ぶ最短距離(≒まっすぐな線)とは以下のようになります。

どのくらい膨らむのか、気になりますよね。計算してみましょう。今回は同じ緯度の2点なので、最短経路がいちばん北に達するのは中間地点です。経度差の半分を(179-135)/2 で求めています。

mysql> SELECT ROUND(DEGREES(ATAN(TAN(RADIANS(35)) / 
    ->       COS(RADIANS((179-135)/2)))), 2) AS mid_lat;
+---------+
| mid_lat |
+---------+
|   37.06 |
+---------+
1 row in set (0.002 sec)

北緯37.06度。出発点も到着点も北緯35度なのに、その中間はおよそ2度も北にずれています。距離にして200kmあまり。東京と福島くらいの差です。「メルカトル脳」で眺めると随分と遠回りしているように見える線こそが、2点間を最短で結ぶ「まっすぐ」な線なのです。

地理座標系における四角形とは

さて、この話を本連載における基準ポリゴンの下辺に当てはめてみましょう。北緯35度のまま東経135度から135.01度までを結ぶ直線というのが、この下辺に与えられた定義です。もう分かりますね。この下辺の中間点は (35, 135.005)ではありません。35度よりも僅かに北にずれた位置になります。

少し誇張して書くと下図のような形になります(緑点線は同緯度の点を結んだもの)。実際には今回のケースでは35度線との差は最大でも1cmかそこら程度なので、実務上は微々たるものかもしれませんが、判定に使うには無視できない違いになるのです。

ここまで来れば、勘の良い方はもう気づいたでしょう。下部に接した(つもりの)ポリゴンをこの図に描き加えると、下図のようになります。

これが「接触判定はFALSEになり、重なり判定がTRUEになる」ことの正体です。

他のRDBMSとの違いは?

地理情報データを扱う上で、そのデータを曲面上で扱うのか平面と見なして近似的に扱うのかというのは、避けて通れない話題です(ジオグラフィとジオメトリと言います)。MySQLではSRIDを指定することで、それが地理座標系であれば原則として曲面上での演算を行い、それ以外であれば平面としての計算を行います。

一方の PostGISでは、利用者側がジオグラフィとジオメトリを意識し、指定して使うことができます。特に指定がない場合にはジオメトリとして、つまり平面と見なした簡易的な演算を行う動作がデフォルトとなっている関数が多いようです。今回のテーマである ST_Touches()も平面と見做して接触判定を行うよう実装されているため、今回の2つのポリゴンにも「接触している」という結果を返します。

2点間の最短距離を基準とするMySQLの動作に、個人的には「正しさ」のようなものを感じますが、実際の世の中では、同じ緯度の2点を結ぶ直線は常に同じ緯度を通り続けるという「まっすぐ」が直感的でもあり、実際に活用されていることが多いかと思います(どちらか一方が「正しい」というわけではありません)。

分かりやすい例としては、境界線などが挙げられます。アメリカの州の境界線は直線的な部分が多いことで有名ですが、例えばコロラド州は南北が北緯37度から41度、東西が西経102度3分から109度3分までの線に囲まれた四角形であるとされています。POLYGONで表すならたったの4点(POLYGONで表現するときは終点=始点の指定が必要なので5点)で表せそうな形です。ここで辺をなす2点を結ぶ線は、あくまでも緯線または経線であり、その東西2点を結ぶ最短経路ではないことに注意が必要です。

MySQLの動作は地球の曲面を実直に意識したもので、ある意味「几帳面すぎる」と言えるかもしれません。

平面として判定させる

最初の2つのポリゴンに話を戻しましょう。MySQLでこの2つのポリゴンの関係を「接している」と判定させるにはどうすれば良いのでしょうか。答えは、平面座標系と見なして計算させる、ということです。

MySQLでは ST_SRID() という関数により、数値をそのままに座標系(SRID)だけを他のものに変更できます。その座標系に変換してくれるわけではなく、単にそのSRIDのものだと見なして処理してくれるこの関数が、今回役に立ちます。SRID=6668という地理座標系の情報を、平面であるSRID=0と見なし、判定関数に喰わせれば良いのです。

実際にやってみましょう。先ほどの判定に使っていたSQL内でジオメトリを与えていた部分すべての値をST_SRID()に噛ませて、SRID=0のものと見なして使用するようにします。

mysql> SELECT ST_Touches(ST_SRID(@poly,0), ST_SRID(@poly4,0))    Tch,
    ->        ST_Overlaps(ST_SRID(@poly,0), ST_SRID(@poly4,0))   Ovl;
+------+------+
| Tch  | Ovl  |
+------+------+
|    1 |    0 |
+------+------+
1 row in set (0.000 sec)

無事に接触判定され、重なりはないと判定されました。なお、平面と見なして演算するこの方法は、図形どうしの関係を見る場合にのみ使用してください。緯度経度の数値をそのまま平面と見なした状態での距離や面積の値は意味を持たないことに注意してください。

おわりに

今回は、直感的には接しているように感じるのに接していない、の謎解きをしました。地球は丸い、その丸い地球に応じた演算ができるのがすごい、と考えがちですが、時によってはシンプルに平面で考えるほうが人間の営みに合致しているということが分かりました。

今回も、表示用の地図データはOpenStreetMapデータを使用しました。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored