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 how to calculate the distance between two points in a location-aware app. Today, I am going to discuss a related topic: how to calculate the bearing between two points.

Like the shortest-distance problem, the bearing between two points on the globe is calculated using the great circle arc that connects them. With the exception of lines of latitude and longitude, great circle arcs do not follow a constant direction relative to true north and this means that as you travel along the arc your heading will vary.

This is made clear in the figure below, which is a gnomonic projection of the earth, showing our route from Portland to London (the gnomonic projection has a very special property: straight lines on the map correspond to great circle arcs). As you 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 is 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 that the resulting angle is in the correct quadrant:

Θ = atan2( sin(Δλ) * cos(Φ2), cos(Φ1) * sin (Φ2) * cos(Δλ) )

This function will return the angle in radians from -π to π but what we want is an angle in degrees from 0 to 360. To accomplish this, we convert to degrees, add 360, 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 is in the opposite direction (180 degrees around).

Unlike our great circle distance calculation, the bearing calculation makes use of atan and it contains a singularity: when the two points converge, the angle becomes undefined. This makes perfect sense in the physical world, as if the source and the destination are 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 be good form to assume the points are coincident if their distance is below a threshold distance of a meter or two.

Code

Below are some code snippets that can be used to calculate the bearing between two points. You pass the latitude and longitude (in decimal degrees) for the first point as lat1 and long1, and for the second point in lat2 and long2.

For Windows developers, here is an implementation in C#:

class GreatCircleBearing
{
static Double degToRad = Math.PI / 180.0; static public Double initial (Double lat1, Double long1, Double lat2, Double long2)
{
return (_bearing(lat1, long1, lat2, long2) + 360.0) % ;
} static public Double final(Double lat1, Double long1, Double lat2, Double long2)
{
return (_bearing(lat2, long2, lat1, long1) + 180.0) % ;
} static private Double _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; return Math.Atan2(Math.Sin(lam2-lam1)*Math.Cos(phi2),
Math.Cos(phi1)*Math.Sin(phi2) - Math.Sin(phi1)*Math.Cos(phi2)*Math.Cos(lam2-lam1)
) * /Math.PI;
}
}

And in Javascript:

function bearingInitial (lat1, long1, lat2, long2)
{
return (bearingDegrees(lat1, long1, lat2, long2) + 360) % 360;
} function bearingFinal(lat1, long1, lat2, long2) {
return (bearingDegrees(lat2, long2, lat1, long1) + 180) % 360;
} function bearingDegrees (lat1, long1, lat2, long2)
{
var degToRad= Math.PI/180.0; var phi1= lat1 * degToRad;
var phi2= lat2 * degToRad;
var lam1= long1 * degToRad;
var lam2= long2 * degToRad; return Math.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, an implementation in Java:

    class GreatCircleBearing
{
static public double initial (double lat1, double long1, double lat2, double long2)
{
return (_bearing(lat1, long1, lat2, long2) + 360.0) % 360;
} static public double final(double lat1, double long1, double lat2, double long2)
{
return (_bearing(lat2, long2, lat1, long1) + 180.0) % 360;
} static private double _bearing(double lat1, double long1, double lat2, double long2)
{
static double degToRad = Math.PI / 180.0;
double phi1 = lat1 * degToRad;
double phi2 = lat2 * degToRad;
double lam1 = long1 * degToRad;
double lam2 = long2 * degToRad; return Math.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 is a spherical earth. This is sufficiently accurate for casual use but scientific applications will need a more sophisticated model.

Calculating a bearing between points in location-aware apps的更多相关文章

  1. How To Start Building Spatially Aware Apps With Google’s Project Tango

    How To Start Building Spatially Aware Apps With Google’s Project Tango “Tango can enable a whole new ...

  2. (转) [it-ebooks]电子书列表

    [it-ebooks]电子书列表   [2014]: Learning Objective-C by Developing iPhone Games || Leverage Xcode and Obj ...

  3. spring boot上传文件错误The temporary upload location [/tmp/tomcat.5260880110861696164.8090/work/Tomcat/localhost/ROOT] is not valid

    参考了:https://www.jianshu.com/p/cfbbc0bb0b84 再次感谢,但还是有些调整 一.在zuul服务中加入两个配置参数(location: /data/apps/temp ...

  4. Netron开发快速上手(一):GraphControl,Shape,Connector和Connection

    版权所有,引用请注明出处:<<http://www.cnblogs.com/dragon/p/5203663.html >> 本文所用示例下载FlowChart.zip 一个用 ...

  5. infoq - neo4j graph db

    My name is Charles Humble and I am here at QCon New York 2014 with Ian Robinson. Ian, can you introd ...

  6. How parse REST service JSON response

    1. get JSON responses and go to : http://json2csharp.com/ 2. write data contracts using C# All class ...

  7. Unsupervised Classification - Sprawl Classification Algorithm

    Idea Points (data) in same cluster are near each others, or are connected by each others. So: For a ...

  8. PhoneGap API Documentation API Reference

    API Reference-API参考 Accelerometer-加速度计 Tap into the device's motion sensor.-点击进入该设备的运动传感器. Camera-相机 ...

  9. Upgrade Guide

    Upgrade Guide This guide will point out the key points to be aware of when upgrading to version 3. A ...

随机推荐

  1. 01-语言入门-01-A+B Problem

    题目地址: http://acm.nyist.net/JudgeOnline/problem.php?pid=1    描述 此题为练手用题,请大家计算一下a+b的值   输入 输入两个数,a,b 输 ...

  2. 【POJ】2170 Lattice Animals

    1. 题目描述给定$n \times m, n.m \in [1, 10]$的方格,求不同形状的$[1 \cdots 10]$联通块的个数?所谓不同形状,表示不能通过平移.旋转.镜像实现相同的形状.2 ...

  3. Android开发之定义接口暴露数据

    写了一个网络请求的工具类,然后想要获取到网络请求的结果,在网络工具类中写了一个接口,暴露除了请求到的数据 代码: package com.lijingbo.knowweather.utils; imp ...

  4. CRC校验码

    循环冗余校验码(CRC)的基本原理是:在K位信息码后再拼接R位的校验码,整个编码长度为N位,因此,这种编码也叫(N,K)码.对于一个给定的(N,K)码,可以证明存在一个最高次幂为R的多项式G(x)(R ...

  5. treap完全版模板

    这是我综合poj1442 3481 2352的treap操作 得到treap完全版模板.(经测AC) 结构体Tree { int key; //键值 int size; //该子树总节点个数 int ...

  6. poj3683 Priest John's Busiest Day

    2-SAT. 读入用了黄学长的快速读入,在此膜拜感谢. 把每对时间当作俩个点.如果有交叉代表相互矛盾. 然后tarjan缩点,这样就能得出当前的2-SAT问题是否有解. 如果有解,跑拓扑排序就能找出一 ...

  7. iOS开发:在Xcode中用Pods管理第三方库

    之前写了一篇 iOS开发:在Swift中调用oc库 ,今天记录一下如何用Pods的方式来管理第三方库,包括Swift/Object-C的库. 在这之前请先查阅Guides.CocoaPods如何使用的 ...

  8. I.MX6 lcd lvds hdmi bootargs

    /********************************************************************* * I.MX6 lcd lvds hdmi bootarg ...

  9. Oracle日常维护脚本

    1.正常停库流程     ps -ef|grep LOCAL=NO|cut -c 9-15|xargs kill -9      shutdown immediate; 2.备份数据库     bac ...

  10. [Everyday Mathematics]20150116

    设 $\al_n\geq 0$ 且 $\dps{\vlm{n}\al_n=0}$, 试求 $$\bex \vlm{n}\frac{1}{n}\sum_{k=1}^n \ln\sex{\frac{k}{ ...