【No.002】緯度経度から距離を算出する方法:球面三角法を使った正確な計算方法とVBAでの実装例

はじめに

緯度経度が何者かが分かったら、今度は距離を算出してみます。
2点の座標(x=経度、y=緯度)を使って距離計算するとき、最初に思いつくのはピタゴラス(三平方)の定理です。しかし残念ながらこれでは距離計算できません。なぜなら地球は球体であり、完全な平面ではないためです。

図1. ピタゴラスの定理で緯度計算はNG

イメージが沸かない方向けに、緯度と経度の性質についてもう少し解説します。
例えば、下の図のA,B,Cはいずれも東経120°~150°を結んだ経度30°分の線です。しかし長さを見てみるとどうでしょうか。赤道付近から北極に向かうにつれて明らかに長さが短くなっています。つまり球体であるがゆえに「緯度経度1°につき●●メートル」と定義することができないために単純な計算では算出できないのです。

図2. 経度30°分の長さ

★関連リンク
緯度経度の10進⇔60進変換したい場合はこちら
2点間の緯度経度で方位を算出したい場合はこちら
緯度経度からMesh変換したい場合はこちら

計算方法

ではどうやったら計算ができるのでしょうか。詳細は省きますが、一般には球面三角法と呼ばれるものを用います。三角関数を組み合わせるだけなのでプログラムでも実装しやすいです。試しにVBAで書いてみるとこんな感じでしょうか。東京(北緯: 35.6581, 東経: 139.7414)とロンドン(北緯: 51.5072, 東経: -0.1276)で表現しています。

Dim x1, x2, y1, y2 As Double
x1 = 139.7414
y1 = 35.6581
x2 = -0.1276
y2 = 51.5072
Dist = r * arcCos(Sin(y1 * Application.WorksheetFunction.Pi / 180) * Sin(y2 * Application.WorksheetFunction.Pi / 180) + Cos(y1 * Application.WorksheetFunction.Pi / 180) * Cos(y2 * Application.WorksheetFunction.Pi / 180) * Cos((x2 - x1) * Application.WorksheetFunction.Pi / 180))

計算機も作ってみました。



地図上で距離を計測してしたい場合はこちらからマップにアクセスして下さい。1回目にクリックした場所を記憶して、2回目にクリックした場所に対して距離を算出します。

Appendix

上記の計算機のソースコードです。JavaScriptというコードで記載されています。

<label>点1の緯度(10進):</label>
<input type="text" id="lat1" value="36.1234">
<label>点1の経度(10進):</label>
<input type="text" id="lon1" value="136.2468">
<br>
<label>点2の緯度(10進):</label>
<input type="text" id="lat2" value="36.6789">
<label>点2の経度(10進):</label>
<input type="text" id="lon2" value="136.1357">
<br>
<button type="button" onclick="calcDistance()">距離を計算する</button>
<div id="result"></div>

<script>
function calcDistance() {
  var lat1 = parseFloat(document.getElementById("lat1").value);
  var lon1 = parseFloat(document.getElementById("lon1").value);
  var lat2 = parseFloat(document.getElementById("lat2").value);
  var lon2 = parseFloat(document.getElementById("lon2").value);

  var R = 6371; // km
  var dLat = (lat2-lat1) * Math.PI / 180;
  var dLon = (lon2-lon1) * Math.PI / 180;
  var lat1 = lat1 * Math.PI / 180;
  var lat2 = lat2 * Math.PI / 180;

  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var distance = R * c;

  document.getElementById("result").innerHTML = "距離は " + distance.toFixed(2) + " km です。";
}
</script>

また大量の緯度経度を変換したい場合はExcelなどをうまく活用すると良いです。簡単なツールを準備しましたので試しにご活用ください。計算式がやや複雑とはいえ、三角関数を用いた単純な算術計算のため数万レコードであっても一瞬で計算してくれます。

★この記事に関連する自作のWebアプリ/Excelアプリを紹介します。

緯度経度(2点間の距離算出)
緯度経度(2点間の距離算出_地図で表示)
緯度経度(2点間の距離・方位算出)

コメント