酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

C#で緯度経度の2点間の直線距離を求める

日本測地系から世界測地系(WGS84)に変換する方法については、「C#で位置情報を日本測地系から世界測地系(WGS84)に変換する」をごらんください。

直線距離を求めるのはとても簡単なんですが計算結果にしっくり来ず調べてみたところ、どうやら地球が球であることを考慮しなければいけないようです。そりゃそうか……

このサイトのプログラムを参考にしながら、C#へソースコードを移植しました。Windows Mobile(.NET Frameworkのサブセットの.NET CF)で扱えるクラスとメソッドで対応しているつもりなので他のバージョンでも動くと思います。

** C#

|cs| ///

/// 度単位から等価なラジアン単位に変換します。 /// /// 度単位 /// static double deg2rad(double deg) { return (deg / 180) * Math.PI; }

///

/// 2点間の位置情報から距離を求める /// /// /// /// public static int CalculateDistance(Positions posA, Positions posB) { // 2点の緯度の平均 double latAvg = deg2rad(posA.Latitude + *1; // 2点の緯度差 double latDifference = deg2rad(posA.Latitude - posB.Latitude); // 2点の経度差 double lonDifference = deg2rad(posA.Longitude - posB.Longitude);

  double curRadiusTemp = 1 - 0.00669438 * Math.Pow(Math.Sin(latAvg), 2);
  // 子午線曲率半径
double meridianCurvatureRadius = 6335439.327 / Math.Sqrt(Math.Pow(curRadiusTemp, 3));
  // 卯酉線曲率半径
  double primeVerticalCircleCurvatureRadius = 6378137 / Math.Sqrt(curRadiusTemp);

  // 2点間の距離
  double distance = Math.Pow(meridianCurvatureRadius * latDifference, 2) 
      + Math.Pow(primeVerticalCircleCurvatureRadius
      * Math.Cos(latAvg) * lonDifference, 2);
  distance = Math.Sqrt(distance);

  return (int)Math.Round(distance);

} ||<

**VB.NET

|vb| '''

''' 度単位から等価なラジアン単位に変換します。 ''' ''' 度単位 ''' Private Shared Function deg2rad(deg As Double) As Double Return (deg / 180) * Math.PI End Function

'''

''' 2点間の位置情報から距離を求める ''' ''' ''' ''' Public Shared Function CalculateDistance(posA As Positions, posB As Positions) As Integer ' 2点の緯度の平均 Dim latAvg As Double = deg2rad(posA.Latitude + *2 ' 2点の緯度差 Dim latDifference As Double = deg2rad(posA.Latitude - posB.Latitude) ' 2点の経度差 Dim lonDifference As Double = deg2rad(posA.Longitude - posB.Longitude)

Dim curRadiusTemp As Double = 1 - 0.00669438 * Math.Pow(Math.Sin(latAvg), 2)
' 子午線曲率半径
Dim meridianCurvatureRadius As Double = 6335439.327 / Math.Sqrt(Math.Pow(curRadiusTemp, 3))
' 卯酉線曲率半径
Dim primeVerticalCircleCurvatureRadius As Double = 6378137 / Math.Sqrt(curRadiusTemp)

' 2点間の距離
Dim distance As Double = Math.Pow(meridianCurvatureRadius * latDifference, 2) + Math.Pow(primeVerticalCircleCurvatureRadius * Math.Cos(latAvg) * lonDifference, 2)
distance = Math.Sqrt(distance)

Return CInt(Math.Round(distance))

End Function ||<

** 追記(2016/2/17)

.NET Framework 4.0からGeoCoordinateオブジェクト同士の差を求めることができるようになっているようです。

|cs| var distance = new GeoCoordinate(lat1, lon1) .GetDistanceTo(new GeoCoordinate(lat2, lon2)); ||<

さすがに.NET Compact Frameworkでの対応をする方はもういないと思いますので、特別理由がなければこちらのクラスを使った方が良さそうです。

.NET Frameworkで2点間(緯度経度)の距離を求める - プログラムの事とか」にて詳しく書かれていますのでこちらをお読みください。

  • 関連記事

Windows Mobile(.NET Compact Framework)を使ってアプリ開発する際に逆引きとしてお使いください。

*1:posB.Latitude - posA.Latitude) / 2

*2:posB.Latitude - posA.Latitude) / 2