根据2个经纬度点,计算这2个经纬度点之间的距离(经过经度纬度获得距离)java
/// 根据经纬度,计算2个点之间的距离。 public static void main(String[] args) { System.out.println(Distance(39.93184899714498,119.54970616784544,39.91492784069314,119.54092245004847)); } public static double HaverSin(double theta) { double v = Math.sin(theta / 2); return v * v; } static double EARTH_RADIUS = 6371.0*1000;//km 地球半径 平均值,公里 /// 给定的经度1,纬度1;经度2,纬度2. 计算2个经纬度之间的距离。 public static double Distance(double lat1,double lon1, double lat2,double lon2) { //用haversine公式计算球面两点间的距离。 //经纬度转换成弧度 lat1 = ConvertDegreesToRadians(lat1); lon1 = ConvertDegreesToRadians(lon1); lat2 = ConvertDegreesToRadians(lat2); lon2 = ConvertDegreesToRadians(lon2); //差值 double vLon = Math.abs(lon1 - lon2); double vLat = Math.abs(lat1 - lat2); //h is the great circle distance in radians, great circle就是一个球体上的切面,它的圆心便是球心的一个周长最大的圆。 double h = HaverSin(vLat) + Math.cos(lat1) * Math.cos(lat2) * HaverSin(vLon); double distance = 2 * EARTH_RADIUS * Math.asin(Math.sqrt(h)); return distance; } /// 将角度换算为弧度。 public static double ConvertDegreesToRadians(double degrees) { return degrees * Math.PI / 180; } public static double ConvertRadiansToDegrees(double radian) { return radian * 180.0 / Math.PI; }
球面上任意两点之间的距离计算公式能够参考维基百科上的下述文章。函数
值得一提的是,维基百科推荐使用Haversine公式,理由是Great-circle distance公式用到了大量余弦函数, 而两点间距离很短时(好比地球表面上相距几百米的两点),余弦函数会得出0.999...的结果, 会致使较大的舍入偏差。而Haversine公式采用了正弦函数,即便距离很小,也能保持足够的有效数字。 之前采用三角函数表计算时的确会有这个问题,但通过实际验证,采用计算机来计算时,两个公式的区别不大。 稳妥起见,这里仍是采用Haversine公式。code
其中orm
根据2个经纬度坐标,距离计算函数ip
下面就是计算球面间两点(lat1, lon1) - (lat2, lon2)之间距离的函数。ci
公式来历:rem
VERSINE(F)=1-cos(F)get
Haversine名字来历是Ha-VERSINE,即Half-Versine ,表示sin的一半的意思。form
hav(A) = (1-cos(A))/2 = sin(A/2)* sin(A/2)class
推倒过程:
以下一个半径为1 的圆,O是圆心,A、B是弦(chord)。角度AOB=theta。则角度AOC=theta/2。OC是垂直于AB的垂线(perpendicular)。AC长度是sin(theta/2),AB长度是2*sin(theta/2)。
(图1)
以下地球图所示,假设半径R为1,O是球心,A (lat1,lon1) 和 B (lat2,lon2) 是咱们感兴趣的2个点。2跟经度线 lon1,lon2相交于北极(north pole)N。EF所在的线是赤道(equator)。ACBD是平面上的等腰梯形的四个顶点(vertice)。AC和DB的弦(直线)在图上没有画出。CD的位置是:C (lat2,lon1) and D (lat1,lon2)。角度AOC是A点与C点的纬度差 dlat。角度EOF是经度E点和经度F点的差dlon。
(图2)
弦AC的长度,参照图1的方式,那么是AC=2*sin(dlat/2),弦BD也是同样的长度。
E、F 2个点是赤道上的2个点,它们的纬度是0。EF的距离是EF=2*sin(dlon/2)
A、D2个点所在的纬度是lat1。AD所在纬度的圆平面的半径是cos(lat1)。从A做一条垂线(perpendicular)到OE为AG,AO是球半径,则OG=cos(lat1),即A、D所在纬度圆圈的半径(AO`)。
这时候,AD的弦长AD= 2*sin(dlon/2)*cos(lat1),相似的能够推出CB的长度= CB=2*sin(dlon/2)*cos(lat2)
下面看一下如何求AB的长度,回到平面等腰梯形,以下图:
(图3)
AH是到CB的垂线(perpendicular),CH= (CB-AD)/2。
根据勾股定理(Pythagorean theorem): 【^2表示2的平方】
AH^2 = AC^2 - CH^2
= AC^2 - (CB-AD)^2/4
HB 的长度是HB=AD+CH = AD+(CB-AD)/2 = (CB+AD)/2,根据勾股定理获得:
AB^2 = AH^2 + HB^2
= AC^2 - (CB-AD)^2/4 + (CB+AD)^2/4
= AC^2 + CB*AD
根据前面球面上的求经纬距离的方式,咱们已经获得 AC、AD和CB的长度,代入公式获得:
AB^2 = 4*(sin^2(dlat/2) + 4*cos(lat1)*cos(lat2)*sin^2(dlon/2))
假设中间值h 是AB长度一半的平方,以下
h = (AB/2)^2
= (sin^2(dlat/2)) + cos(lat1) * cos(lat2) * sin^2(dlon/2)
(请参看代码里的h)
最后一步,是求得表明AB长度的角度AOB。参照图1的方式,咱们能够知道
(图4)
设AC=,根据勾股定理(Pythagorean theorem)获得:
OC= = sqrt(OA^2 - AC^2)
= = sqrt(1-a) // sqrt表示开根号
若是设c是角AOB的度数值。
tan(<AOC) = tan(c)= AC/OC = sqrt(a)/sqrt(1-a)
则:
c = 2 * arctan(sqrt(a)/sqrt(1-a)),
最后的AB真实距离,把地球半径带上就能够了。
distance = 2 * EARTH_RADIUS * c。