zoukankan      html  css  js  c++  java
  • 百度和谷歌的逆地址解析及GPS、谷歌地图和百度地图坐标之间的转换(python版)

    PostGis用函数转换之后的4326坐标为GPS坐标,这个坐标不能直接在谷歌maps的API上面直接使用需要经过上面的转换,因为谷歌地图的国内参考坐标系为GCJ-02,而一般GPS为WGS84的坐标系。而且同一坐标百度和谷歌API逆向地址解析之后的结果不一致,这个需要后续验证:

    谷歌:https://maps.googleapis.com/maps/api/geocode/json?latlng=23.082373643343487,113.69356554583203&key=${yourkey}&language=zh-CN

    百度:http://api.map.baidu.com/geocoder/v2/?location=lat,lon&output=json&ak=${yourkey}&extensions_road=ture&latest_admin=1&coordtype=wgs84

    如果不能翻墙谷歌的话替换maps.googleapis.com为ditu.google.cn。

    下面为code:

    def get_street_baidu(lat_gps, lng_gps):
        # 输入gps坐标,逆地址解析返回百度地图地址信息
        try:
            url = 'http://api.map.baidu.com/geocoder/v2/?&' 
                  'location=' + str(lat_gps) + ',' + str(lng_gps) + 
                  '&output=json&ak=${yourkey}&extensions_road=ture&coordtype=wgs84ll'
            response = urllib.urlopen(url)
            string = response.read()
            json_data = json.loads(string, encoding='utf8')
            if 'result' in json_data.keys():
                result = json_data['result']
                street = result['addressComponent']['street']
            else:
                street = None
        except Exception as e:
            print(e.message)
        return street
    
    
    def get_street_google(lat, lng):
        # 输入GPS坐标,返回逆地址解析谷歌地图地址,GPS坐标需要转换成谷歌地图坐标
        try:
            url = 'https://ditu.google.cn/maps/api/geocode/json?latlng=' + 
                  str(lat) + ',' + str(lng) + 
                  '&key=${yourkey}&language=zh-CN'
            response = urllib.urlopen(url)
            string = response.read()
            json_data = json.loads(string, encoding='utf8')
            if 'results' in json_data.keys():
                result = json_data['results']
                street = result[0]['address_components'][0]['long_name']
            else:
                street = None
        except Exception as e:
            print(e.message)
        return street

    转换坐标函数code:

    #!/usr/bin/env python
    # coding:utf-8
    # @author: KaiVen
    """
    GPS坐标转换:
    WGS-84:是国际标准,GPS坐标(Google Earth使用、或者GPS模块)
    GCJ-02:中国坐标偏移标准,Google Map、高德、腾讯使用
    BD-09:百度坐标偏移标准,Baidu Map使用
    """
    
    import math
    
    
    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(abs(x))
        ret += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0
        ret += (20.0 * math.sin(y * math.pi) + 40.0 * math.sin(y / 3.0 * math.pi)) * 2.0 / 3.0
        ret += (160.0 * math.sin(y / 12.0 * math.pi) + 320 * math.sin(y * math.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(abs(x))
        ret += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0
        ret += (20.0 * math.sin(x * math.pi) + 40.0 * math.sin(x / 3.0 * math.pi)) * 2.0 / 3.0
        ret += (150.0 * math.sin(x / 12.0 * math.pi) + 300.0 * math.sin(x / 30.0 * math.pi)) * 2.0 / 3.0
        return ret
    
    
    def delta(lat, lng):
        a = 6378245.0
        # a: 卫星椭球坐标投影到平面地图坐标系的投影因子
        ee = 0.00669342162296594323
        # ee: 椭球的偏心率
        dLat = transformLat(lng - 105.0, lat - 35.0)
        dLon = transformLon(lng - 105.0, lat - 35.0)
        radLat = lat / 180.0 * math.pi
        magic = math.sin(radLat)
        magic = 1 - ee * magic * magic
        sqrtMagic = math.sqrt(magic)
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * math.pi)
        dLon = (dLon * 180.0) / (a / sqrtMagic * math.cos(radLat) * math.pi)
        return dLat, dLon
    
    
    def wgs2gcj(wgsLat, wgsLng):
        """
        WGS-84转成GCJ-02
        """
        if outOfChina(wgsLat, wgsLng):
            print("The latitude or longitude is out of China!")
            return wgsLat, wgsLng
        lat, lng = delta(wgsLat, wgsLng)
        return wgsLat + lat, wgsLng + lng
    
    
    def gcj2wgs_rough(gcjLat, gcjLon):
        """
        GCJ-02 转 WGS-84 粗略版
        """
        if outOfChina(gcjLat, gcjLon):
            print("The latitude or longitude is out of China!")
            return gcjLat, gcjLon
        lat, lng = delta(gcjLat, gcjLon)
        return gcjLat - lat, gcjLon - lng
    
    
    def gcj2wgs_accurate(gcjLat, gcjLon):
        """
        GCJ-02 转 WGS-84 精确版
        """
        initDelta = 0.01
        threshold = 0.000000001
        dLat = initDelta
        dLon = initDelta
        mLat = gcjLat - dLat
        mLon = gcjLon - dLon
        pLat = gcjLat + dLat
        pLon = gcjLon + dLon
        wgsLat = 0
        wgsLon = 0
        i = 0
        while 1:
            wgsLat = (mLat + pLat) / 2
            wgsLon = (mLon + pLon) / 2
            lat, lon = gcj2wgs_rough(wgsLat, wgsLon)
            dLat = lat - gcjLat
            dLon = lon - gcjLon
            if (abs(dLat) < threshold) and (abs(dLon) < threshold):
                break
            if dLat > 0:
                pLat = wgsLat
            else:
                mLat = wgsLat
            if dLon > 0:
                pLon = wgsLon
            else:
                mLon = wgsLon
            if ++i > 10000:
                break
        return wgsLat, wgsLon
    
    
    def gcj2bd(gcjLat, gcjLon):
        """
        GCJ-02 转 BD-09
        """
        x_pi = math.pi * 3000.0 / 180.0
        x = gcjLon
        y = gcjLat
        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)
        bdLon = z * math.cos(theta) + 0.0065
        bdLat = z * math.sin(theta) + 0.006
        return bdLat, bdLon
    
    
    def bd2gcj(bdLat, bdLon):
        """
        BD-09 转 GCJ-02
        """
        x_pi = math.pi * 3000.0 / 180.0
        x = bdLon - 0.0065
        y = bdLat - 0.006
        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)
        gcjLon = z * math.cos(theta)
        gcjLat = z * math.sin(theta)
        return gcjLat, gcjLon
    
    
    def wgs2mercator(wgsLat, wgsLon):
        """
        WGS-84 to Web mercator
        mercatorLat -> y mercatorLon -> x
        """
        x = wgsLon * 20037508.34 / 180.
        y = math.log(math.tan((90. + wgsLat) * math.pi / 360)) / (math.pi / 180)
        y = y * 20037508.34 / 180.
        return y, x
    
    
    def mercator2wgs(mercatorLat, mercatorLon):
        """
        Web mercator to WGS-84
        mercatorLat -> y mercatorLon -> x
        """
        x = mercatorLon / 20037508.34 * 180
        y = mercatorLat / 20037508.34 * 180
        y = 180 / math.pi * (2 * math.atan(math.exp(y * math.pi / 180.)) - math.pi / 2)
        return y, x
    
    
    def outOfChina(lat, lng):
        """
        判断是否在中国范围外
        """
        if lng < 72.004 or lng > 137.8347:
            return True
        if lat < 0.8293 or lat > 55.8271:
            return True
        return False
    
    
    def haversine(lat1, lon1, lat2, lon2):
        """
        :param: 纬度1,经度1,纬度2,经度2(十进制度数)
        :return: 二个坐标之间的距离(单位米)
        Calculate the great circle distance between two points
        on the earth (specified in decimal degrees)
        """
        # 将十进制度数转化为弧度
        lat1, lon1, lat2, lon2 = map(math.radians, [lat1, lon1, lat2, lon2])
        # haversine公式
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = math.sin(dlat / 2) ** 2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2
        c = 2 * math.asin(math.sqrt(a))
        r = 6371  # 地球平均半径,单位为公里
        return c * r * 1000

    坐标转换参考:https://www.oschina.net/code/snippet_260395_39205

  • 相关阅读:
    mysql BETWEEN操作符 语法
    mysql IN操作符 语法
    mysql LIKE通配符 语法
    mysql TOP语句 语法
    mysql DELETE语句 语法
    mysql Update语句 语法
    mysql INSERT语句 语法
    mysql ORDER BY语句 语法
    mysql OR运算符 语法
    mysql AND运算符 语法
  • 原文地址:https://www.cnblogs.com/Kaivenblog/p/8607803.html
Copyright © 2011-2022 走看看