特别注意:
網上有根據以下公式計算經緯度坐标的方法,實際上是錯誤的,這個d隻能在111.12和-111.12之間
以下包含四種C#實現方法,地球半徑不統一,從精确度上推薦使用【方法一】,注意參數的經緯度順序
地球平均半徑 :6371.004千米
地球赤道半徑 :6378.140千米
航天使用的經過拟合的地球半徑為:6378.137千米
方法一:
/// <summary> /// 從兩個gps坐标點(經緯度)獲得兩點的直線距離,谷歌和高德地圖的計算方式 /// </summary> /// <param name="dLati1">第一個點的緯度</param> /// <param name="dLong1">第一個點的經度</param> /// <param name="dLati2">第二個點的緯度</param> /// <param name="dLong2">第二個點的經度</param> /// <returns>單位是米</returns> publicdoublegetDistanceGD(doubledLati1, doubledLong1, doubledLati2, doubledLong2) {
|
/// <summary> /// 從兩個gps坐标點(經緯度)獲得兩點的直線距離,百度地圖的計算方式(JS代碼修改而來,可能不精準),參數依次為A點的經度、A點的緯度、B點的經度、B點的緯度 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <param name="c"></param> /// <param name="d"></param> /// <returns></returns> publicdoublegetDistanceBD(doublea, doubleb, doublec, doubled) { if(a < 0 || b < 0 || c < 0 || d < 0) return0; a = fD(a, -180, 180); b = jD(b, -74, 74); c = fD(c, -180, 180); d = jD(d, -74, 74); returnCe(yk(a), yk(c), yk(b), yk(d)); } privatedoublefD(doublea, doubleb, doublec) { for(; a > c;) a -= c - b; for(; a < b;) a = c - b; returna; } privatedoublejD(doublea, doubleb, doublec) { //JS代碼 //b != null && (a = Math.Max(a, b)); //c != null && (a = Math.Min(a, c)); //C#代碼 if(b > 0) { a = Math.Max(a, b); } if(c > 0) { a = Math.Min(a, c); } returna; } privatedoubleyk(doublea) { returnMath.PI * a / 180; } privatedoubleCe(doublea, doubleb, doublec, doubled) { doubledO = 6370996.81; //double dO = 6378137.0; returndO * Math.Acos(Math.Sin(c) * Math.Sin(d) Math.Cos(c) * Math.Cos(d) * Math.Cos(b - a)); } |
//對應的JS代碼 functionfD(a, b, c) { for(; a > c;) a -= c - b; for(; a < b;) a = c - b; returna; }; functionjD(a, b, c) { b != null&& (a = Math.max(a, b)); c != null&& (a = Math.min(a, c)); returna; }; functionyk(a) { returnMath.PI * a / 180 }; functionCe(a, b, c, d) { vardO = 6370996.81; returndO * Math.acos(Math.sin(c) * Math.sin(d) Math.cos(c) * Math.cos(d) * Math.cos(b - a)); }; functiongetDistance(a, b) { if(!a || !b) return0; a.lng = fD(a.lng, -180, 180); a.lat = jD(a.lat, -74, 74); b.lng = fD(b.lng, -180, 180); b.lat = jD(b.lat, -74, 74); returnCe(yk(a.lng), yk(b.lng), yk(a.lat), yk(b.lat)); }; alert(getDistance({lng : 106.486654, lat: 29.490295},{lng : 106.581515,lat :29.615467})); |
方法三:
/// <summary> ///計算兩點GPS坐标的距離,複雜度較低 /// </summary> /// <param name="n1">第一點的緯度坐标</param> /// <param name="e1">第一點的經度坐标</param> /// <param name="n2">第二點的緯度坐标</param> /// <param name="e2">第二點的經度坐标</param> /// <returns></returns> publicdoubleDistance(doublen1, doublee1, doublen2, doublee2) { doublejl_jd = 102834.74258026089786013677476285; doublejl_wd = 111712.69150641055729984301412873; doubleb = Math.Abs((e1 - e2) * jl_jd); doublea = Math.Abs((n1 - n2) * jl_wd); returnMath.Sqrt((a * a b * b)); } |
方法四:
staticdoubleDEF_PI = 3.14159265359; // PI staticdoubleDEF_2PI = 6.28318530712; // 2*PI staticdoubleDEF_PI180 = 0.01745329252; // PI/180.0 staticdoubleDEF_R = 6370693.5; // radius of earth /// <summary> /// 從兩個gps坐标點(經緯度)獲得兩點的直線距離,适用于計算短程距離 /// </summary> /// <param name="lon1">第一個點的經度</param> /// <param name="lat1">第一個點的緯度</param> /// <param name="lon2">第二個點的經度</param> /// <param name="lat2">第二個點的緯度</param> /// <returns>單位是米</returns> publicdoubleGetShortDistance(doublelon1, doublelat1, doublelon2, doublelat2) { doubleew1, ns1, ew2, ns2; doubledx, dy, dew; doubledistance; // 角度轉換為弧度 ew1 = lon1 * DEF_PI180; ns1 = lat1 * DEF_PI180; ew2 = lon2 * DEF_PI180; ns2 = lat2 * DEF_PI180; // 經度差 dew = ew1 - ew2; // 若跨東經和西經180 度,進行調整 if(dew > DEF_PI) dew = DEF_2PI - dew; elseif(dew < -DEF_PI) dew = DEF_2PI dew; dx = DEF_R * Math.Cos(ns1) * dew; // 東西方向長度(在緯度圈上的投影長度) dy = DEF_R * (ns1 - ns2); // 南北方向長度(在經度圈上的投影長度) // 勾股定理求斜邊長 distance = Math.Sqrt(dx * dx dy * dy); returndistance; } /// <summary> /// 從兩個gps坐标點(經緯度)獲得兩點的直線距離,适用于計算長程距離 /// </summary> /// <param name="lon1">第一個點的經度</param> /// <param name="lat1">第一個點的緯度</param> /// <param name="lon2">第二個點的經度</param> /// <param name="lat2">第二個點的緯度</param> /// <returns>單位是米</returns> publicdoubleGetLongDistance(doublelon1, doublelat1, doublelon2, doublelat2) { doubleew1, ns1, ew2, ns2; doubledistance; // 角度轉換為弧度 ew1 = lon1 * DEF_PI180; ns1 = lat1 * DEF_PI180; ew2 = lon2 * DEF_PI180; ns2 = lat2 * DEF_PI180; // 求大圓劣弧與球心所夾的角(弧度) distance = Math.Sin(ns1) * Math.Sin(ns2) Math.Cos(ns1) * Math.Cos(ns2) * Math.Cos(ew1 - ew2); // 調整到[-1..1]範圍内,避免溢出 if(distance > 1.0) distance = 1.0; elseif(distance < -1.0) distance = -1.0; // 求大圓劣弧長度 distance = DEF_R * Math.Acos(distance); returndistance; } |
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!