一、
1、計算兩點之間球面距離
matlab版
function [dist] = computeDistanceLatLon(lon1,lat1,lon2,lat2)
pi = 3.14159265358979324;
Rc = 6378137.0;
Rj = 6356725.0;
DEG2RAD = pi / 180.0;
r_lat_1 = lat1 * DEG2RAD;
r_lng_1 = lon1 * DEG2RAD;
r_lat_2 = lat2 * DEG2RAD;
r_lng_2 = lon2 * DEG2RAD;
Ec = Rj + (Rc - Rj) * (90.0 - lat1) / 90.0;
Ed = Ec * cos(r_lat_1);
dx = (r_lng_2 - r_lng_1) * Ed;
dy = (r_lat_2 - r_lat_1) * Ec;
dist = sqrt(dx * dx + dy * dy);
end
pyhton 版
import math
def computeDistanceLatLon(lon1,lat1,lon2,lat2):
pi = 3.14159265358979324
Rc = 6378137.0
Rj = 6356725.0
DEG2RAD = pi / 180.0
r_lat_1 = lat1 * DEG2RAD
r_lng_1 = lon1 * DEG2RAD
r_lat_2 = lat2 * DEG2RAD
r_lng_2 = lon2 * DEG2RAD
Ec = Rj + (Rc - Rj) * (90.0 - lat1) / 90.0
Ed = Ec * math.cos(r_lat_1)
dx = (r_lng_2 - r_lng_1) * Ed
dy = (r_lat_2 - r_lat_1) * Ec
return math.sqrt(dx * dx + dy * dy)
C++版
void calculate_dist_m(vector<double> &dist, double lon_a, double lat_a, double lon_b, double lat_b) {
if ((int)dist.size() != 3) {
dist.resize(3);
}
double lng1, lat1, lng2, lat2;
lng1 = lon_a;
lng2 = lon_b;
lat1 = lat_a;
lat2 = lat_b;
const double Rc = 6378137.0;
const double Rj = 6356725.0;
const double DEG2RAD = M_PI / 180.0;
double r_lat_1 = lat1 * DEG2RAD;
double r_lng_1 = lng1 * DEG2RAD;
double r_lat_2 = lat2 * DEG2RAD;
double r_lng_2 = lng2 * DEG2RAD;
double Ec = Rj + (Rc - Rj) * (90.0 - lat1) / 90.0;
double Ed = Ec * cos(r_lat_1);
dist[0] = ((r_lng_2 - r_lng_1) * Ed);
dist[1] = ((r_lat_2 - r_lat_1) * Ec);
dist[2] = sqrt(dist[0] * dist[0] + dist[1] * dist[1]);
}
經驗公式版
dist = 111120*((lon1-lon2)^2+(lat1-lat2)^2)^0.5
二、
經緯度座標轉換
1、WGS84-GCJ02互轉
import math
# GCJ座標與WGS座標互轉
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626
a = 6378245.0
ee = 0.00669342162296594323
def out_of_china(lng, lat):
return not (lng > 73.66 and lng < 135.05 and lat > 3.86 and lat < 53.55)
def _transformlng(lng, lat):
ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
math.sin(2.0 * lng * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(lng * pi) + 40.0 *
math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
return ret
def _transformlat(lng, lat):
ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
math.sin(2.0 * lng * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(lat * pi) + 40.0 *
math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
math.sin(lat * pi / 30.0)) * 2.0 / 3.0
return ret
def wgs84_to_gcj02(lng, lat):
if out_of_china(lng, lat):
return [lng, lat]
dlat = _transformlat(lng - 105.0, lat - 35.0)
dlng = _transformlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
mglat = lat + dlat
mglng = lng + dlng
return [mglng, mglat]
def gcj02_to_wgs84(lng, lat):
if out_of_china(lng, lat):
return [lng, lat]
dlat = _transformlat(lng - 105.0, lat - 35.0)
dlng = _transformlng(lng - 105.0, lat - 35.0)
radlat = lat / 180.0 * pi
magic = math.sin(radlat)
magic = 1 - ee * magic * magic
sqrtmagic = math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
mglat = lat + dlat
mglng = lng + dlng
return [lng * 2 - mglng, lat * 2 - mglat]
C 版:
int outOfChina(double lat, double lon)
{
if (lon < 72.004 || lon > 137.8347)
return 1;
if (lat < 0.8293 || lat > 55.8271)
return 1;
return 0;
}
double transformLat(double x, double y)
{
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(x > 0 ? x:-x);
ret += (20.0 * sin(6.0 * x * pi) + 20.0 *sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * sin(y * pi) + 40.0 * sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * sin(y / 12.0 * pi) + 320 * sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
double transformLon(double x, double y)
{
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(x > 0 ? x:-x);
ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * sin(x * pi) + 40.0 * sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * sin(x / 12.0 * pi) + 300.0 * sin(x / 30.0 * pi)) * 2.0 / 3.0;
return ret;
}
Location_t transformFromWGSToGCJ(Location_t wgLoc)
{
Location_t mgLoc;
if (outOfChina(wgLoc.lat, wgLoc.lng))
{
mgLoc = wgLoc;
return mgLoc;
}
double dLat = transformLat(wgLoc.lng - 105.0, wgLoc.lat - 35.0);
double dLon = transformLon(wgLoc.lng - 105.0, wgLoc.lat - 35.0);
double radLat = wgLoc.lat / 180.0 * pi;
double magic = sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * pi);
mgLoc.lat = wgLoc.lat + dLat;
mgLoc.lng = wgLoc.lng + dLon;
return mgLoc;
}
Location_t transformFromGCJToWGS(Location_t gcLoc)
{
Location_t wgLoc = gcLoc;
Location_t currGcLoc, dLoc;
while (1) {
currGcLoc = transformFromWGSToGCJ(wgLoc);
dLoc.lat = gcLoc.lat - currGcLoc.lat;
dLoc.lng = gcLoc.lng - currGcLoc.lng;
if (fabs(dLoc.lat) < 1e-7 && fabs(dLoc.lng) < 1e-7) {
return wgLoc;
}
wgLoc.lat += dLoc.lat;
wgLoc.lng += dLoc.lng;
}
return wgLoc;
}
2、WGS84與墨卡託座標系轉換
部分更復雜的計算可以參考: