Search code examples
vbscriptcoordinate-systemscoordinate-transformation

Convert Latitude/Longitude to decimal degrees


i need to convert a large txt file with latitudes, and a large txt file with longitudes into decimal degrees.

The data i have is in the current format:

7d44'31.495"W for longitude

and

41d3'40.313"N for latitude

i need to convert both of this files to decimal degrees (using a script preferably). How can i do this?


Solution

  • Knowing nothing about *itudes, I can only give you a general idea about how to solve your problem:

    Use a RegExp to cut the numbers from your data and feed them in a trusted formula

    To give you some confidence in my proposal, I show you, how I would tackle the two sub-problems of your task.

    (1) Apply a RegExp on an input string and calculate.

    Based on this section

    Conversion from DMS to Decimal Degree

    Given a DMS (Degrees, Minutes, Seconds) coordinate such as W87°43'41", convert it to a number of decimal degrees using the following method:

    Calculate the total number of seconds:
    43'41" = (43*60 + 41) = 2621 seconds.
    The fractional part is total number of seconds divided by 3600:
    2621 / 3600 = ~0.728056
    Add fractional degrees to whole degrees to produce the final result:
    87 + 0.728056 = 87.728056
    Since it is a West longitude coordinate, negate the result.
    The final result is -87.728056.
    

    found here

    Code:

      Dim oFmt   : Set oFmt = New cFormat
      Dim oRE    : Set oRE  = New RegExp
      '                 0    1     2     3
      oRE.Pattern = "^([W])(\d+)°(\d+)'(\d+)""$"
      Dim aTests : aTests   = Array( _
          Array("W87°43'41""", -87.728056) _
      )
      Dim aTest
      For Each aTest In aTests
          Dim sInp : sInp     = aTest(0)
          Dim nExp : nExp     = aTest(1)
          Dim oMTS : Set oMTS = oRE.Execute(sInp)
          Dim sMsg
          If 1 <> oMTS.Count Then
             sMsg = oFmt.formatTwo("|{0}| didn't match /{1}/", sInp, oRE.Pattern)
          Else
             Dim sLoLa    : sLoLa    =      oMTS(0).SubMatches(0)
             Dim nDegrees : nDegrees = CDbl(oMTS(0).SubMatches(1))
             Dim nMinutes : nMinutes = CDbl(oMTS(0).SubMatches(2))
             Dim nSeconds : nSeconds = CDbl(oMTS(0).SubMatches(3))
             Dim nRes
    
    '        Calculate the total number of seconds:
    '        43'41" = (43*60 + 41) = 2621 seconds.
             nRes = nMinutes * 60 + nSeconds
    '        WScript.Echo "***", nRes
    
    '        The fractional part is total number of seconds divided by 3600:
    '        2621 / 3600 = ~0.728056
             nRes = nRes / 3600
    '        WScript.Echo "***", nRes
    
    '        Add fractional degrees to whole degrees to produce the final result:
    '        87 + 0.728056 = 87.728056
             nRes = nDegrees + nRes
    '        WScript.Echo "***", nRes
    
    '        Since it is a West longitude coordinate, negate the result.
    '        The final result is -87.728056.
             Select Case sLoLa
               Case "W"
                 nRes = -nRes
             End Select
    
             sMsg = oFmt.formatArray(_
                  "{0,-12}: R: {1,12:N6} E: {2,12:N6} D: {3,12:N6}" _
                , Array(sInp, nRes, nExp, nRes - nExp) _
             )
          End If
          WScript.Echo sMsg
      Next
    

    Output:

    Step00 - conversion a la wikipedia
    ================================================================
    W87°43'41"  : R:   -87,728056 E:   -87,728056 D:     0,000000
    ================================================================
    xpl.vbs: Erfolgreich beendet. (0) [0.08594 secs]
    

    Starting from an input sample, I derive (a first attempt at) the Regexp pattern

                    "   W   87  ° 43  ' 41  "" "
      '                 0    1     2     3
      oRE.Pattern = "^([W])(\d+)°(\d+)'(\d+)""$"
    

    For your data, something like this

                    "   7  d 44  ' 31.495   ""  W    "
                    "  41  d  3  ' 40.313   ""  N    "
      '                 0     1        2        3
      oRE.Pattern = "^(\d+)d(\d+)'(\d+\.\d+)""([WN])$"
    

    may be appropriate.

    To get the parts captured by the RegExps group ()s, I access and convert the match's submatches

     Dim sLoLa    : sLoLa    =      oMTS(0).SubMatches(0)
     Dim nDegrees : nDegrees = CDbl(oMTS(0).SubMatches(1))
     Dim nMinutes : nMinutes = CDbl(oMTS(0).SubMatches(2))
     Dim nSeconds : nSeconds = CDbl(oMTS(0).SubMatches(3))
    

    Then it's just computing according to the algorithm/formulas stolen from Wikipedia (see the code/comments).

    (2) Get the data from your files

    If the files are not to big, you can .ReadAll() them into memory and apply the RegExp in multiline mode:

      Dim oFmt : Set oFmt = New cFormat
    
      Dim oRE  : Set oRE  = New RegExp
      oRE.Global    = True
      oRE.Multiline = True
      '                 0     1        2        3
      oRE.Pattern = "^(\d+)d(\d+)'(\d+\.\d+)""([WN])$"
    
      Dim sAll : sAll = goFS.OpenTextFile("..\data\f00.txt").ReadAll()
      WScript.Echo sAll
    
      WScript.Echo oFmt.formatArray( _
          "|{0,-5}|{1,-11}|{2,-11}|{3,-15}|" _
        , Array("LoLa", "Degrees", "Minutes", "Seconds") _
      )
    
      Dim oMTS : Set oMTS = oRE.Execute(sAll)
      Dim oMT
      For Each oMT In oMTS
          Dim sLoLa    : sLoLa    =      oMT.SubMatches(3)
          Dim nDegrees : nDegrees = CDbl(oMT.SubMatches(0))
          Dim nMinutes : nMinutes = CDbl(oMT.SubMatches(1))
          Dim nSeconds : nSeconds = CDbl(oMT.SubMatches(2))
    
          WScript.Echo oFmt.formatArray( _
              "|{0,-5}|{1,11:N2}|{2,11:N2}|{3,15:N6}|" _
            , Array(sLoLa, nDegrees, nMinutes, nSeconds) _
          )
      Next
    

    output:

    ======================================================
    7d44'31.495"W
    41d3'40.313"N
    
    
    |LoLa |Degrees    |Minutes    |Seconds        |
    |W    |       7,00|      44,00|      31,495000|
    |N    |      41,00|       3,00|      40,313000|
    ======================================================
    

    Get the cFormat class from here