python 地图纠偏/坐标系转换
程序员文章站
2022-07-02 08:34:20
...
一、为什么用数据画出来的路线图有偏差?
国家安全与地图保密,对真实坐标系统进行人为的加偏处理,将坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。加偏之后会使别的国家看不懂我们的坐标系统。
来源:http://yanue.net/post-121.html
二、几种坐标系统
- WGS84坐标系:即地球坐标系,国际上通用的坐标系。
- GCJ02坐标系:即火星坐标系,WGS84坐标系经加密后的坐标系。
- BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系。
来源:https://www.cnblogs.com/gispathfinder/p/5778774.html
三、几种坐标系的转换
import math
pi=math.pi
axis=6378245.0
offset=0.00669342162296594323
x_pi=pi*3000.0/180.0
def gcj2_BD9(glat,glon):#GCJ-02=>BD09 火星坐标系=>百度坐标系
latlon=[]
z=math.sqrt(glon*glon+glat*glat)+0.00002*math.sin(glat*x_pi)
theta=math.atan2(glat,glon)+ 0.000003 * math.cos(glon*x_pi)
latlon.append( z * math.sin(theta) + 0.006)
latlon.append(z * math.cos(theta) + 0.0065)
return latlon
def bd092GCJ(glat,glon):#BD09=>GCJ-02 百度坐标系=>火星坐标系
x = glon - 0.0065
y = glat - 0.006
latlon=[]
z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * x_pi)
theta = math.atan2(y, x) - 0.000003 * math.cos(x * x_pi)
latlon.append(z * math.sin(theta))
latlon.append(z * math.cos(theta))
return latlon
def bd092WGS(glat,glon):#BD09 = > WGS84百度坐标系 = > 地球坐标系
latlon = bd092GCJ(glat, glon)
return gcj2WGS(latlon[0], latlon[1])
def wgs2BD09(wgLat,wgLon):#WGS84 =》BD09地球坐标系 = > 百度坐标系
latlon = wgs2GCJ(wgLat, wgLon)
return gcj2_BD9(latlon[0], latlon[1])
def wgs2GCJ(wgLat,wgLon):#WGS84 =》GCJ02地球坐标系 = > 火星坐标系
latlon = []
if (outOfChina(wgLat, wgLon)):
latlon.append(wgLat)
latlon.append(wgLon)
return latlon
deltaD = delta(wgLat, wgLon)
latlon.append(wgLat + deltaD[0])
latlon.append(wgLon + deltaD[1])
return latlon
def gcj2WGS(glat,glon):#GCJ02 = > WGS84火星坐标系 = > 地球坐标系(粗略)
latlon = [0,0]
if (outOfChina(glat, glon)):
latlon[0] = glat
latlon[1] = glon
return latlon
deltaD = delta(glat, glon)
latlon[0] = glat - deltaD[0]
latlon[1] = glon - deltaD[1]
return latlon
def gcj2WGSExactly(gcjLat,gcjLon):#GCJ02 = > WGS84火星坐标系 = > 地球坐标系(精确)
initDelta = 0.01
threshold = 0.000000001
dLat = initDelta
dLon = initDelta
mLat = gcjLat - dLat
mLon = gcjLon - dLon
pLat = gcjLat + dLat
pLon = gcjLon + dLon
wgsLat=wgsLon=i=0
while (True) :
wgsLat = (mLat + pLat) / 2
wgsLon = (mLon + pLon) / 2
tmp = wgs2GCJ(wgsLat, wgsLon)
dLat = tmp[0] - gcjLat
dLon = tmp[1] - gcjLon
if ((math.fabs(dLat) < threshold)and(math.fabs(dLon) < threshold)):
break
if (dLat > 0):
pLat = wgsLat
if(dLat<=0):
mLat = wgsLat
if (dLon > 0):
pLon = wgsLon
if(dLon<=0):
mLon = wgsLon
if (i+1 > 10000):
break
latlon = [0,0]
latlon[0] = wgsLat
latlon[1] = wgsLon
return latlon
def distance(latA,logA, latB, logB):
earthR = 6371000
x = math.cos(latA * math.pi / 180) * math.cos(latB * math.pi / 180) * math.cos((logA - logB) * math.pi / 180)
y = math.sin(latA * math.pi / 180) * math.sin(latB * math.pi / 180)
s = x + y
if (s > 1):
s = 1
if (s < -1):
s = -1
alpha = math.acos(s)
distance = alpha * earthR
return distance
def delta(wgLat,wgLon):
latlng =[0,0]
dLat = transformLat(wgLon - 105.0, wgLat - 35.0)
dLon = transformLon(wgLon - 105.0, wgLat - 35.0)
radLat = wgLat / 180.0 * pi
magic = math.sin(radLat)
magic = 1 - offset * magic * magic
sqrtMagic = math.sqrt(magic)
dLat = (dLat * 180.0) / (axis * (1 - offset)/ (magic * sqrtMagic) * pi)
dLon = (dLon * 180.0) / (axis / sqrtMagic * math.cos(radLat) * pi)
latlng[0] = dLat
latlng[1] = dLon
return latlng
def outOfChina(lat,lon):
if (lon < 72.004 or lon > 137.8347):
return True
if (lat < 0.8293 or lat > 55.8271):
return True
return False
def transformLat(x,y):
ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(math.fabs(x))
ret += (20.0 * math.sin(6.0 * x * pi) + 20.0 * math.sin(2.0 * x * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(y * pi) + 40.0 * math.sin(y / 3.0 * pi)) * 2.0 / 3.0
ret += (160.0 * math.sin(y / 12.0 * pi) + 320 * math.sin(y * pi / 30.0)) * 2.0 / 3.0
return ret
def transformLon(x,y):
ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(math.fabs(x))
ret += (20.0 * math.sin(6.0 * x * pi) + 20.0 * math.sin(2.0 * x * pi)) * 2.0 / 3.0
ret += (20.0 * math.sin(x * pi) + 40.0 * math.sin(x / 3.0 * pi)) * 2.0 / 3.0
ret += (150.0 * math.sin(x / 12.0 * pi) + 300.0 * math.sin(x / 30.0 * pi)) * 2.0 / 3.0
return ret