python 地图纠偏/坐标系转换

一、为什么用数据画出来的路线图有偏差?

国家安全与地图保密,对真实坐标系统进行人为的加偏处理,将坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。加偏之后会使别的国家看不懂我们的坐标系统。
来源: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

你可能感兴趣的:(python 地图纠偏/坐标系转换)