Jump to content

Haversine / Vincenty Calculator


GEOSoft
 Share

Recommended Posts

Just a simple GUI to calculate the Haversine formula.

For those of you that are unfamiliar with the formula, it is used to calculate the direct distance between two surface points of the globe.

I basicly wrote this GUI to test the haversine functions in my distance UDF. That UDF (the part that was completed) is included in the zip file.

Just extract the two files to anyplace and run the Hav_Calc.au3 file.

Many thanks to Sm0ke_N for his help with the StrRegEx().

EDIT: Since it requires Latitud and longitude I guess I should be a nice guy and give you a source for that info.

World Chart There is a link just above the chart to another for USA and Canada.

Edit 2: Changes

The haversine functions now accept negative values which will allow for calculation of distance between different hemispheres. For example when getting the distance between London, UK and Brisbane Australia.

Entering - or s or S to the Latitude inputs will change the coresponding Radio controls. Entering - or e or E to the Longitude inputs will Change the corresponding Radio controls.

Menu has been added but is not yet complete nor is it functional.

Here is the GUI Code

#include "distance.au3"
Opt("GUICoordMode", " 2")

GUICreate("Haversine Calculator", 240, 260)
GUICtrlCreateLabel("Calculate the direct distance between any two points of the globe", 15, 15, 210, 30, 1)
GUISetCoord(15, 55)
$Menu_Cities = GUICtrlCreateMenu("&Cities")
$Menu_Chart = GUICtrlCreateMenu("&Links")
$Menu_Chart1 = GUICtrlCreateMenuItem("infoPlease World", $Menu_Chart)
$Menu_Chart2 = GUICtrlCreateMenuItem("InfoPlease USA and Canada", $Menu_Chart)
$Lbl_Lat1 = GUICtrlCreateLabel("Latitude 1", -1, -1, 60, 20)
$Lbl_Lon1 = GUICtrlCreateLabel("Longitude 1", -1, 5)
$Lbl_Lat2 = GUICtrlCreateLabel("Latitude 2", -1, 20)
$Lbl_Lon2 = GUICtrlCreateLabel("Longitude 2", -1, 5)
GUISetCoord(75, 50)
$in_Lat1 = GUICtrlCreateInput("", -1, -1, 80)
$in_Lon1 = GUICtrlCreateInput("", -1, 5)
$in_Lat2 = GUICtrlCreateInput("", -1, 20)
$in_Lon2 = GUICtrlCreateInput("", -1, 5)
GUISetCoord(160, 50)
GUIStartGroup()
$Rad_N1 = GUICtrlCreateRadio("N", -1, -1, 30)
GUICtrlSetState(-1, 1)
$Rad_S1 = GUICtrlCreateRadio("S", 10, -1)
GUIStartGroup()
$Rad_W1 = GUICtrlCreateRadio("W", -70, 5)
GUICtrlSetState(-1, 81)
$Rad_E1 = GUICtrlCreateRadio("E", 10, -1)
GUIStartGroup()
$Rad_N2 = GUICtrlCreateRadio("N", -70, 20)
GUICtrlSetState(-1, 81)
$Rad_S2 = GUICtrlCreateRadio("S", 10, -1)
GUIStartGroup()
$Rad_W2 = GUICtrlCreateRadio("W", -70, 5)
GUICtrlSetState(-1, 81)
$Rad_E2 = GUICtrlCreateRadio("E", 10, -1)
GUIStartGroup()
GUISetCoord(15, 170)
GUICtrlCreateLabel("Return in...", -1, -1, 70)
GUIStartGroup()
$Rad1 = GUICtrlCreateRadio("Miles", 0, -1, 65)
$Rad2 = GUICtrlCreateRadio("Kilometers", 0, -1)
GUIStartGroup()
GUICtrlSetState($Rad1, 81)
GUISetCoord(80, 200)
$Btn_Go = GUICtrlCreateButton("Calculate", -1, -1, 80, 30, 1)
GUICtrlSetState($Btn_Go, 144)

GUISetState()
While 1
    If GUICtrlRead($in_Lat1) <> "" And GUICtrlRead($in_Lon1) <> "" And GUICtrlRead($in_Lat2) <> "" And GUICtrlRead($in_Lon2) <> "" Then
        If GUICtrlGetState($Btn_Go) > 80 Then GUICtrlSetState($Btn_Go, 80)
    Else
        If GUICtrlGetState($Btn_Go) = 80 Then GUICtrlSetState($Btn_Go, 144)
    EndIf
    If StringInStr(GUICtrlRead($in_Lat1), "S") Or StringInStr(GUICtrlRead($in_Lat1), "-") Then
        If GUICtrlRead($Rad_S1) <> 1 Then GUICtrlSetState($Rad_S1, 1)
    Else
        If GUICtrlRead($Rad_N1) <> 1 Then GUICtrlSetState($Rad_N1, 1)
    EndIf
    If StringInStr(GUICtrlRead($in_Lon1), "E") Or StringInStr(GUICtrlRead($in_Lon1), "-") Then
        If GUICtrlRead($Rad_E1) <> 1 Then GUICtrlSetState($Rad_E1, 1)
    Else
        If GUICtrlRead($Rad_W1) <> 1 Then GUICtrlSetState($Rad_W1, 1)
    EndIf
    If StringInStr(GUICtrlRead($in_Lat2), "S") Or StringInStr(GUICtrlRead($in_Lat2), "-") Then
        If GUICtrlRead($Rad_S2) <> 1 Then GUICtrlSetState($Rad_S2, 1)
    Else
        If GUICtrlRead($Rad_N2) <> 1 Then GUICtrlSetState($Rad_N2, 1)
    EndIf
    If StringInStr(GUICtrlRead($in_Lon2), "E") Or StringInStr(GUICtrlRead($in_Lon2), "-") Then
        If GUICtrlRead($Rad_E2) <> 1 Then GUICtrlSetState($Rad_E2, 1)
    Else
        If GUICtrlRead($Rad_W2) <> 1 Then GUICtrlSetState($Rad_W2, 1)
    EndIf

    $Msg = GUIGetMsg()
    Switch $Msg
        Case - 3
            Exit
        Case $Btn_Go
            $N = 0
            If GUICtrlRead($Rad_S1) = 1 Then $N = 1
            $Lat1 = _Bearing(GUICtrlRead($in_Lat1), $N)
            $N = 0
            If GUICtrlRead($Rad_E1) = 1 Then $N = 1
            $Lon1 = _Bearing(GUICtrlRead($in_Lon1), $N)
            $N = 0
            If GUICtrlRead($Rad_S2) = 1 Then $N = 1
            $Lat2 = _Bearing(GUICtrlRead($in_Lat2), $N)
            $N = 0
            If GUICtrlRead($Rad_E2) = 1 Then $N = 1
            $Lon2 = _Bearing(GUICtrlRead($in_Lon2), $N)
            $Hav = _Haversine($Lat1, $Lon1, $Lat2, $Lon2)
            If GUICtrlRead($Rad1) = 1 Then
                $oTxt = " Miles"
                $Hav = Round($Hav, 2);; Round Miles to 2 decimal places
            Else
                $oTxt = " Kilometers"
                $Hav = _Dist_Cvt_Miles($Hav, 1, 2);; Convert to Km with 2 decimal places
            EndIf
            MsgBox(4096, "Distance", @CRLF & "The calculated distance is " & $Hav & $oTxt)
            GUICtrlSetState($in_Lat1, 256)
        Case Else
            ContinueLoop
    EndSwitch
WEnd

This is what is completed in the UDF

#include-once
#include <math.au3>

Func _Dist_Cvt_Km($Km, $oType = 0, $acc = -1);
;;kilometer = 0.621371192237334 mile $oType = 1
;;kilometer = 0.539956803455724 nautical mile $oType = 2
;;kilometer = 4.97096953789867 furlongs $oType = 3
;;kilometer = 198.838781515947 rods $oType = 4
;;kilometer = 1093.61329833771 yards $oType = 5
;;kilometer = 3280.83989501312 feet $oType = 6
;;
    $oVal = $Km;
    Switch $oType
        Case 1
            $oVal *= .621371192237334
        Case 2
            $oVal *= .539956803455724
        Case 3
            $oVal *= 4.97096953789867
        Case 4
            $oVal *= 198.838781515947
        Case 5
            $oVal *= 1093.61329833771
        Case 6
            $oVal *= 3280.83989501312
    EndSwitch
    If $acc <> -1 Then $oVal = Round($oVal, $acc);
    Return $oVal
EndFunc;==>_Dist_Cvt_Km

Func _Dist_Cvt_Miles($miles, $oType = 0, $acc = -1);
;;mile = 1.609344 kilometer $oType = 1
;;mile = 0.868976241900648 nautical mile $oType = 2
;;mile = 8 furlongs $oType = 3
;;mile = 320 rods $oType = 4
;;mile = 1760 yards $oType = 5
;;mile = 5280 feet $oType = 6
    $oVal = $miles;
    Switch $oType
        Case 1
            $oVal *= 1.609344;
        Case 2
            $oVal *= 0.868976241900648;
        Case 3
            $oVal *= 8
        Case 4
            $oVal *= 320
        Case 5
            $oVal *= 1760
        Case 6
            $oVal *= 5280
    EndSwitch
    If $acc <> -1 Then $oVal = Round($oVal, $acc);
    Return $oVal
EndFunc;==>_Dist_Cvt_Miles

Func _Dist_Cvt_Nmiles($Nmiles, $oType = 0, $acc = -1)
;;nautical mile = 1.15077944802354 mile $oType = 1
;;nautical mile = 1.852 kilometer $oType = 2
;;nautical mile = 9.20623558418834 furlongs $oType = 3
;;nautical mile = 368.249423367534 rods $oType = 4
;;nautical mile = 2025.37182852143 yards $oType = 5
;;nautical mile = 6076.11548556431 feet $oType = 6
    $oVal = $Nmiles;
    Switch $oType
        Case 1
            $oVal *= 1.15077944802354;
        Case 2
            $oVal *= 1.852
        Case 3
            $oVal *= 9.20623558418834
        Case 4
            $oVal *= 368.249423367534
        Case 5
            $oVal *= 2025.37182852143
        Case 6
            $oVal *= 6076.11548556431
    EndSwitch
    If $acc <> -1 Then $oVal = Round($oVal, $acc);
    Return $oVal;
EndFunc;==>_Dist_Cvt_Nmiles

Func _Haversine($Lat1, $Lon1, $Lat2, $Lon2);  <<== Get the distance between two points on the globe.
    $Lat1 = _Radian($Lat1);
    $sinl1 = Sin($Lat1);
    $Lat2 = _Radian($Lat2);
    $Lon1 = _Radian($Lon1);
    $Lon2 = _Radian($Lon2);
    $D = (7926 - (26 * $sinl1)) * ASin(_Min(1, 0.707106781186548 * Sqrt((1 - (Sin($Lat2) * $sinl1) - Cos($Lat1) * Cos($Lat2) * Cos($Lon2 - $Lon1)))));
    Return $D;
EndFunc;==>_Haversine

;;<<=========   Private Functions =========>>

Func _Bearing($in,$neg= 0)
    $oData = 0
    $Bearing = StringRegExp($in, "(?s)(?i)(\d+)", 3)
    Switch UBound($Bearing)
        Case 1
            $oData = $Bearing[0]
        Case 2
            $oData = $Bearing[0] + _ArcPort2Degree($neg, $Bearing[1])
        Case 3
            $oData = $Bearing[0] + _ArcPort2Degree($Neg, $Bearing[1], $Bearing[2])
        Case Else
            Return 0
    EndSwitch
    If $oData >= 360 Then Return 0
    If $neg = 0 Then
       Return $oData
    Else
       Return "-" & $oData
    EndIf
EndFunc;==>_Bearing

Func _ArcPort2Degree($neg = 0, $nMin = 0, $nSec = 0)
;;1 arcminutes = 0.0166666667 degrees
;;1 arcsecond = 0.0166666667 arcminutes
    $nMin += $nSec * .0166666667
    $nMin *= .0166666667
    If $Neg = 0 Then
       Return $nMin
    Else
       Return "-" & $nMin
    EndIf
EndFunc;==>_ArcPort2Degree

Edit: Attachment Removed. Now available for download at

Haversine.zip

This really should be renamed as well. It now has both Vincenty and Haversine formulas with Vincenty being the default.

Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

Updated with new controls on the calculator and changes to the Haversine functions in the UDF that will allow negative numbers to be input.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

Updated with new controls on the calculator and changes to the Haversine functions in the UDF that will allow negative numbers to be input.

Very nice. It's just what I need when I get lost on my bicycle!

I look forward to a version to allow for the fact that the earth is an oblate spheroid. :)

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Very nice. It's just what I need when I get lost on my bicycle!

I look forward to a version to allow for the fact that the earth is an oblate spheroid. :)

Thanks martin;

There is another formula that does what you want but it's way more difficult to use and so far I have not been able to properly write it in AutoIt. Just noticed a bug in the latest version but it's not affecting anything except the radio buttons. The calculation still works. I'll fix the bug but probably not until tommorow. Just a couple of lines to add.

When this is finished I also want it to be a demonstartion of using "sliding" windows and I hope that is ready soon.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

I did this a little while ago

http://www.autoitscript.com/forum/index.ph...showtopic=48161

I have it complete now, just haven't put it online. It will get the elevation and calculate all the angles and such...

I'd be interested in seeing the finished version. How close were your Vincent and Haversine calculations to each other?

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

I'd be interested in seeing the finished version. How close were your Vincent and Haversine calculations to each other?

#446786

I stopped using the haversine function because it was too inaccurate. Mine could be wrong, i mainly pursued the Vincent function.

Link to comment
Share on other sites

#446786

I stopped using the haversine function because it was too inaccurate. Mine could be wrong, i mainly pursued the Vincent function.

That seems to be a common complaint with Haversine. Mine was far more accurate in tests than what I was getting with my version of the Vincenti code. I am sure the problem is in my Vincenti calculation. I'll test it against your version. I am also changing my distance UDF to lenght since I too have added a lot of conversions in there that goes the whole gamut from inches to nautical miles including all of the surveyor lengths like chain and rod. Even threw in furlongs for the race lovers. :)

Next UDFs are area (square, circular, conical &etc.) and speed including a a distance/time calculator to get average speed. That one I hope goes to milisecs.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...