近期做一个与GRPS相关的应用,涉及到经纬度的计算,找资料时颇费了一番功夫,特此将其相关资料整理了一下,发布出来,希望对用到的同学有所帮助。
闲话少说,经纬度计算主要有两种:
1. 知道两点的经纬度值,计算两点间的距离
2. 知道一点的经纬度,知道另一点相对于此点的角度,距离。计算另一点的经纬度信息
对于第一种计算,网上搜索到大概有三种:
1. 把地球当球体,根据球面公式计算
2. 根据公式d=111.12cos{1/[sinΦAsinΦB十cosΦAcosΦBcos(λB—λA)]}
其中A点经度,纬度分别为λA和ΦA,B点的经度、纬度分别为λB和ΦB,d为距离。
这个公司搜索结果挺多,在百度搜索“经纬度 计算距离”,一二位都是这个公式。
3. 从Google地图中反推出的算法(详见参考文档1)。公式如下图
第一种没做验证,第二种测试了一下,偏差较大(以圆明园、动物园之间的距离进行测定)目前采用的是第三种算法。
对于第二种计算,找到的资料很少,倒是找到不少遇到相同问题的朋友。不过最终还是找到了(详见参考文档2)。并使用第一种计算进行反验证,偏差很小。
整理后的代码如下:
经纬度类
代码
1 using System;
2 using System.Data;
3 using System.Configuration;
4 using System.Linq;
5 using System.Web;
6 using System.Web.Security;
7 using System.Web.UI;
8 using System.Web.UI.HtmlControls;
9 using System.Web.UI.WebControls;
10 using System.Web.UI.WebControls.WebParts;
11 using System.Xml.Linq;
12
13 namespace GeoSite
14 {
15 /// <summary>
16 /// 经纬度表示类
17 /// 经纬度计算主要有两种:
18 /// 1. 知道两点的经纬度值,计算两点间的距离
19 /// 2. 知道一点的经纬度,知道另一点相对于此点的角度,距离。计算另一点的经纬度信息
20 /// http://blog.csdn.net/fdnike/archive/2007/07/18/1696603.aspx
21 /// </summary>
22 public class LatLon
23 {
24 /// <summary>
25 /// 赤道半径 earth radius
26 /// </summary>
27 public const double EARTH_RADIUS = 6378137;
28
29 /// <summary>
30 /// 极半径 polar radius
31 /// </summary>
32 public const double POLAR_RADIUS = 6356725;
33
34 /// <summary>
35 ///
36 /// </summary>
37 public LatLon()
38 { }
39
40 /// <summary>
41 /// 构造函数
42 /// </summary>
43 /// <param name="lat">维度</param>
44 /// <param name="lon">经度</param>
45 public LatLon(double lat, double lon)
46 {
47 this.Lat = lat;
48 this.Lon = lon;
49 }
50
51 /// <summary>
52 /// 纬度
53 /// </summary>
54 public double Lat { get; set; }
55
56 /// <summary>
57 /// 经度
58 /// </summary>
59 public double Lon { get; set; }
60
61 /// <summary>
62 /// 纬度的弧度
63 /// </summary>
64 public double RadLat { get { return Lat * Math.PI / 180; } }
65
66 /// <summary>
67 /// 经度的弧度
68 /// </summary>
69 public double RadLon { get { return Lon * Math.PI / 180; } }
70
71 /// <summary>
72 /// ?
73 /// </summary>
74 public double Ec { get { return POLAR_RADIUS + (EARTH_RADIUS - POLAR_RADIUS) * (90 - Lat) / 90; } }
75
76 /// <summary>
77 /// ?
78 /// </summary>
79 public double Ed { get { return Ec * Math.Cos(RadLat); } }
80 }
81 }
82
2 using System.Data;
3 using System.Configuration;
4 using System.Linq;
5 using System.Web;
6 using System.Web.Security;
7 using System.Web.UI;
8 using System.Web.UI.HtmlControls;
9 using System.Web.UI.WebControls;
10 using System.Web.UI.WebControls.WebParts;
11 using System.Xml.Linq;
12
13 namespace GeoSite
14 {
15 /// <summary>
16 /// 经纬度表示类
17 /// 经纬度计算主要有两种:
18 /// 1. 知道两点的经纬度值,计算两点间的距离
19 /// 2. 知道一点的经纬度,知道另一点相对于此点的角度,距离。计算另一点的经纬度信息
20 /// http://blog.csdn.net/fdnike/archive/2007/07/18/1696603.aspx
21 /// </summary>
22 public class LatLon
23 {
24 /// <summary>
25 /// 赤道半径 earth radius
26 /// </summary>
27 public const double EARTH_RADIUS = 6378137;
28
29 /// <summary>
30 /// 极半径 polar radius
31 /// </summary>
32 public const double POLAR_RADIUS = 6356725;
33
34 /// <summary>
35 ///
36 /// </summary>
37 public LatLon()
38 { }
39
40 /// <summary>
41 /// 构造函数
42 /// </summary>
43 /// <param name="lat">维度</param>
44 /// <param name="lon">经度</param>
45 public LatLon(double lat, double lon)
46 {
47 this.Lat = lat;
48 this.Lon = lon;
49 }
50
51 /// <summary>
52 /// 纬度
53 /// </summary>
54 public double Lat { get; set; }
55
56 /// <summary>
57 /// 经度
58 /// </summary>
59 public double Lon { get; set; }
60
61 /// <summary>
62 /// 纬度的弧度
63 /// </summary>
64 public double RadLat { get { return Lat * Math.PI / 180; } }
65
66 /// <summary>
67 /// 经度的弧度
68 /// </summary>
69 public double RadLon { get { return Lon * Math.PI / 180; } }
70
71 /// <summary>
72 /// ?
73 /// </summary>
74 public double Ec { get { return POLAR_RADIUS + (EARTH_RADIUS - POLAR_RADIUS) * (90 - Lat) / 90; } }
75
76 /// <summary>
77 /// ?
78 /// </summary>
79 public double Ed { get { return Ec * Math.Cos(RadLat); } }
80 }
81 }
82
计算类:
代码
1 using System;
2 using System.Data;
3 using System.Configuration;
4 using System.Linq;
5 using System.Web;
6 using System.Web.Security;
7 using System.Web.UI;
8 using System.Web.UI.HtmlControls;
9 using System.Web.UI.WebControls;
10 using System.Web.UI.WebControls.WebParts;
11 using System.Xml.Linq;
12
13 namespace GeoSite
14 {
15 /// <summary>
16 /// Geo辅助类
17 /// </summary>
18 public static class GeoHelper
19 {
20 /// <summary>
21 /// 根据两点的经纬度计算两点距离
22 /// 可参考:通过经纬度计算距离的公式 http://www.storyday.com/html/y2009/2212_according-to-latitude-and-longitude-distance-calculation-formula.html
23 /// </summary>
24 /// <param name="src">A点维度</param>
25 /// <param name="dest">B点经度</param>
26 /// <returns></returns>
27 public static double GetDistance(LatLon src, LatLon dest)
28 {
29 if (Math.Abs(src.Lat) > 90 || Math.Abs(dest.Lat) > 90 || Math.Abs(src.Lon) > 180 || Math.Abs(dest.Lon) > 180)
30 throw new ArgumentException("经纬度信息不正确!");
31
32 double latDis = src.RadLat - dest.RadLat;
33 double lonDis = src.RadLon - dest.RadLon;
34
35 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)));
36 s = s * LatLon.EARTH_RADIUS / 1000;
37 s = Math.Round(s * 10000) / 10000;
38
39 return s;
40 }
41
42 /// <summary>
43 /// 根据两点的经纬度计算两点距离
44 /// 可参考:通过经纬度计算距离的公式 http://www.storyday.com/html/y2009/2212_according-to-latitude-and-longitude-distance-calculation-formula.html
45 /// </summary>
46 /// <param name="lat1">A点维度</param>
47 /// <param name="lon1">A点经度</param>
48 /// <param name="lat2">B点维度</param>
49 /// <param name="lon2">B点经度</param>
50 /// <returns></returns>
51 public static double GetDistance(double lat1, double lon1, double lat2, double lon2)
52 {
53 LatLon src = new LatLon(lat1, lon1);
54 LatLon dest = new LatLon(lat2, lon2);
55 return GetDistance(src, dest);
56 }
57
58
59 /// <summary>
60 /// 已知点A经纬度,根据B点据A点的距离,和方位,求B点的经纬度
61 /// </summary>
62 /// <param name="a">已知点A</param>
63 /// <param name="distance">B点到A点的距离 </param>
64 /// <param name="angle">B点相对于A点的方位,12点钟方向为零度,角度顺时针增加</param>
65 /// <returns>B点的经纬度坐标</returns>
66 public static LatLon GetLatLon(LatLon a, double distance, double angle)
67 {
68 double dx = distance * 1000 * Math.Sin(angle * Math.PI / 180);
69 double dy = distance * 1000 * Math.Cos(angle * Math.PI / 180);
70
71 double lon = (dx / a.Ed + a.RadLon) * 180 / Math.PI;
72 double lat = (dy / a.Ec + a.RadLat) * 180 / Math.PI;
73
74 LatLon b = new LatLon(lat, lon);
75 return b;
76 }
77
78 /// <summary>
79 /// 已知点A经纬度,根据B点据A点的距离,和方位,求B点的经纬度
80 /// </summary>
81 /// <param name="longitude">已知点A经度</param>
2 using System.Data;
3 using System.Configuration;
4 using System.Linq;
5 using System.Web;
6 using System.Web.Security;
7 using System.Web.UI;
8 using System.Web.UI.HtmlControls;
9 using System.Web.UI.WebControls;
10 using System.Web.UI.WebControls.WebParts;
11 using System.Xml.Linq;
12
13 namespace GeoSite
14 {
15 /// <summary>
16 /// Geo辅助类
17 /// </summary>
18 public static class GeoHelper
19 {
20 /// <summary>
21 /// 根据两点的经纬度计算两点距离
22 /// 可参考:通过经纬度计算距离的公式 http://www.storyday.com/html/y2009/2212_according-to-latitude-and-longitude-distance-calculation-formula.html
23 /// </summary>
24 /// <param name="src">A点维度</param>
25 /// <param name="dest">B点经度</param>
26 /// <returns></returns>
27 public static double GetDistance(LatLon src, LatLon dest)
28 {
29 if (Math.Abs(src.Lat) > 90 || Math.Abs(dest.Lat) > 90 || Math.Abs(src.Lon) > 180 || Math.Abs(dest.Lon) > 180)
30 throw new ArgumentException("经纬度信息不正确!");
31
32 double latDis = src.RadLat - dest.RadLat;
33 double lonDis = src.RadLon - dest.RadLon;
34
35 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)));
36 s = s * LatLon.EARTH_RADIUS / 1000;
37 s = Math.Round(s * 10000) / 10000;
38
39 return s;
40 }
41
42 /// <summary>
43 /// 根据两点的经纬度计算两点距离
44 /// 可参考:通过经纬度计算距离的公式 http://www.storyday.com/html/y2009/2212_according-to-latitude-and-longitude-distance-calculation-formula.html
45 /// </summary>
46 /// <param name="lat1">A点维度</param>
47 /// <param name="lon1">A点经度</param>
48 /// <param name="lat2">B点维度</param>
49 /// <param name="lon2">B点经度</param>
50 /// <returns></returns>
51 public static double GetDistance(double lat1, double lon1, double lat2, double lon2)
52 {
53 LatLon src = new LatLon(lat1, lon1);
54 LatLon dest = new LatLon(lat2, lon2);
55 return GetDistance(src, dest);
56 }
57
58
59 /// <summary>
60 /// 已知点A经纬度,根据B点据A点的距离,和方位,求B点的经纬度
61 /// </summary>
62 /// <param name="a">已知点A</param>
63 /// <param name="distance">B点到A点的距离 </param>
64 /// <param name="angle">B点相对于A点的方位,12点钟方向为零度,角度顺时针增加</param>
65 /// <returns>B点的经纬度坐标</returns>
66 public static LatLon GetLatLon(LatLon a, double distance, double angle)
67 {
68 double dx = distance * 1000 * Math.Sin(angle * Math.PI / 180);
69 double dy = distance * 1000 * Math.Cos(angle * Math.PI / 180);
70
71 double lon = (dx / a.Ed + a.RadLon) * 180 / Math.PI;
72 double lat = (dy / a.Ec + a.RadLat) * 180 / Math.PI;
73
74 LatLon b = new LatLon(lat, lon);
75 return b;
76 }
77
78 /// <summary>
79 /// 已知点A经纬度,根据B点据A点的距离,和方位,求B点的经纬度
80 /// </summary>
81 /// <param name="longitude">已知点A经度</param>