2点間の距離を求める方法は直線距離を求める方法と道路距離を求める方法があります。
実際には公共交通機関(電車など)による移動距離などもっと複雑な条件がありますが、今回は出発地点と到着地点の緯度と経度から、単純な直線距離と道路距離を求める方法についてサンプルプログラムをご紹介します。
尚、今回は正確な距離というより参考になる数値を取得することを目的としています。
よって、多少の誤差は気にしないというスタンスです。1mも違わない正確な距離ということですともっと他の方法があるかと思いますので別記事を参考にされてください。
こんな結果になります
以下のような画面を用意しました。出発地点と到着地点の緯度と経度を入力します。
この例では東京新宿を出発地点、到着を名古屋に設定しています。
※住所から緯度経度を算出する方法はまた今度・・・

直線距離ボタンをクリックすると257.8kmと表示されます。

道路距離ボタンをクリックすると363kmと表示されます。ついでに所要時間も表示されています。(有料道路を通らないオプションを付けています)

2点間の直線距離を求める方法
2点間の直線距離を求める計算式としては以下のような算出方法があるそうです。
大変申し訳ありませんが、この辺りの詳しいことは私には分かりませんので、Qiitaのサイトが参考になると思います。
- ヒュベニの公式
- 球面三角法
- 測地線航海算法
Option Compare Database
Option Explicit
Const GRS80_A = 6378137#
Const GRS80_E2 = 6.69438002301188E-03
Const GRS80_MNUM = 6335439.32708317
Const PAI = 3.14159265358979
Function deg2rad(deg As Double) As Double
deg2rad = deg * PAI / 180#
End Function
'***********************************************************************
' [説 明] 2地点間の直線距離を求める関数
' [引 数] lat1:地点1緯度 lng1:地点1経度 lat2:地点2緯度 lng2:地点2経度
' [戻り値] なし
'***********************************************************************
Public Sub calcHubeny(lat1 As Double, lng1 As Double, lat2 As Double, lng2 As Double)
Dim my As Double
Dim dy As Double
Dim dx As Double
Dim sin As Double
Dim w As Double
Dim m As Double
Dim n As Double
Dim dym As Double
Dim dxncos As Double
my = deg2rad((lat1 + lat2) / 2#)
dy = deg2rad(lat1 - lat2)
dx = deg2rad(lng1 - lng2)
sin = Math.sin(my)
w = Math.Sqr(1# - GRS80_E2 * sin * sin)
m = GRS80_MNUM / (w * w * w)
n = GRS80_A / w
dym = dy * m
dxncos = dx * n * Math.Cos(my)
'メートルで取得するので、キロメートルに変換し小数第一位までにする
MsgBox "距離:" & Round(Math.Sqr(dym * dym + dxncos * dxncos) / 1000, 1) & "km", vbInformation, "直線距離は・・・"
End Sub
参考にさせていただいたサイトはこちらです。ヒュベニの公式を使った算出方法です。
この関数を「道路距離」ボタンのクリック時イベントでCallします。引数は出発地点と到着地点の緯度・経度です。戻り値なし。
道路距離を求める方法
こちらのページを参考にさせていただきました。
'***********************************************************************
' [説 明] 2点間の道路距離を求める
' [引 数] lat1:地点1緯度 lng1:地点1経度 lat2:地点2緯度 lng2:地点2経度
' [戻り値] getCoordinate(0):緯度 getCoordinate(1):経度
'***********************************************************************
Public Sub getGoogledistance(lat1 As Double, lng1 As Double, lat2 As Double, lng2 As Double)
Dim HTTP As Object
Set HTTP = CreateObject("MSXML2.XMLHTTP")
HTTP.Open "GET", "https://maps.googleapis.com/maps/api/distancematrix/xml?" & _
"origins=" & lat1 & "," & lng1 & _
"&destinations=" & lat2 & "," & lng2 & _
"&avoid=highways", False
HTTP.send
Do While HTTP.ReadyState <> 4
DoEvents
Loop
MsgBox "時間:" & _
HTTP.responseXML.DocumentElement.LastChild.LastChild.ChildNodes(1).LastChild.nodeTypedValue & vbLf & _
"距離:" & _
HTTP.responseXML.DocumentElement.LastChild.LastChild.ChildNodes(2).LastChild.nodeTypedValue, vbInformation, "道路距離は・・・"
Set HTTP = Nothing
End Sub
GoogleのAPI関数を使用する方法です。
今回は有料道路を通らない条件で距離を算出しています。
有料道路を通らない条件は16行目の“&avoid=highways”, Falseで設定しています。
こちらをTrueにすることで有料道路を通る条件で計算してくれます。
この関数を「直線距離」ボタンのクリック時イベントでCallします。引数は出発地点と到着地点の緯度・経度です。戻り値なし。
そもそも、どんな時に使う?
今回必要に迫られて実装した訳ですが、要件としては
ある拠点で実施されるイベント(お仕事依頼)に多数の応募があった場合、拠点とご自宅の距離から優先順位をつけて採用したい
というものでした。
このニーズは繰り返し発生するニーズだったため、関数化して対応することにしました。
追加情報
2018/09/11より、GoogleMapの仕様変更により上記のコードがエラーになるようになりました。
これは、GoogleがMapAPIの提供について条件付有料化を実施したことに起因します。
今後はAPIキーの発行が必須となりますので、参考になる記事をご紹介します。
お使いのGoogleアカウントにおいてAPIキーを発行してからご利用ください。
簡潔にいうと、無料枠は月間200ドルまで。超過する分については主にクレジット決済される。(クレジットカードの登録がない場合はエラー)
月間200ドルとは、約28000リクエスト分に相当。
とのことです。詳しくは各記事を参考にされてください。
コメント