2024年8月の FOSS4G Tokai、MySQLの山﨑さんの発表後に「MySQLでは180度線を跨ぐ場合の距離など、正しく計算してくれるのか」という質問がありました。確か以前、(当然)それは大丈夫だったのを確認したよなぁと朧気に思いつつもその場でフォローはできなかったので、ご講演終了後に速攻で確認してみました。
結論
「ちゃんと、180度をまたいでも、最短の距離で計算してくれる(ぐるりと0度のほうを回って、つまり例えば 東経175度から0度を経由して西経175度までの距離を計算するわけではない)」
実例
赤道上での、東経165度から175度の距離、および東経175度から西経175度までの距離を求める。どちらも経度10度ぶんの距離(1000kmちょっと)になるはずである。
mysql> SELECT ST_Distance( -> ST_GeomFromText('POINT(0 165)',4326) -> ,ST_GeomFromText('POINT(0 175)',4326) -> ) d; +-------------------+ | d | +-------------------+ | 1113194.907932733 | +-------------------+
mysql> SELECT ST_Distance( -> ST_GeomFromText('POINT(0 175)',4326) -> ,ST_GeomFromText('POINT(0 -175)',4326) -> ) d; +-------------------+ | d | +-------------------+ | 1113194.907932774 | +-------------------+
期待通り「ほぼ一致」した。
少しの誤差が気になる
どちらも赤道上での10度ぶんという、回転楕円体上では同じ距離となるはずなのに、やや異なる数値となったのが気になる。その差は、0.000000041メートル。つまり0.000041ミリ。1000kmぶんの距離を測って、0.000041ミリ。実務上は無視しても良い程度ですが、本来一致するはずなのに差が出るのが気になりますね。
ラジアンに変換する際の誤差ではないか
MySQLでは(というか Boost::Geometryライブラリでは)、内部でラジアンで計算しているものと思われます。
ということで、「同じ経度10度でも、180度線をまたぐ場合の計算で差が発生するのではないか」を仮説と立てて、確認してみたいと思います。
まず値の準備。Piの値を設定し、経度 165, 175, -175 の3つをラジアン変換します。
irb(main):001:0> pi=3.1415926535897932384626433 irb(main):002:0> rad165=165*(pi/180) irb(main):003:0> rad175=175*(pi/180) irb(main):004:0> rad_175=-175*(pi/180)) irb(main):014:0> rad165 => 2.8797932657906435 irb(main):015:0> rad175 => 3.0543261909900767 irb(main):016:0> rad_175 => -3.0543261909900767
ラジアンどうしの引き算として、東経177度と179度の差と、東経179度と西経179度の差(どちらも度で表すと2度の差)を求めます。
165度と175度は単純に引き算すれば良く、175度と-175度は、これらの差(非常に大きい)を一周の角である2*piから減ずれば良いです。
irb(main):009:0> (rad175-rad165).abs => 0.1745329251994332 irb(main):010:0> (2*pi-(rad175-rad_175)).abs => 0.17453292519943275
0.00000000000000045ラジアン程度の差が発生しました。
これは弧の長さにすると、半径rを用いて rθで求められるので、
>||irb(main):011:0> r=6378137
irb(main):009:0> (rad175-rad165).abs
=> 0.1745329251994332
irb(main):010:0> (2*pi-(rad175-rad_175)).abs
=> 0.17453292519943275
|
0.0000000028メートルほどの差が発生しました。これ、piの値を結構詳細に指定したので先ほどよりも小さい値となりましたが、試しに pi=3.141592653 で同様の計算をしたところ、差は0.0000000062メートルとなりました。
180度線を跨ぐ計算で発生する差は、これかなー。
確証はないので、みなさんの続報に期待したいと思います。