先日リリースしたAndroidアプリ「地球測定」(公開終了しました)は、地球を楕円体として2点間の距離と方位角を求めることができます。この距離と方位角は、球体については容易に求められますが、楕円体の場合は容易ではなく、「測地学の逆問題(Inverse problem)」と言われ、昔から議論されています。

弊社が運営しているマップリドットネットでは、Webページ上で簡単にこの距離と方位角が求められますが、この時はオーストラリアの測量マニュアルにアルゴリズムがあったので、それを元にプログラムを作成しました。5,6年前になりますが、相当苦労しました。そして、米国測地局(NGS)と国土地理院の計算サイトで検証しました。

距離を正確に計算できる多言語対応ライブラリ

今回は、もう自分では作らずに、素晴らしいライブラリがあるので、こちらを使わせてもらいました。それが、GeographicLibです。非常に便利です。ライセンスもMITなので、扱いやすいです。座標変換、重力、地磁気の計算も可能です。言語もC、FORTRAN、Java、JavaScript、Python、C#のライブラリが公開されています。詳しくは、以下のサイトをご覧ください。

2点間の最短距離は、以下のように求めることができます(Javaの場合)。ここでは、日本の測量基準で用いられている準拠楕円体(ITRF座標系GRS80楕円体)を使用しています。


import net.sf.geographiclib.*;

public class DistanceModel {

    // 楕円体定数(GRS80)
    private static final double A_ELLIPSE = 6378137.0;
    private static final double F_ELLIPSE = 1.0 / 298.257222101;

    // キョリ(m)
    private double mDistance;
    // 方位角(degree)
    private double mAzimuth1, mAzimuth2;

    public DistanceModel(double distance, double azimuth1, double azimuth2) {
        mDistance = distance;
        mAzimuth1 = azimuth1;
        mAzimuth2 = azimuth2;
    }

    public double getDistance() {
        return mDistance;
    }

    public double getAzimuth1() {
        return mAzimuth1;
    }

    public double getAzimuth2() {
        return mAzimuth2;
    }

    public static DistanceModel newInstance(double lat1, 
                                            double lon1, 
                                            double lat2, 
                                            double lon2) {

        Geodesic geodesic = new Geodesic(A_ELLIPSE, F_ELLIPSE);
        GeodesicData data = geodesic.Inverse(lat1, lon1, lat2, lon2, 
                                     GeodesicMask.DISTANCE | GeodesicMask.AZIMUTH);
        return new DistanceModel(data.s12, data.azi1, data.azi2);
    }
}

この問題の難しさが、多少なりともわかるため、作者のCharles Karneyさんには、大変感謝いたします。

Google Maps APIでも、距離は簡単に求めることができますが、地球を球体とみなした値です。楕円体として、より精度高く計算する場合には、以上のようなライブラリの利用が必要となります。