Sunday 26 May 2019

google maps - Calculate bearing between two decimal GPS coordinates


I'm building a virtual tour application that uses custom panoramas in conjunction with Google's StreetView service. With StreetView, you can have 1 to n links at each particular location to move to, and these links are based on compass bearings.


Each panorama has an associated GPS location to six decimal places acquired via iTouchMaps. My issue is when I calculate the compass bearings from each link location, it returns a bearing that is a tiny (as in 0.00001 degree difference) from true north.


Given a map like


                       4
|

|
|
2
|
|
|
1

where each number is a location and has the following values:


1- 43.682213, -70.450696

2- 43.682194, -70.450769
4- 43.682179, -70.450837

What I'd like is a method to determine programatically that the bearing from 1 to 2 and 2 to 4 is 70 degrees, and 2 to 1 is 250 degrees. Using the code from here as a starting point, I wrote the following function


//starting lat/long along with converting degrees to radius
var endLat = location.lat(); //for rhumb calc
var endLong = location.lng();

//loop over response, calculate new headings for links and add link to array
for(var i=0; i
//this link's lat/long coordinates
var startLat = data[i].lat;
var startLong = data[i].lon;

//get the delta values between start and end coordinates
var dLong = endLong - startLong;

//calculate rhumb bearing to
var dPhi = Math.log(Math.tan(endLat/2+Math.PI/4)/Math.tan(startLat/2+Math.PI/4));
if (Math.abs(dLong) > Math.PI ) dLong = dLong > 0 ? -(2*Math.PI-dLong) : (2*Math.PI+dLong);

var bearing = (toDeg(Math.atan(dLong, dPhi)) + 360) % 360;

Using the above function and substituting


location for position 2
data[0] for position 1
data[1] for position 4

I get the bearings


359.9958174081038 degrees to 4 (should be 70 degrees)


and


0.0038961130024404156 degrees to 1 (should be 250)

Why is this function returning such different values than expected?



Answer



It looks to me like you need to perform the trigonometry in radians not degrees. You use a function toDeg() so presumably you have one called toRad() (or possibly fromDeg() if you're odd). Call that function with your latitude and longitude values before the calculations, and you should be set.


Edit


I just tried this in Python (the syntax isn't dissimilar to JavaScript) using radians and your coordinates:


startLat = math.radians(43.682213)
startLong = math.radians(-70.450696)

endLat = math.radians(43.682194)
endLong = math.radians(-70.450769)

dLong = endLong - startLong

dPhi = math.log(math.tan(endLat/2.0+math.pi/4.0)/math.tan(startLat/2.0+math.pi/4.0))
if abs(dLong) > math.pi:
if dLong > 0.0:
dLong = -(2.0 * math.pi - dLong)
else:

dLong = (2.0 * math.pi + dLong)

bearing = (math.degrees(math.atan2(dLong, dPhi)) + 360.0) % 360.0;

print(bearing)

and I get 250.20613449 as expected.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...