Https://software.intel.com/en-us/blogs/2012/11/30/calculating-a-bearing-between-points-in-location-aware-apps
Submitted by John Mechalas (... on Fri, 11/30/2012-08:37
Earlier this week I wrote about what to calculate the distance between II points in a Location-aware app. Today, I am going to discuss a related topic:how to calculate the bearing between.
Like the shortest-distance problem, the bearing between and the points on the globe are calculated using the Great circle arc T Hat connects them. With the exception of lines of latitude and longitude, great circle arcs does not follow a constant direction relative to TR UE North and this means the along the arc your heading would vary.
This was made clear in the figure below, which is a gnomonic projection of the Earth, showing we route from Portland to Lo Ndon (the gnomonic projection have a very special property:straight lines on the map correspond to Great circle arcs). As can see, the direction of travel changes along the path. The initial bearing, or forward azimuth, is about 33.6°but the final bearing as we approach London are about 141.5°.
|
As you travel along a great circle route your bearing to your destination changes. The dotted lines represent the direction of true north relative to the starting and ending points. |
To calculate the initial bearing bearing we use the following formula. Note the use of the Two-argument form of the arctangent, atan2 (y,x), which ensures, the resulting angle are in the Corr ECT Quadrant:
θ= atan2 (sin (Δλ) * cos (Φ2), cos (φ1) * sin (Φ2) * cos (Δλ))
This function would return the angle in radians from-πtoπbut "What we want are an" angle in degrees from 0 to 360. To accomplish this, we convert to degrees, add, and take the modulo 360:
Θd = (θ* 180/π+ 360)% 360
To get the final bearing, you reverse the latitudes and longitudes, and then take the angle that's in the opposite direct Ion (degrees around).
Unlike our great circle distance calculation, the bearing calculation makes use of Atan and it contains a singularity:whe n the points converge, the angle becomes undefined. This makes perfect sense in the physical world, as if the source and the destination be exactly the same then there is no Bearing between them. In practice, rounding errors would probably prevent a perfect equality from occurring, but it would still is good form to Assume the points is coincident if their distance is below a threshold distance of a meter or both.
Code
Below is some code snippets that can is used to calculate the bearing between the points. You pass the latitude and longitude (in decimal degrees) for the first point as LAT1 and Long1, and for the second point I n Lat2 and Long2.
For Windows developers, where is a implementation in C #:
classgreatcirclebearing {StaticDouble Degtorad = Math.PI/180.0; Static PublicDouble Initial (double lat1, double long1, double lat2, double long2) {return(_bearing (LAT1, Long1, LAT2, long2) +360.0) % the; } Static PublicDouble final (double lat1, double long1, double lat2, double long2) {return(_bearing (LAT2, Long2, LAT1, long1) +180.0) % the; } Static Privatedouble _bearing (double lat1, double long1, double lat2, double long2) {double Phi1= LAT1 *Degtorad; Double Phi2= Lat2 *Degtorad; Double lam1= Long1 *Degtorad; Double lam2= Long2 *Degtorad; returnMath.atan2 (Math.sin (lam2-lam1) *Math.Cos (PHI2), Math.Cos (PHI1)*math.sin (PHI2)-Math.sin (PHI1) *math.cos (PHI2) *math.cos (lam2-lam1)) * the/Math.PI; } }
And in Javascript:
functionbearinginitial (LAT1, Long1, LAT2, long2) {return(Bearingdegrees (LAT1, Long1, LAT2, long2) + 360)% 360;}functionbearingfinal (LAT1, Long1, LAT2, long2) {return(Bearingdegrees (LAT2, Long2, LAT1, long1) + 180)% 360;}functionbearingdegrees (LAT1, Long1, LAT2, long2) {varDegtorad= math.pi/180.0;varphi1= LAT1 *Degtorad; varphi2= LAT2 *Degtorad; varlam1= Long1 *Degtorad; varlam2= Long2 *Degtorad; returnMath.atan2 (Math.sin (lam2-lam1) *Math.Cos (PHI2), Math.Cos (PHI1)*math.sin (PHI2)-Math.sin (PHI1) *math.cos (PHI2) *math.cos (lam2-lam1)) * 180/MATH.PI;}
And for Android developers, a implementation in Java:
classgreatcirclebearing {Static Public DoubleInitial (DoubleLAT1,DoubleLong1,DoubleLAT2,Doublelong2) { return(_bearing (LAT1, Long1, LAT2, long2) + 360.0)% 360; } Static Public Double Final(DoubleLAT1,DoubleLong1,DoubleLAT2,Doublelong2) { return(_bearing (LAT2, Long2, LAT1, long1) + 180.0)% 360; } Static Private Double_bearing (DoubleLAT1,DoubleLong1,DoubleLAT2,Doublelong2) { Static DoubleDegtorad = math.pi/180.0; DoublePHI1 = LAT1 *Degtorad; DoublePhi2 = Lat2 *Degtorad; DoubleLAM1 = long1 *Degtorad; DoubleLAM2 = Long2 *Degtorad; returnMath.atan2 (Math.sin (lam2-lam1) *Math.Cos (PHI2), Math.Cos (PHI1)*math.sin (PHI2)-Math.sin (PHI1) *math.cos (PHI2) *math.cos (lam2-lam1)) * 180/Math.PI; } }
As with our distance calculations, the assumption behind these formulas are a spherical earth. This was sufficiently accurate for casual use but scientific applications would need a more sophisticated model.