30
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

qnoteAdvent Calendar 2017

Day 17

2点の緯度経度の距離を計算する

Last updated at Posted at 2017-12-17

#経緯
専門学校時代にマップを扱うことがありその時に作った関数をこの機会に残しておこうと思い書きました。

#解説
山だらけにて解説されているヒュベニの公式というものを使いました。式は

\sqrt{(d_yM)^2+(d_zN \cos µ_y)^2}

です。

わかりやすく言葉に直すと

\sqrt{(緯度の差 × 子午線曲線半径)^2 + (経度の差 × 卯酉線曲率半径 × cos緯度の平均値)^2}

何をしてるんだろうって私も思いました。
よく見ると

\sqrt{(c−a)^2+(d−b)^2}

という二点間の距離を求める公式になります。
そこに地球を楕円と仮定した場合の誤差を補正した式らしいです。

#コード

HubenyDistance.java
public class HubenyDistance {

    //世界観測値系
    public static final double GRS80_A = 6378137.000;//長半径 a(m)
    public static final double GRS80_E2 = 0.00669438002301188;//第一遠心率  eの2乗

    public static double deg2rad(double deg){
        return deg * Math.PI / 180.0;
    }

    public static double calcDistance(double lat1, double lng1, double lat2, double lng2){
        double my = deg2rad((lat1 + lat2) / 2.0); //緯度の平均値
        double dy = deg2rad(lat1 - lat2); //緯度の差
        double dx = deg2rad(lng1 - lng2); //経度の差

        //卯酉線曲率半径を求める(東と西を結ぶ線の半径)
        double sinMy = Math.sin(my);
        double w = Math.sqrt(1.0 - GRS80_E2 * sinMy * sinMy);
        double n = GRS80_A / w;

        //子午線曲線半径を求める(北と南を結ぶ線の半径)
        double mnum = GRS80_A * (1 - GRS80_E2);
        double m = mnum / (w * w * w);

        //ヒュベニの公式
        double dym = dy * m;
        double dxncos = dx * n * Math.cos(my);
        return Math.sqrt(dym * dym + dxncos * dxncos);
    }
}
30
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?