public class MapLocationHelper { #region 构造函数 /// <summary> /// 构造函数 /// </summary> public MapLocationHelper() { } #endregion #region 方法 /// <summary> /// 数字经纬度和度分秒经纬度转换 (Digital degree of latitude and longitude and vehicle to latitude and longitude conversion) /// </summary> /// <param name="digitalLati_Longi">数字经纬度</param> /// <return>度分秒经纬度</return> static public string ConvertDigitalToDegrees(string digitalLati_Longi) { double digitalDegree = Convert.ToDouble(digitalLati_Longi); return ConvertDigitalToDegrees(digitalDegree); } /// <summary> /// 数字经纬度和度分秒经纬度转换 (Digital degree of latitude and longitude and vehicle to latitude and longitude conversion) /// </summary> /// <param name="digitalDegree">数字经纬度</param> /// <return>度分秒经纬度</return> static public string ConvertDigitalToDegrees(double digitalDegree) { const double num = 60; int degree = (int)digitalDegree; double tmp = (digitalDegree - degree) * num; int minute = (int)tmp; double second = (tmp - minute) * num; string degrees = "" + degree + "°" + minute + "′" + second + "″"; return degrees; } /// <summary> /// 度分秒经纬度(必须含有'°')和数字经纬度转换 /// </summary> /// <param name="digitalDegree">度分秒经纬度</param> /// <return>数字经纬度</return> static public double ConvertDegreesToDigital(string degrees) { const double num = 60; double digitalDegree = 0.0; int d = degrees.IndexOf('°'); //度的符号对应的 Unicode 代码为:00B0[1](六十进制),显示为°。 if (d < 0) { return digitalDegree; } string degree = degrees.Substring(0, d); digitalDegree += Convert.ToDouble(degree); int m = degrees.IndexOf('′'); //分的符号对应的 Unicode 代码为:2032[1](六十进制),显示为′。 if (m < 0) { return digitalDegree; } string minute = degrees.Substring(d + 1, m - d - 1); digitalDegree += ((Convert.ToDouble(minute)) / num); int s = degrees.IndexOf('″'); //秒的符号对应的 Unicode 代码为:2033[1](六十进制),显示为″。 if (s < 0) { return digitalDegree; } string second = degrees.Substring(m + 1, s - m - 1); digitalDegree += (Convert.ToDouble(second) / (num * num)); return digitalDegree; } /// <summary> /// 度分秒经纬度(必须含有'/')和数字经纬度转换 /// </summary> /// <param name="digitalDegree">度分秒经纬度</param> /// <param name="cflag">分隔符</param> /// <return>数字经纬度</return> static public double ConvertDegreesToDigital_default(string degrees) { char ch = '/'; return ConvertDegreesToDigital(degrees, ch); } /// <summary> /// 度分秒经纬度和数字经纬度转换 /// </summary> /// <param name="digitalDegree">度分秒经纬度</param> /// <param name="cflag">分隔符</param> /// <return>数字经纬度</return> static public double ConvertDegreesToDigital(string degrees, char cflag) { const double num = 60; double digitalDegree = 0.0; int d = degrees.IndexOf(cflag); if (d < 0) { return digitalDegree; } string degree = degrees.Substring(0, d); digitalDegree += Convert.ToDouble(degree); int m = degrees.IndexOf(cflag, d + 1); if (m < 0) { return digitalDegree; } string minute = degrees.Substring(d + 1, m - d - 1); digitalDegree += ((Convert.ToDouble(minute)) / num); int s = degrees.Length; if (s < 0) { return digitalDegree; } string second = degrees.Substring(m + 1, s - m - 1); digitalDegree += (Convert.ToDouble(second) / (num * num)); return digitalDegree; } #endregion }
上面是度分秒转度
下面是几个坐标互转
1 /* ---------------------------------------------------------- 2 * 文件名称:MapConverter.cs 3 * 4 * 开发环境: 5 * Visual Studio V2017 6 * 7 * 版本历史: 8 * V1.0 2017年05月16日 9 * 坐标转换器 10 * 11 * 说明: 12 * WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。 13 * GCJ02:又称火星坐标系,是由中国国家测绘局制定的地理坐标系统,是由WGS84加密后得到的坐标系。 14 * BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标。 15 * 16 * 参考资料: 17 ------------------------------------------------------------ */ 18 /// <summary> 19 /// WGS-84、GCJ-02(火星坐标系)、BD-09(百度坐标系)之间的坐标转换器 20 /// </summary> 21 public static class MapConverter 22 { 23 /// <summary> 24 /// 圆周率 25 /// </summary> 26 private const double PI = 3.1415926535897932384626; 27 private const double X_PI = PI * 3000.0 / 180.0; 28 29 /// <summary> 30 /// 地理位置是否位于中国以外 31 /// </summary> 32 /// <param name="wgLat">WGS-84坐标纬度</param> 33 /// <param name="wgLon">WGS-84坐标经度</param> 34 /// <returns> 35 /// true:国外 36 /// false:国内 37 /// </returns> 38 public static bool OutOfChina(double wgLat, double wgLon) 39 { 40 if (wgLon < 72.004 || wgLon > 137.8347) return true; 41 if (wgLat < 0.8293 || wgLat > 55.8271) return true; 42 43 return false; 44 } 45 46 /// <summary> 47 /// WGS-84坐标系转火星坐标系 (GCJ-02) 48 /// </summary> 49 /// <param name="wgLat">WGS-84坐标纬度</param> 50 /// <param name="wgLon">WGS-84坐标经度</param> 51 /// <param name="mgLat">输出:GCJ-02坐标纬度</param> 52 /// <param name="mgLon">输出:GCJ-02坐标经度</param> 53 public static void WGS84ToGCJ02(double wgLat, double wgLon, out double mgLat, out double mgLon) 54 { 55 if (OutOfChina(wgLat, wgLon)) 56 { 57 mgLat = wgLat; 58 mgLon = wgLon; 59 } 60 else 61 { 62 double dLat; 63 double dLon; 64 Delta(wgLat, wgLon, out dLat, out dLon); 65 mgLat = wgLat + dLat; 66 mgLon = wgLon + dLon; 67 } 68 } 69 70 /// <summary> 71 /// 火星坐标系 (GCJ-02)转WGS-84坐标系 72 /// </summary> 73 /// <param name="mgLat">GCJ-02坐标纬度</param> 74 /// <param name="mgLon">GCJ-02坐标经度</param> 75 /// <param name="wgLat">输出:WGS-84坐标纬度</param> 76 /// <param name="wgLon">输出:WGS-84坐标经度</param> 77 public static void GCJ02ToWGS84(double mgLat, double mgLon, out double wgLat, out double wgLon) 78 { 79 if (OutOfChina(mgLat, mgLon)) 80 { 81 wgLat = mgLat; 82 wgLon = mgLon; 83 } 84 else 85 { 86 double dLat; 87 double dLon; 88 Delta(mgLat, mgLon, out dLat, out dLon); 89 wgLat = mgLat - dLat; 90 wgLon = mgLon - dLon; 91 } 92 } 93 94 /// <summary> 95 /// 火星坐标系 (GCJ-02)转WGS-84坐标系 96 /// </summary> 97 /// <param name="mgLat">GCJ-02坐标纬度</param> 98 /// <param name="mgLon">GCJ-02坐标经度</param> 99 /// <param name="wgLat">输出:WGS-84坐标纬度</param> 100 /// <param name="wgLon">输出:WGS-84坐标经度</param> 101 public static void GCJ02ToWGS84Exact(double mgLat, double mgLon, out double wgLat, out double wgLon) 102 { 103 const double InitDelta = 0.01; 104 const double Threshold = 0.000001; 105 106 double dLat = InitDelta; 107 double dLon = InitDelta; 108 double mLat = mgLat - dLat; 109 double mLon = mgLon - dLon; 110 double pLat = mgLat + dLat; 111 double pLon = mgLon + dLon; 112 113 double nLat; 114 double nLon; 115 116 int i = 0; 117 do 118 { 119 wgLat = (mLat + pLat) / 2; 120 wgLon = (mLon + pLon) / 2; 121 122 WGS84ToGCJ02(wgLat, wgLon, out nLat, out nLon); 123 124 dLat = nLat - mgLat; 125 dLon = nLon - mgLon; 126 if ((Math.Abs(dLat) < Threshold) && (Math.Abs(dLon) < Threshold)) break; 127 128 if (dLat > 0) pLat = wgLat; else mLat = wgLat; 129 if (dLon > 0) pLon = wgLon; else mLon = wgLon; 130 } while (++i <= 30); 131 } 132 133 /// <summary> 134 /// 百度坐标系 (BD-09)转火星坐标系 (GCJ-02) 135 /// </summary> 136 /// <param name="bdLat">百度坐标系纬度</param> 137 /// <param name="bdLon">百度坐标系经度</param> 138 /// <param name="mgLat">输出:GCJ-02坐标纬度</param> 139 /// <param name="mgLon">输出:GCJ-02坐标经度</param> 140 public static void BD09ToGCJ02(double bdLat, double bdLon, out double mgLat, out double mgLon) 141 { 142 double x = bdLon - 0.0065; 143 double y = bdLat - 0.006; 144 double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * X_PI); 145 double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * X_PI); 146 mgLat = z * Math.Sin(theta); 147 mgLon = z * Math.Cos(theta); 148 } 149 150 /// <summary> 151 /// 火星坐标系 (GCJ-02)转百度坐标系 (BD-09) 152 /// </summary> 153 /// <param name="mgLat">GCJ-02坐标纬度</param> 154 /// <param name="mgLon">GCJ-02坐标经度</param> 155 /// <param name="bdLat">输出:百度坐标系纬度</param> 156 /// <param name="bdLon">输出:百度坐标系经度</param> 157 public static void GCJ02ToBD09(double mgLat, double mgLon, out double bdLat, out double bdLon) 158 { 159 double x = mgLon; 160 double y = mgLat; 161 double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * X_PI); 162 double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * X_PI); 163 bdLat = z * Math.Sin(theta) + 0.006; 164 bdLon = z * Math.Cos(theta) + 0.0065; 165 } 166 167 /// <summary> 168 /// WGS-84坐标系转百度坐标系 (BD-09) 169 /// </summary> 170 /// <param name="wgLat">WGS-84坐标纬度</param> 171 /// <param name="wgLon">WGS-84坐标经度</param> 172 /// <param name="bdLat">输出:百度坐标系纬度</param> 173 /// <param name="bdLon">输出:百度坐标系经度</param> 174 public static void WGS84ToBD09(double wgLat, double wgLon, out double bdLat, out double bdLon) 175 { 176 double mgLat; 177 double mgLon; 178 179 WGS84ToGCJ02(wgLat, wgLon, out mgLat, out mgLon); 180 GCJ02ToBD09(mgLat, mgLon, out bdLat, out bdLon); 181 } 182 183 /// <summary> 184 /// 百度坐标系 (BD-09)转WGS-84坐标系 185 /// </summary> 186 /// <param name="bdLat">百度坐标系纬度</param> 187 /// <param name="bdLon">百度坐标系经度</param> 188 /// <param name="wgLat">输出:WGS-84坐标纬度</param> 189 /// <param name="wgLon">输出:WGS-84坐标经度</param> 190 public static void BD09ToWGS84(double bdLat, double bdLon, out double wgLat, out double wgLon) 191 { 192 double mgLat; 193 double mgLon; 194 195 BD09ToGCJ02(bdLat, bdLon, out mgLat, out mgLon); 196 GCJ02ToWGS84(mgLat, mgLon, out wgLat, out wgLon); 197 } 198 199 public static double Distance(double LatA, double LonA, double LatB, double LonB) 200 { 201 const double EarthR = 6371000.0; 202 203 double x = Math.Cos(LatA * PI / 180.0) * Math.Cos(LatB * PI / 180.0) * Math.Cos((LonA - LonB) * PI / 180); 204 double y = Math.Sin(LatA * PI / 180.0) * Math.Sin(LatB * PI / 180.0); 205 double s = x + y; 206 if (s > 1) s = 1; 207 if (s < -1) s = -1; 208 209 return Math.Acos(s) * EarthR; 210 } 211 212 private static void Delta(double Lat, double Lon, out double dLat, out double dLon) 213 { 214 const double AXIS = 6378245.0; 215 const double EE = 0.00669342162296594323; 216 217 dLat = TransformLat(Lon - 105.0, Lat - 35.0); 218 dLon = TransformLon(Lon - 105.0, Lat - 35.0); 219 double radLat = Lat / 180.0 * PI; 220 double magic = Math.Sin(radLat); 221 magic = 1 - EE * magic * magic; 222 double sqrtMagic = Math.Sqrt(magic); 223 dLat = (dLat * 180.0) / ((AXIS * (1 - EE)) / (magic * sqrtMagic) * PI); 224 dLon = (dLon * 180.0) / (AXIS / sqrtMagic * Math.Cos(radLat) * PI); 225 } 226 227 private static double TransformLat(double x, double y) 228 { 229 double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x)); 230 ret += (20.0 * Math.Sin(6.0 * x * PI) + 20.0 * Math.Sin(2.0 * x * PI)) * 2.0 / 3.0; 231 ret += (20.0 * Math.Sin(y * PI) + 40.0 * Math.Sin(y / 3.0 * PI)) * 2.0 / 3.0; 232 ret += (160.0 * Math.Sin(y / 12.0 * PI) + 320 * Math.Sin(y * PI / 30.0)) * 2.0 / 3.0; 233 return ret; 234 } 235 236 private static double TransformLon(double x, double y) 237 { 238 double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x)); 239 ret += (20.0 * Math.Sin(6.0 * x * PI) + 20.0 * Math.Sin(2.0 * x * PI)) * 2.0 / 3.0; 240 ret += (20.0 * Math.Sin(x * PI) + 40.0 * Math.Sin(x / 3.0 * PI)) * 2.0 / 3.0; 241 ret += (150.0 * Math.Sin(x / 12.0 * PI) + 300.0 * Math.Sin(x / 30.0 * PI)) * 2.0 / 3.0; 242 return ret; 243 } 244 }
经纬度计算完了以后就是距离计算代码
public class LocationUtil { ///// <summary> /////计算两点GPS坐标的距离(单位:米) ///// </summary> ///// <param name="n1">第一点的纬度坐标</param> ///// <param name="e1">第一点的经度坐标</param> ///// <param name="n2">第二点的纬度坐标</param> ///// <param name="e2">第二点的经度坐标</param> //public static double Distance(double n1, double e1, double n2, double e2) //{ // double jl_jd = 102834.74258026089786013677476285;//每经度单位米; // double jl_wd = 111712.69150641055729984301412873;//每纬度单位米; // double b = Math.Abs((e1 - e2) * jl_jd); // double a = Math.Abs((n1 - n2) * jl_wd); // return Math.Sqrt((a * a + b * b)); //} ///// <summary> ///// 获取维度差 ///// </summary> ///// <param name="km">千米</param> //public static double GetLatitudeDifference(double km) //{ // return km * (1d / 111d); //} ///// <summary> ///// 获取经度差 ///// </summary> ///// <param name="km">千米</param> //public static double GetLongitudeDifference(double km, double latitude) //{ // return km * (1d / (111d * Math.Cos(latitude))); //} private const double EARTH_RADIUS = 6378.137; //地球半径 private static double Rad(double d) { return d * Math.PI / 180.0; } public static double Distance(double lat1, double lng1, double lat2, double lng2) { double radLat1 = Rad(lat1); double radLat2 = Rad(lat2); double a = radLat1 - radLat2; double b = Rad(lng1) - Rad(lng2); double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2))); s = s * EARTH_RADIUS; s = Math.Round(s * 10000) / 10000; return s; } }