POI经纬度坐标常见用法整理(Python版)

本文章整理了经纬度坐标的相关用法,包括与geohash编码互相转换、火星坐标系转换算法、求两个坐标的距离、求围栏面积以及判断poi坐标是否在围栏里,后续再有经纬度相关的也会补充到这里~~芝士就是力量!power!!

目录

1.根据经纬度坐标获得geohash

2.GCJ-02 和 WGS 84 坐标系互相转换

GCJ-02 和 WGS 84 坐标系区别

火星坐标系转换算法

3.求两个坐标的距离

方法一

方法二

4.求围栏面积

5.判断poi坐标是否在围栏里


1.根据经纬度坐标获得geohash

输入不同的precision,可以获得不同长度的geohash,以geohash7为例:

import geohash2

# 将经度和纬度转换为 Geohash7 编码
def encode_geohash7(latitude, longitude):
    return geohash2.encode(latitude, longitude, precision=7)

逆操作:通过geohash编码转换为经纬度坐标

# 将 Geohash7 编码转换为经度和纬度
def decode_geohash7(geohash7):
    lat, lon = geohash2.decode(geohash7)
    return lat, lon

2.GCJ-02 和 WGS 84 坐标系互相转换

GCJ-02 和 WGS 84 坐标系区别

GCJ-02(国测局坐标系)和 WGS 84(World Geodetic System 1984)是两种不同的地理坐标系,用于表示地球上的位置。以下是它们之间的主要差别:
  • 坐标偏移:
        WGS 84: 是一种全球通用的坐标系,由GPS使用。WGS 84 坐标通常被认为是地球上某一点的真实坐标。
        GCJ-02: 是中国国测局为保护国家地理信息安全而对 WGS 84 进行的一种加密处理。GCJ-02 对原始的 WGS 84 坐标进行了一定的偏移,使得在中国境内的地理位置不容易被外部解析。
  • 使用范围:
        WGS 84: 广泛用于全球,是GPS设备和地理信息系统(GIS)等应用的标准坐标系。
        GCJ-02: 主要在中国境内使用,包括大部分在线地图服务如百度地图、高德地图等。
  • 加密算法:
        WGS 84: 没有加密处理,坐标表示地球上的真实位置。
        GCJ-02: 使用了一种加密算法,通常称为"火星坐标系"。这个算法会对 WGS 84 坐标进行加密,以保护地理信息的安全。
  • 坐标转换:
        由于 GCJ-02 的加密处理,WGS 84 坐标不能直接转换为 GCJ-02 坐标,反之亦然。因此,在进行坐标转换时,需要使用专门的算法,如火星坐标系转换算法。

火星坐标系转换算法

import math

#GCJ-02 坐标转换为 WGS 84 坐标
def gcj02_to_wgs84(gcj_lon, gcj_lat):
    a = 6378245.0
    ee = 0.00669342162296594323

    def transform_lon(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 transform_lat(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.0 * math.sin(y * math.pi / 30.0)) * 2.0 / 3.0
        return ret

    if out_of_china(gcj_lon, gcj_lat):
        return gcj_lon, gcj_lat

    dlat = transform_lat(gcj_lon - 105.0, gcj_lat - 35.0)
    dlon = transform_lon(gcj_lon - 105.0, gcj_lat - 35.0)
    rad_lat = gcj_lat / 180.0 * math.pi
    magic = math.sin(rad_lat)
    magic = 1 - ee * magic * magic
    sqrt_magic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrt_magic) * math.pi)
    dlon = (dlon * 180.0) / (a / sqrt_magic * math.cos(rad_lat) * math.pi)
    wgs_lat = gcj_lat - dlat
    wgs_lon = gcj_lon - dlon

    return wgs_lon, wgs_lat


#WGS 84 坐标转换为 GCJ-02 坐标
def wgs84_to_gcj02(wgs_lon, wgs_lat):
    a = 6378245.0
    ee = 0.00669342162296594323

    def transform_lon(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 transform_lat(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.0 * math.sin(y * math.pi / 30.0)) * 2.0 / 3.0
        return ret

    if out_of_china(wgs_lon, wgs_lat):
        return wgs_lon, wgs_lat

    dlat = transform_lat(wgs_lon - 105.0, wgs_lat - 35.0)
    dlon = transform_lon(wgs_lon - 105.0, wgs_lat - 35.0)
    rad_lat = wgs_lat / 180.0 * math.pi
    magic = math.sin(rad_lat)
    magic = 1 - ee * magic * magic
    sqrt_magic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrt_magic) * math.pi)
    dlon = (dlon * 180.0) / (a / sqrt_magic * math.cos(rad_lat) * math.pi)
    gcj_lat = wgs_lat + dlat
    gcj_lon = wgs_lon + dlon

    return gcj_lon, gcj_lat

def out_of_china(lon, lat):
    return lon < 72.004 or lon > 137.8347 or lat < 0.8293 or lat > 55.8271

3.求两个坐标的距离

介绍两种方法

方法一

from math import radians, sin, cos, sqrt, atan2

def haversine(lat1, lon1, lat2, lon2):
    # 将经纬度转换为弧度
    lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])

    # Haversine 公式
    dlat = lat2 - lat1
    dlon = lon2 - lon1
    a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
    c = 2 * atan2(sqrt(a), sqrt(1 - a))

    # 地球半径(单位:千米)
    R = 6371.0

    # 计算距离
    distance = R * c

    return distance

# 示例:计算两个坐标点的距离
lat1, lon1 = 45.7890, 123.4560    
lat2, lon2 = 45.7899, 123.4560

distance_km = haversine(lat1, lon1, lat2, lon2)

# 打印结果
print(f"The distance between the two points is {distance_km*1000:.2f} m.")

方法二

from geopy.distance import geodesic

lat1, lon1 = (45.7890, 123.4560)  # 示例坐标1
lat2, lon2 = (45.7899, 123.4560)  # 示例坐标2


# 计算两个坐标之间的距离
distance_km = geodesic((lat1, lon1), (lat2, lon2)).kilometers

# 打印结果
print(f"The distance between the two points is {distance_km*1000:.2f} m.")

4.求围栏面积

尝试了多种求围栏面积的方法,对比后发现以下方法是比较准确的

参考来源:根据经纬度点求面积_经纬度 面积-CSDN博客

#计算围栏面积函数
def ComputeArea(temp):
    arr_len = len(temp)
    if arr_len < 3:
        return 0.0

    s = temp[0][1] * (temp[arr_len -1][0]-temp[1][0])
    for i in range(1,arr_len):
        s += temp[i][1] * (temp[i-1][0] - temp[(i+1)%arr_len][0])
    return round(math.fabs(s/2)*9101160000.085981,6)


# 围栏
polygon='113.986907,22.595623;113.988259,22.595658;113.988224,22.595045;113.986888,22.595036'

#处理围栏格式
polygon_gcj =[]
for lon_lat in polygon.split(';'):
    lon=float(lon_lat.split(',')[0])
    lat=float(lon_lat.split(',')[1])
    polygon_gcj +=[(lon,lat)]

print(polygon_gcj)

#计算面积
area=ComputeArea(polygon_gcj)

print("围栏面积是:",area)

5.判断poi坐标是否在围栏里

简单版

from shapely.geometry import Point, Polygon

# POI坐标
poi = (113.988188,22.595069)
polygon='112.964302,28.225389;112.974781,28.226108;112.970758,28.209185;112.966764,28.190226;112.964703,28.164677;112.96312,28.157887;112.960295,28.149132;112.958914,28.139693;112.953478,28.139737;112.957256,28.163486;112.959139,28.208019'

# 创建Shapely的Point和Polygon对象
poi = Point(poi)
fence = Polygon(polygon)

# 判断POI是否在围栏内
is_inside = poi.within(fence)

if is_inside:
    print("POI在围栏内")
else:
    print("POI不在围栏内")

数组版

from shapely.geometry import Point, Polygon
'''
假设有一个数组data,包含longitude,latitude,polyline列,
需要判断(longitude,latitude)是否在polyline里
'''

#单个封闭围栏格式处理,经纬度对用";"隔开
def lon_lat_list(fence_i):
    fence_l = []
    for lon_lat in fence_i.split(';'):
        lon = float(lon_lat.split(',')[0])
        lat = float(lon_lat.split(',')[1])
        fence_l += [(lon, lat)]
    return fence_l


#这里考虑了polyline包含多个封闭围栏的情况,每个封闭围栏间用"|"隔开
def polyline_to_fence(polyline):
    fence=[]
    if '|' in polyline:
        for fence_i in polyline.split('|'):
            fence_l=lon_lat_list(fence_i)
            fence.append(fence_l)
    else:
        fence_l = lon_lat_list(polyline)
        fence.append(fence_l)
    return fence

def is_in_fence(row):
    lon,lat = row['longitude'],row['latitude']
    poi=(lon,lat)

    # 创建Shapely的Point对象
    poi = Point(poi)
    
    #应用自定义函数处理围栏格式
    fence = polyline_to_fence(row['polyline_x'])

    count=0
    for fence_x in fence:
        # 创建Shapely的Polygon对象
        fence = Polygon(fence_x)

        # 判断POI是否在围栏内
        is_inside = poi.within(fence)
        
        #is_inside为布尔型:Ture or False
        if is_inside:
            count+=1

    #返回1表示在围栏,0表示不在围栏
    return count    


#apply应用数组的自定义函数
data['is_in_fence']=data.apply(is_in_fence,axis=1)

#输出在/不在围栏的数量
print(data['is_in_fence'].value_counts())

  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 高德POI是指高德地图的兴趣点(Points of Interest,POI)数据。Python是一种广泛使用的编程语言。那么,Python如何与高德的POI数据进行交互呢? 首先,我们可以使用Python的requests库向高德的POI接口发送HTTP请求,以获取POI数据。我们需要使用高德的开发者密钥,将其作为参数添加到请求中。通过设置请求的经纬度、半径、关键词等参数,可以获取特定区域、特定类型的POI数据。 接着,我们可以使用Python的json库对返回的JSON格式数据进行解析和处理。通过解析,我们可以获取POI的名称、地址、经纬度、电话等相关信息,并根据需要进行进一步的处理和分析。 在获取到POI数据后,我们可以将其展示在地图上,借助Python的地图可视化库(如folium)实现。通过将POI经纬度坐标添加到地图上,可以方便地查看POI分布情况,并进行可视化分析。 此外,我们还可以使用Python的机器学习和数据挖掘库对POI数据进行分析。例如,可以使用聚类算法POI进行聚类分析,找出具有相似特征的POI群组。或者,可以使用文本挖掘技术对POI的描述文本进行情感分析,了解用户对POI的评价情况。 总之,Python提供了丰富的工具和库,可以方便地获取、解析和分析高德的POI数据。通过Python的强大功能,我们可以更好地利用和分析POI数据,以满足不同领域的需求,如地理信息分析、城市规划等。 ### 回答2: Python 高德POI是一个基于Python编程语言的高德地图兴趣点服务接口。POI即兴趣点(Points of Interest),是指地图上的特定地点,例如餐馆、商场、景点等。 使用Python高德POI,我们可以通过调用相应的接口获得特定位置周边的兴趣点信息。首先,我们需要在高德地图开放平台上获取API密钥,然后使用Python的HTTP库发送HTTP请求到高德POI的接口地址,将API密钥和其他参数一起传递给接口。接口会返回一个JSON格式的响应,其中包含了周边兴趣点的相关信息,如名称、地址、经纬度等。 在Python中使用高德POI可以实现很多功能,比如查找指定位置附近的餐馆,或者根据用户输入的关键词搜索特定类型的兴趣点。我们可以根据返回的兴趣点信息,对其进行处理和分析,比如绘制地图、计算距离等。 Python高德POI的使用非常灵活,我们可以根据自己的需求定制特定的功能。此外,高德POI也提供了批量操作接口,允许我们一次性获取多个位置周围的兴趣点信息,方便进行大规模的数据处理和分析。 总而言之,Python高德POI是一个强大的工具,能够帮助我们在Python环境中轻松实现与高德地图相关的兴趣点服务。无论是进行实时地理位置数据处理,还是进行地理信息系统开发,Python高德POI都能够提供便捷而高效的解决方案。 ### 回答3: Python高德POI是一个用于访问和使用高德地图的Python库。POI代表兴趣点(Point of Interest),它是指地图上的特定位置或区域,如酒店、餐厅、景点等。 使用Python高德POI,我们可以通过API获取各种POI的详细信息。首先,我们需要在高德地图开发者平台上申请一个API密钥。然后,我们可以使用该密钥访问高德地图的API。 要使用Python高德POI,我们首先需要安装它的库文件。可以使用pip命令在命令行中运行"pip install amap"来安装。安装好之后,我们可以在Python脚本中导入amap模块,然后使用其中的函数和类进行地图操作。 例如,我们可以使用amap的search函数在指定的城市中搜索特定类型的POI。我们可以指定查询关键词和城市名称,并设置一些可选参数,如搜索半径、搜索结果数量等。执行查询后,我们可以获取到符合条件的POI的信息,如名称、地址、坐标等。 除了搜索,Python高德POI还提供了其他功能,如地点周边搜索、路径规划等。我们可以使用amap的相关函数来实现这些操作,以满足不同的需求。 总的来说,Python高德POI是一个强大的工具,可以帮助我们在Python中方便地访问和使用高德地图的POI数据。无论是开发地图导航应用程序,还是进行地理位置分析,都可以使用Python高德POI来简化我们的工作,并提供丰富的地图数据支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jackie_kk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值