经纬度相关计算
2010-07-13 03:01 韩龙 阅读(4997) 评论(7) 编辑 收藏 举报近期做一个与GRPS相关的应用,涉及到经纬度的计算,找资料时颇费了一番功夫,特此将其相关资料整理了一下,发布出来,希望对用到的同学有所帮助。
闲话少说,经纬度计算主要有两种:
1. 知道两点的经纬度值,计算两点间的距离
2. 知道一点的经纬度,知道另一点相对于此点的角度,距离。计算另一点的经纬度信息
对于第一种计算,网上搜索到大概有三种:
1. 把地球当球体,根据球面公式计算
2. 根据如下公式进行计算:
其中A点纬度、经度分别为lat1和lon1,B点的纬度、经度分别为lat2和lon2,D为距离。
这个公式搜索结果挺多,在百度搜索"经纬度 计算距离"很多都是这个公式。
3. 从Google地图中反推出的算法(详见参考文档1)。公式如下图
公式中经纬度均用弧度表示;lat1,lon1 表示A点经纬度,lat2,lon2 表示B点经纬度;
a= lat1 – lat2 为两点纬度之差 ; b= lon1 - lon2 为两点经度之差;
6378.137为地球半径,单位为公里;
第一种没做验证,第二种测试了一下,偏差较大(以圆明园、动物园之间的距离进行测定)目前采用的是第三种算法。
第二种计算,找到的资料很少,倒是找到不少遇到相同问题的朋友。不过最终还是找到了(详见参考文档2)。并使用第一种计算进行反验证,偏差很小。
整理后的代码如下:
经纬度类:
using System; using System.Data; using System.Configuration; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; namespace GeoSite { /// <summary> /// 经纬度表示类 /// 经纬度计算主要有两种: /// 1. 知道两点的经纬度值,计算两点间的距离 /// 2. 知道一点的经纬度,知道另一点相对于此点的角度,距离。计算另一点的经纬度信息 /// http://blog.csdn.net/fdnike/archive/2007/07/18/1696603.aspx /// </summary> public class LatLon { /// <summary> /// 赤道半径 earth radius /// </summary> public const double EARTH_RADIUS = 6378137; /// <summary> /// 极半径 polar radius /// </summary> public const double POLAR_RADIUS = 6356725; /// <summary> /// /// </summary> public LatLon() { } /// <summary> /// 构造函数 /// </summary> /// <param name="lat">维度</param> /// <param name="lon">经度</param> public LatLon(double lat, double lon) { this.Lat = lat; this.Lon = lon; } /// <summary> /// 纬度 /// </summary> public double Lat { get; set; } /// <summary> /// 经度 /// </summary> public double Lon { get; set; } /// <summary> /// 纬度的弧度 /// </summary> public double RadLat { get { return Lat * Math.PI / 180; } } /// <summary> /// 经度的弧度 /// </summary> public double RadLon { get { return Lon * Math.PI / 180; } } /// <summary> /// ? /// </summary> public double Ec { get { return POLAR_RADIUS + (EARTH_RADIUS - POLAR_RADIUS) * (90 - Lat) / 90; } } /// <summary> /// ? /// </summary> public double Ed { get { return Ec * Math.Cos(RadLat); } } } }
计算类:
using System; using System.Data; using System.Configuration; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; namespace GeoSite { /// <summary> /// Geo辅助类 /// </summary> public static class GeoHelper { /// <summary> /// 根据两点的经纬度计算两点距离 /// </summary> /// <param name="src">A点维度</param> /// <param name="dest">B点经度</param> /// <returns></returns> public static double GetDistance(LatLon src, LatLon dest) { if (Math.Abs(src.Lat) > 90 || Math.Abs(dest.Lat) > 90 || Math.Abs(src.Lon) > 180 || Math.Abs(dest.Lon) > 180) throw new ArgumentException("经纬度信息不正确!"); double latDis = src.RadLat - dest.RadLat; double lonDis = src.RadLon - dest.RadLon; double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(latDis / 2), 2) + Math.Cos(src.Lat) * Math.Cos(dest.Lat) * Math.Pow(Math.Sin(lonDis / 2), 2))); s = s * LatLon.EARTH_RADIUS / 1000; s = Math.Round(s * 10000) / 10000; return s; } /// <summary> /// 根据两点的经纬度计算两点距离 /// </summary> /// <param name="lat1">A点维度</param> /// <param name="lon1">A点经度</param> /// <param name="lat2">B点维度</param> /// <param name="lon2">B点经度</param> /// <returns></returns> public static double GetDistance(double lat1, double lon1, double lat2, double lon2) { LatLon src = new LatLon(lat1, lon1); LatLon dest = new LatLon(lat2, lon2); return GetDistance(src, dest); } /// <summary> /// 已知点A经纬度,根据B点据A点的距离,和方位,求B点的经纬度 /// </summary> /// <param name="a">已知点A</param> /// <param name="distance">B点到A点的距离 </param> /// <param name="angle">B点相对于A点的方位,12点钟方向为零度,角度顺时针增加</param> /// <returns>B点的经纬度坐标</returns> public static LatLon GetLatLon(LatLon a, double distance, double angle) { double dx = distance * 1000 * Math.Sin(angle * Math.PI / 180); double dy = distance * 1000 * Math.Cos(angle * Math.PI / 180); double lon = (dx / a.Ed + a.RadLon) * 180 / Math.PI; double lat = (dy / a.Ec + a.RadLat) * 180 / Math.PI; LatLon b = new LatLon(lat, lon); return b; } /// <summary> /// 已知点A经纬度,根据B点据A点的距离,和方位,求B点的经纬度 /// </summary> /// <param name="longitude">已知点A经度</param> /// <param name="latitude">已知点A纬度</param> /// <param name="distance">B点到A点的距离</param> /// <param name="angle">B点相对于A点的方位,12点钟方向为零度,角度顺时针增加</param> /// <returns>B点的经纬度坐标</returns> public static LatLon GetLatLon(double longitude, double latitude, double distance, double angle) { LatLon a = new LatLon(latitude, longitude); return GetLatLon(a, distance, angle); } } }
示例运行结果:
参考文档:
1. 通过经纬度计算距离的公式
2. 经纬度距离计算
http://blog.csdn.net/fdnike/archive/2007/07/18/1696603.aspx
开发环境:VS2008