根据2个经纬度点,计算这2个经纬度点之间的距离

原文  http://www.cnblogs.com/softfair/p/distance_of_two_latitude_and_longitude_points.html

根据 2 个经纬度点,计算这 2 个经纬度点之间的距离

球面上任意两点之间的距离计算公式可以参考维基百科上的下述文章。

值得一提的是,维基百科推荐使用Haversine公式,理由是Great-circle distance公式用到了大量余弦函数, 而两点间距离很短时(比如地球表面上相距几百米的两点),余弦函数会得出0.999...的结果, 会导致较大的舍入误差。而Haversine公式采用了正弦函数,即使距离很小,也能保持足够的有效数字。 以前采用三角函数表计算时的确会有这个问题,但经过实际验证,采用计算机来计算时,两个公式的区别不大。 稳妥起见,这里还是采用Haversine公式。

其中

  • R为地球半径,可取平均值 6371km;
  • φ 1 , φ 2  表示两点的纬度;
  • Δλ 表示两点经度的差值。

根据 个经纬度坐标,距离计算函数

下面就是计算球面间两点(lat1, lon1) - (lat2, lon2)之间距离的函数。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace HarvenSin
{
    class Program
    {
  /// <summary>
  /// 根据经纬度,计算2个点之间的距离。
  /// </summary>
  /// <param name="args"></param>
  static void Main(string[] args)
  {
      //39.94607,116.32793  31.24063,121.42575
      Console.WriteLine(Distance(39.94607, 116.32793, 31.24063, 121.42575));
  }
  public static double HaverSin(double theta)
  {
      var v = Math.Sin(theta / 2);
      return v * v;
  }
  static double EARTH_RADIUS = 6371.0;//km 地球半径 平均值,千米
  /// <summary>
  /// 给定的经度1,纬度1;经度2,纬度2. 计算2个经纬度之间的距离。
  /// </summary>
  /// <param name="lat1">经度1</param>
  /// <param name="lon1">纬度1</param>
  /// <param name="lat2">经度2</param>
  /// <param name="lon2">纬度2</param>
  /// <returns>距离(公里、千米)</returns>
  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);
      //差值
      var vLon = Math.Abs(lon1 - lon2);
      var vLat = Math.Abs(lat1 - lat2);
      //h is the great circle distance in radians, great circle就是一个球体上的切面,它的圆心即是球心的一个周长最大的圆。
      var h = HaverSin(vLat) + Math.Cos(lat1) * Math.Cos(lat2) * HaverSin(vLon);
      var distance = 2 * EARTH_RADIUS * Math.Asin(Math.Sqrt(h));
      return distance;
  }
  /// <summary>
  /// 将角度换算为弧度。
  /// </summary>
  /// <param name="degrees">角度</param>
  /// <returns>弧度</returns>
  public static double ConvertDegreesToRadians(double degrees)
  {
      return degrees * Math.PI / 180;
  }
  public static double ConvertRadiansToDegrees(double radian)
  {
      return radian * 180.0 / Math.PI;
  }
    }
}

公式来历:

VERSINE(F)=1-cos(F)

Haversine名字来历是Ha-VERSINE,即Half-Versine ,表示sin的一半的意思。

hav(A) = (1-cos(A))/2 = sin(A/2)* sin(A/2)

推倒过程:

如下一个半径为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。

结束。

参考资料:

http://mathforum.org/library/drmath/view/51879.html

http://blog.charlee.li/location-search/

时间: 2024-10-07 15:27:01

根据2个经纬度点,计算这2个经纬度点之间的距离的相关文章

Lua 计算两个GPS坐标点之间的距离

local EARTH_RADIUS = 6378.137local function rad(d) return d * math.pi / 180.0end local function getDistance(lat1,lng1,lat2,lng2) local radLat1 = rad(lat1) local radLat2 = rad(lat2) local a = radLat1 - radLat2 local b = rad(lng1) - rad(lng2) local s =

mysql 下 计算 两点 经纬度 之间的距离

公式如下,单位米: 第一点经纬度:lng1 lat1 第二点经纬度:lng2 lat2 round(6378.138*2*asin(sqrt(pow(sin( (lat1*pi()/180-lat2*pi()/180)/2),2)+cos(lat1*pi()/180)*cos(lat2*pi()/180)* pow(sin( (lng1*pi()/180-lng2*pi()/180)/2),2)))*1000) 例如: SELECT store_id,lng,lat, ROUND(6378.13

java通过经纬度计算两个点的之间的距离的算法

通过两个点的经纬度计算距离 从google maps的脚本里扒了段代码,没准啥时会用上.大家一块看看是怎么算的.private const double EARTH_RADIUS = 6378.137;private static double rad(double d){   return d * Math.PI / 180.0;} public static double GetDistance(double lat1, double lng1, double lat2, double ln

计算两个GPS经纬度坐标之间的距离 PHP

不多说了,自己代码就行,你可以直接拿来用. /** * 计算两个坐标之间的距离(米) * @param float $fP1Lat 起点(纬度) * @param float $fP1Lon 起点(经度) * @param float $fP2Lat 终点(纬度) * @param float $fP2Lon 终点(经度) * @return int */ function distanceBetween($fP1Lat, $fP1Lon, $fP2Lat, $fP2Lon){ $fEARTH_

IOS 计算两个经纬度之间的距离

一 丶 -(double)distanceBetweenOrderBy:(double) lat1 :(double) lat2 :(double) lng1 :(double) lng2{ CLLocation *curLocation = [[CLLocation alloc] initWithLatitude:lat1 longitude:lng1]; CLLocation *otherLocation = [[CLLocation alloc] initWithLatitude:lat2

计算两个经纬度之间的距离(python算法)

EARTH_REDIUS = 6378.137 def rad(d): return d * pi / 180.0 def getDistance(lat1, lng1, lat2, lng2): radLat1 = rad(lat1) radLat2 = rad(lat2) a = radLat1 - radLat2 b = rad(lng1) - rad(lng2) s = 2 * math.asin(math.sqrt(math.pow(sin(a/2), 2) + cos(radLat1

给你两个经纬度,计算他们之间的距离

原文:给你两个经纬度,计算他们之间的距离 这些经纬线是怎样定出来的呢?地球是在不停地绕地轴旋转(地轴是一根通过地球南北两极和地球中心的假想线),在地球中腰画一个与地轴垂直的大圆圈,使圈上的每一点都和南北两极的距离相等,这个圆圈就叫作“赤道”.在赤道的南北两边,画出许多和赤道平行的圆圈,就是“纬圈”:构成这些圆圈的线段,叫做纬线.我们把赤道定为纬度零度,向南向北各为90度,在赤道以南的叫南纬,在赤道以北的叫北纬.北极就是北纬90度,南极就是南纬90度.纬度的高低也标志着气候的冷热,如赤道和低纬度地

计算2个坐标(经纬度)之间的距离,.Net

.Net 中计算2个点之间的距离的方法,或者叫计算2个坐标,2个经纬度之间的距离. 代码如下: 1 /// <summary> 2 /// Calculates the distance between two geographics locations 3 /// </summary> 4 public static class GeoDistance 5 { 6 public static double Between(double latitude1, double long

sql server2008根据经纬度计算两点之间的距离

--通过经纬度计算两点之间的距离 create FUNCTION [dbo].[fnGetDistanceNew] --LatBegin 开始经度 --LngBegin 开始维度 --29.490295,106.486654,29.615467, 106.581515 (@LatBegin1 varchar(128), @LngBegin1 varchar(128),@location varchar(128)) Returns real AS BEGIN --转换location字段,防止字段