欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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