先日リリースしたAndroidアプリ「地球測定」(公開終了しました)は、地球を楕円体として2点間の距離と方位角を求めることができます。この距離と方位角は、球体については容易に求められますが、楕円体の場合は容易ではなく、「測地学の逆問題(Inverse problem)」と言われ、昔から議論されています。
弊社が運営しているマップリドットネットでは、Webページ上で簡単にこの距離と方位角が求められますが、この時はオーストラリアの測量マニュアルにアルゴリズムがあったので、それを元にプログラムを作成しました。5,6年前になりますが、相当苦労しました。そして、米国測地局(NGS)と国土地理院の計算サイトで検証しました。
距離を正確に計算できる多言語対応ライブラリ
今回は、もう自分では作らずに、素晴らしいライブラリがあるので、こちらを使わせてもらいました。それが、GeographicLibです。非常に便利です。ライセンスもMITなので、扱いやすいです。座標変換、重力、地磁気の計算も可能です。言語もC、FORTRAN、Java、JavaScript、Python、C#のライブラリが公開されています。詳しくは、以下のサイトをご覧ください。
http://geographiclib.sourceforge.net
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でも、距離は簡単に求めることができますが、地球を球体とみなした値です。楕円体として、より精度高く計算する場合には、以上のようなライブラリの利用が必要となります。