球面三角法による2点間の距離計算をGoで実装してみた
はじめに
バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。
地球上の2点間の距離計算ってアプリだと Google Map API を使えば完了!だと思いますが、どう計算してるかって気になりますよね?
今回は球面三角法を利用した地球上の2点間の距離計算を Go で実装します。(調べたらフツーにあるんですが)
球面三角法とは
その名の通り、三角関数を利用して球面上の辺や角の大きさを導出するものです。平面と球面とでの違いは辺の大きさが 球面では中心角によって表されることにあります。
よって、球面三角法を使用して算出した弧の長さ(中心角)と赤道の半径を乗算すると距離が求まります。
球面三角法の証明については、球面三角形の定理を参考にしました!
(“高校生に向けて"とある通り、非常にわかりやすかったです)
球面三角法の余弦定理を利用して実際に距離を算出する方法は球面三角法の余弦定理がわかりやすいです。
実装
実装したソースコードは Github でも確認できます。
package main
import "math"
// Coordinate 緯度経度
type Coordinate struct {
Longitude float64
Latitude float64
}
// EarthRadius 赤道半径
const EarthRadius = 6378140
// DistanceOnTheEarth 地球上の 2 点間の距離を出す(球面三角法)
func DistanceOnTheEarth(from, to Coordinate) float64 {
fromLadLon := from.Longitude * math.Pi / 180
fromLadLat := from.Latitude * math.Pi / 180
toLadLon := to.Longitude * math.Pi / 180
toLadLat := to.Latitude * math.Pi / 180
alpha := math.Sin(fromLadLat)*math.Sin(toLadLat) +
math.Cos(fromLadLat)*math.Cos(toLadLat)*math.Cos(fromLadLon-toLadLon)
arcAlpha := math.Acos(alpha)
return arcAlpha * EarthRadius / 1000
}
動かしてみる
それでは実装した Go の関数を呼び出す簡単なアプリを動かしていきます。
※今回使用するアプリも Github 上の同じディレクトリにあるのでビルドすると使用できます。
アプリの挙動としては、
- 2 点間の緯度経度情報を取得する(取得するために外部 APIを利用します)
- 1 で取得した2点の緯度経度情報を今回実装した距離計算の関数へ渡して算出する
比較するためにこちらのサイトを利用します。
結果
場所 | 比較サイト | 今回のアプリ |
---|---|---|
西東京市 ~ 大阪市都島区 | 383.344422 | 383.3444215569602 |
札幌市厚別区 ~ 沖縄市 | 2,231.318234 | 2231.3182342761 |
※地球上の半径 r は 6378.140km にしています。
。。。同じになってしまいました。。比較とはなんだったんだろう
まあよく捉えると、比較サイトのような便利計算サイトと同等?のものが作れたということでしょうか。
余談
久しぶりに証明を見たり計算を手で追っていく作業をしたので懐かしい気持ちになりました。
普段の業務でそこまで計算式を使わない分、こう自発的に調べて実装するのも楽しいと思いました。