MySQLの空間拡張機能のaxis orderについて

はじめに

PostGISユーザがMySQL 8の空間拡張機能を少し触ってみたで、MySQLにおいては、WKT表現では座標系のaxis orderはその座標系の定義によることと、内部表現ではWKTと違い横-縦に固定していることとを述べました。

次の結果を見てみると、後ろ32桁が、16桁の前半後半で入れ替わっていることが分かります。

mysql> SELECT HEX(ST_GeomFromText('POINT(1 2)', 4326));  
+----------------------------------------------------+  
| HEX(ST_GeomFromText('POINT(1 2)', 4326))           |  
+----------------------------------------------------+  
| E610000001010000000000000000000040000000000000F03F |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

mysql> SELECT HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 4326)));  
+----------------------------------------------------+  
| HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 4326))) |  
+----------------------------------------------------+  
| 0101000000000000000000F03F0000000000000040         |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

他の座標参照系ではどうなるかを確認してみたいと思います。また、それが本当に座標系の定義に合致しているかを見てみたいと思います (疑り深い)。

前提

EPSG:4326を指定すると、WKTと内部表現のaxis orderが違ってきます。

POINT(1 2)のWKBは0101000000000000000000F03F0000000000000040です。うち1を示す部分は000000000000F03Fで、2を示す部分は0000000000000040です。

1, 2の順で渡した場合 (かつリトルエンディアンである場合)、末尾が40になっているときはWKTと内部表現のaxis orderが違い、3Fのときは同じ、となります。

ざーっと見ていきます

指定なし (0)

mysql> SELECT HEX(ST_GeomFromText('POINT(1 2)', 0));  
+----------------------------------------------------+  
| HEX(ST_GeomFromText('POINT(1 2)', 0))              |  
+----------------------------------------------------+  
| 000000000101000000000000000000F03F0000000000000040 |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

mysql> SELECT HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 0)));  
+-------------------------------------------------+  
| HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 0))) |  
+-------------------------------------------------+  
| 0101000000000000000000F03F0000000000000040      |  
+-------------------------------------------------+  
1 row in set (0.00 sec)  

WGS84地理座標系 (4326)

mysql> SELECT HEX(ST_GeomFromText('POINT(1 2)', 4326));  
+----------------------------------------------------+  
| HEX(ST_GeomFromText('POINT(1 2)', 4326))           |  
+----------------------------------------------------+  
| E610000001010000000000000000000040000000000000F03F |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

mysql> SELECT HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 4326)));  
+----------------------------------------------------+  
| HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 4326))) |  
+----------------------------------------------------+  
| 0101000000000000000000F03F0000000000000040         |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

Webメルカトル (3857)

mysql> SELECT HEX(ST_GeomFromText('POINT(1 2)', 3857));  
+----------------------------------------------------+  
| HEX(ST_GeomFromText('POINT(1 2)', 3857))           |  
+----------------------------------------------------+  
| 110F00000101000000000000000000F03F0000000000000040 |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

mysql> SELECT HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 3857)));  
+----------------------------------------------------+  
| HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 3857))) |  
+----------------------------------------------------+  
| 0101000000000000000000F03F0000000000000040         |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

まとめ

SRID0 (未定義)のとき、3857 (Webメルカトル)のときは、WKTと内部表現のaxis orderが同じです。
4326はWKTと内部表現のaxis orderが違います。

本当かどうか確認する

http://www.epsg-registry.org/ に、EPSGの空間参照系検索サイトがあります。

左上の"retrieve by code"をクリックして、コード検索を行います。

EPSG:4326は北-東のオーダー

Codeに4326を入れてみます。
検索結果は、次のように2件出ますが、typeがareaのものは今回は不要なので、WGS 84のみ見てください。

座標系の定義がざーっと表示されます。

今回は、axis orderのみを見るので、"Ellipsoidal CS"を開いてみます。

"Axes"の表を見ると、1番目が"Lat"で北方向、2番目が"Lon"で東方向、となっているのが分かります。

以上から、EPSG:4326のaxis orderは縦(南北)-横(東西)の順になることが、これで分かります。

EPSG:3857は東-北のオーダー

同じようにして、EPSG:3857も見てみます。
同じように検索して表示させるのですが、注目するカテゴリ名は、"Cartesian CS"となります。EPSG:4326の時は"Ellipsoidal CS"でしたので、名称が異なりますが、とりあえず気にしないで下さい。

以上から、EPSG:3857のaxis orderは横(東西)-縦(南北)の順になることが、これで分かります。

もうちょっとやってみる

今度は、JGD2000平面直角座標系1系で同じことをやってみましょう。

mysql> SELECT HEX(ST_GeomFromText('POINT(1 2)', 2443));  
+----------------------------------------------------+  
| HEX(ST_GeomFromText('POINT(1 2)', 2443))           |  
+----------------------------------------------------+  
| 8B0900000101000000000000000000F03F0000000000000040 |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

mysql> SELECT HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 2443)));  
+----------------------------------------------------+  
| HEX(ST_AsWKB(ST_GeomFromText('POINT(1 2)', 2443))) |  
+----------------------------------------------------+  
| 0101000000000000000000F03F0000000000000040         |  
+----------------------------------------------------+  
1 row in set (0.00 sec)  

ということで、平面直角座標系はWKTと内部表現のaxis orderが同じ、となってしまいます。

間違ってますやん

EPSGレジストリを見てみます。

ご覧の通り、North-Eastの順となっているので、EPSG:4326と同様、axis orderは縦(南北)-横(東西)の順になります。

ということは、WKTと内部表現のaxis orderが違わなければいけません。

axis orderがこんがらがるのは困ります

axis orderが東-北の順だと右手系、北-東の順だと左手系、にそれぞれあたります。

右・左で整理すると、地理座標系のWKTは左手系です。投影座標系のWKTは右・左が混在して、EPSG:3857は右手系ですが、平面直角座標系は左手系です。

そうすると、地理座標系WKTから内部表現に変換する際に、左手系から右手系に変換する必要があります。これは実装されていますので問題ありません。

EPSG:3857のWKTから内部表現に変換する際には、右手系左手系の変換は不要です。これも問題ありません。

問題は、平面直角座標系のWKTから内部表現に変換する際です。左手系から右手系に変換する必要がありますが、実装されていません。よって、平面直角座標系を思料すると、内部表現がすべて右手系にならない、ということになります。

内部表現を使うと、右手系と左手系で正負逆になる計算をする場合には、大変大きな混乱をまねくことになると思います。

おわりに

MySQLのaxis orderについてもうちょっと見ました。また、座標系の定義を提供してくれるサイトで座標系のaxis orderを確認してみました。

そして、axis orderが座標系の定義と異なるものがあることを示しました。

改善した方がいいと個人的には思います。

本記事のライセンス


この記事は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。