logitech334
asked on
Visual Basic .NET 2015 calculating new lat/lon based on bearing and distance
Hello guys,
I have wrote a vb.net code
Which calculates the point on specified distance in km, however, I am getting very inaccurate result (~15-20km difference). The result for values: heading 360 (0-north), 111.2km and lon 61.0000 lat -30.0000 (61N30W) i am expecting is 62.0000 and -30.0000) as the distance between longs is around 111.2km. I guess it is some accuracy problem in vb.net math calculations. Would you give me any advice how to make this formula working in vb.net (it was supposed to give me accurate point to meters - not kilometers).
The output result of above formula currently is: 62,15471 (Long) and -29.99496.
Thanks in advance.
I have wrote a vb.net code
Const EarthRadius As Double = 6371
Public Shared Function FindPointAtDistanceFrom(lat1 As Decimal, lon1 As Decimal, bearing As Double, range As Double) As PointF
Dim latA As Decimal = deg2rad(lat1)
Dim lonA As Decimal = deg2rad(lon1)
Dim angularDistance As Decimal = range / EarthRadius
Dim trueCourse As Decimal = deg2rad(bearing - 270)
Dim lat As Decimal = Math.Asin(Math.Sin(latA) * Math.Cos(angularDistance) + Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse))
Dim dlon As Decimal = lonA + Math.Atan2(Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA), Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat))
Dim lon As Decimal = ((lonA - dlon + Math.PI) Mod (Math.PI * 3)) - Math.PI
' lon1 + ATAN2(COS(d/R)-SIN(lat1)*SIN(lat2), SIN(brng)*SIN(d/R)*COS(lat1))
'Dim lon As Double = lonA + Math.Atan2(Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA), Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat))
Dim prt As PointF = New PointF(rad2deg(lat), rad2deg(dlon))
Return prt
End Function
Which calculates the point on specified distance in km, however, I am getting very inaccurate result (~15-20km difference). The result for values: heading 360 (0-north), 111.2km and lon 61.0000 lat -30.0000 (61N30W) i am expecting is 62.0000 and -30.0000) as the distance between longs is around 111.2km. I guess it is some accuracy problem in vb.net math calculations. Would you give me any advice how to make this formula working in vb.net (it was supposed to give me accurate point to meters - not kilometers).
The output result of above formula currently is: 62,15471 (Long) and -29.99496.
Thanks in advance.
ASKER
Hello, thank you for your reply. "Decimal" thing was last change I did to this code to chceck if that works better. I get exactly the same wrong coords on doubles.
I was comparing your code to the discussion on Great Circle type calculations at http://www.movable-type.co.uk/scripts/latlong.html I tried your sample problem on their calculator, and it returned the exact answer expected: 62 degrees longitude, -30 degrees latitude.
Your code matched the formulas on Movable Type. I assume that your VB.Net code uses the same convention for atan2 that Movable Type did. If you note the footnote 4 just above the middle of the page, the question is whether atan2 uses y as the first paramter and x as the second--or the converse.
Your code matched the formulas on Movable Type. I assume that your VB.Net code uses the same convention for atan2 that Movable Type did. If you note the footnote 4 just above the middle of the page, the question is whether atan2 uses y as the first paramter and x as the second--or the converse.
I'm not a real expert at this, but I do see a problem here:
Now that may be a simple typo but it could explain the error. Either reverse the lat/lon arguments or the bearing is calculated wrong (where did you get that -270 from?). In fact, if I enter bearing 90 (or 270) in your function it returns a result that matches your expectation (moving 1 degree of latitude) but you'd still need to double check which is which with regard to lat/lon going in and coming out of your function.
lon 61.0000 lat -30.0000 (61N30W)As you can see here for example, the latitude should be N/S and the longitude E/W.
Now that may be a simple typo but it could explain the error. Either reverse the lat/lon arguments or the bearing is calculated wrong (where did you get that -270 from?). In fact, if I enter bearing 90 (or 270) in your function it returns a result that matches your expectation (moving 1 degree of latitude) but you'd still need to double check which is which with regard to lat/lon going in and coming out of your function.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I've tried couple of your suggestions however I can't still get it working. I've managed it to work for -30 60 point but when I try to calculate another it returns value (of latitude) 2x smaller (on distance ~300 nautical miles) than it should be. Moreover, "bearing" by definition is not a bearing (VB .NET issues?) - thats why i put -270 there to rotate it so I could get points on the correct radial from known lat/lon. I am having exactly the same issues with the last formula from here: https://www.experts-exchange.com/questions/22555684/VB6-Lat-Lon-given-heading-and-distance.html I do not know if this will help if I say that I tried even Vincenty's formulas but they were affected by the same issues. I now doubt if this is formula's itself related issue. Do you have further ideas?
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
It is worth noting that on almost any Great Circle route, the instantaneous bearing will be different from what it was at the beginning of the trip. The only exceptions are those routes that head strictly north/south or east/west. The function (and Movable Type webpage) are looking for the initial bearing. This is why you can't connect two points on a paper map with a straight line and call that your bearing. You must draw the Great Circle route and measure the initial bearing.
ASKER
Thank you, above thing should be now solved - there was some problems with type PointF x/y usage so function missed lat with lons and round around. Before I set status to Solved I'd like to ask you for the same related thing - I have another function:
This function should return bearing to the point. I compare results from lat -15 and long 55.5 to -10 and long 57 (W/N) - the bearing should be ~60 (final ~63) as per http://www.movable-type.co.uk/scripts/latlong.html however my application returns now ~73 which is very inaccurate for me.
Public Shared Function CalcAzimuth(ByVal lat1 As Double, ByVal long1 As Double, ByVal lat2 As Double, ByVal long2 As Double) As Double
Dim dlon As Double = Rad(long2) - Rad(long1)
lat1 = Rad(lat1)
long1 = Rad(long1)
lat2 = Rad(lat2)
long2 = Rad(long2)
Dim x As Decimal = Math.Sin(dlon) * Math.Cos(lat2)
Dim y As Decimal = Math.Cos(lat1) * Math.Sin(lat2) - Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(dlon)
Dim brng As Double = Math.Atan2(y, x)
brng = Deg(brng)
brng = Math.Abs((brng + 360) Mod 360)
Main.Label1.Text = brng.ToString
Return brng
End Function
This function should return bearing to the point. I compare results from lat -15 and long 55.5 to -10 and long 57 (W/N) - the bearing should be ~60 (final ~63) as per http://www.movable-type.co.uk/scripts/latlong.html however my application returns now ~73 which is very inaccurate for me.
How odd, when I run your function with arguments (-15, 55, -10, 55) I get the result 90.
Can you please post a clear example preferably including screenshot of what you have input on that website?
Can you please post a clear example preferably including screenshot of what you have input on that website?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Guys,
I am very thankful to everyone for support you gave me. It worked and I am very happy to continue my project since it was very hard for me to finish/continue the project without proper calculations. The code I've posted could be very disorganized however it is the reason of overnight working & coding. I have tried different methods to find a solution and there it is. Thank you very much to all of you! :)
I am very thankful to everyone for support you gave me. It worked and I am very happy to continue my project since it was very hard for me to finish/continue the project without proper calculations. The code I've posted could be very disorganized however it is the reason of overnight working & coding. I have tried different methods to find a solution and there it is. Thank you very much to all of you! :)
I'm an Excel VBA kind of guy, and so had to read up on the Decimal variable type at http://www.visualbasic.w3computing.com/vb2008/2/vb-decimal-data-type.php. I bolded one specific sentence in the quote below, where it leads me to believe that Double might work better.