VBAで2点間(緯度経度)の距離を求める方法

当ページのリンクには広告が含まれています。
VBA距離計算
  • URLをコピーしました!

2点間の距離を求める方法は直線距離を求める方法と道路距離を求める方法があります。

実際には公共交通機関(電車など)による移動距離などもっと複雑な条件がありますが、今回は出発地点と到着地点の緯度と経度から、単純な直線距離と道路距離を求める方法についてサンプルプログラムをご紹介します

尚、今回は正確な距離というより参考になる数値を取得することを目的としています。

よって、多少の誤差は気にしないというスタンスです。1mも違わない正確な距離ということですともっと他の方法があるかと思いますので別記事を参考にされてください。

目次

こんな結果になります

以下のような画面を用意しました。出発地点と到着地点の緯度と経度を入力します。

この例では東京新宿を出発地点、到着を名古屋に設定しています。

※住所から緯度経度を算出する方法はまた今度・・・

VBA距離計算

直線距離ボタンをクリックすると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リクエスト分に相当。

とのことです。詳しくは各記事を参考にされてください。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次