赞
踩
程序示例:
# -*- coding: utf-8 -*-
# @Time : 2023/3/1 下午2:48
# @Author : Micheal
# @FileName: GoogleS2Util.py
# @Content : 关于Google S2算法的一些基本函数封装
import math
import webbrowser
import s2sphere
import folium
class GoogleS2Util(object):
# (lat, lng, level=30) -> cell ID
@classmethod
def latlng2CellID(cls, lat, lng, level=30):
ll = s2sphere.LatLng.from_degrees(lat, lng)
cellId = s2sphere.CellId.from_lat_lng(ll).parent(level).id() # 指定级数
return cellId
# cell ID -> (lat, lng)
@classmethod
def cellID2Latlng(cls, cellId):
ll = s2sphere.CellId(cellId).to_lat_lng()
point = [ll.lat().degrees, ll.lng().degrees]
return point
# cell ID -> (lat, lng) (推荐使用上面的简便写法)
@classmethod
def cellID2Latlng2(cls, cellId):
cell = s2sphere.Cell(s2sphere.CellId(cellId))
ll = s2sphere.LatLng.from_point(cell.get_center())
point = [ll.lat().degrees, ll.lng().degrees]
return point
# 判断Cell之间的包含关系: (cellIdA, cellIdB) -> isContain
@classmethod
def cellIsContain(cls, cellIdA, cellIdB):
return s2sphere.CellId(cellIdA).contains(s2sphere.CellId(cellIdB))
# 获取 cell 的四个方位: cell ID -> List<GeoPoint>
@classmethod
def cellId2Vertexs(cls, cellId):
cell = s2sphere.Cell(s2sphere.CellId(cellId))
points = []
for i in range(4):
ll = s2sphere.LatLng.from_point(cell.get_vertex(i))
points.append([ll.lat().degrees, ll.lng().degrees])
return points
# 计算两个Point之间的距离(单位:米): (lat1, lng1, lat2, lng2) -> diatance
@classmethod
def getDistance(cls, lat1, lng1, lat2, lng2):
latLng1 = s2sphere.LatLng.from_degrees(lat1, lng1)
latLng2 = s2sphere.LatLng.from_degrees(lat2, lng2)
angle = latLng1.get_distance(latLng2)
# 弧长 = α(圆心角弧度数)× r(半径)= n(圆心角)× π(圆周率)× r(半径)/180
distance = angle.radians * 6371.01 * 1000
# distance = (angle.degrees * math.pi / 180) * 6371.01 * 1000
return distance
# 利用地球经纬度来计算两个坐标点之间的距离
@classmethod
def rad(self, ang):
return math.pi * ang / 180.0
@classmethod
def getDistance2(cls, lat1, lng1, lat2, lng2):
lat1 = cls.rad(lat1)
lng1 = cls.rad(lng1)
lat2 = cls.rad(lat2)
lng2 = cls.rad(lng2)
dlng = lng2 - lng1
dlat = lat2 - lat1
a = (math.sin(dlat / 2)) ** 2
b = math.cos(lat1) * math.cos(lat2)
c = (math.sin(dlng / 2)) ** 2
distance = 6371.01 * 2 * math.asin(math.sqrt(a + b * c)) * 1000.0
return distance
# 获取cellid的Level: cell ID -> level
@classmethod
def getLevel(cls, cellId):
cellID = s2sphere.CellId(cellId)
return cellID.level()
# 获取某一 cellID 的所有邻接Cell: (cellID, level) --> List<Long>
@classmethod
def getNeighborCells(cls, cellId, level=None):
if level is None:
level = cls.getLevel(cellId)
cellID = s2sphere.CellId(cellId)
cellANeighbor = [item.id() for item in cellID.get_all_neighbors(level)]
return cellANeighbor
# 判断两个(同Level的) cellId 是否相邻
@classmethod
def isNeighbor(cls, cellIdA, cellIdB):
return cellIdA in cls.getNeighborCells(cellIdB)
# 获取矩形区域内所有的 cell
# 更多形状区域内的Cell,参考: https://blog.csdn.net/qq_43777978/article/details/116800460
@classmethod
def getCoverCells(cls, lat1, lng1, lat2, lng2, minLevel=0, maxLevel=30, maxCells=100):
# 左下角坐标
startS2 = s2sphere.LatLng.from_degrees(min(lat1, lat2), min(lng1, lng2))
# 右上角坐标
endS2 = s2sphere.LatLng.from_degrees(max(lat1, lat2), max(lng1, lng2))
rect = s2sphere.LatLngRect(startS2, endS2) # 矩形区域
# 获取region区域内的cell
s2RegionCoverer = s2sphere.RegionCoverer()
s2RegionCoverer.min_level = minLevel
s2RegionCoverer.max_level = maxLevel
s2RegionCoverer.max_cells = maxCells
covering = s2RegionCoverer.get_covering(rect)
return [item.id() for item in covering]
if __name__ == "__main__":
# # 验证 “获取矩形区域内所有的 cell”
# tiles = 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}' # 蓝黑版
# myMap = folium.Map([31.374500, 121.487500], zoom_start=12, tiles=tiles, attr='蓝黑版')
# lat1, lng1, lat2, lng2 = -31.408080852440047, -121.26010348059191, -30.995548292413257, -121.727418244035
#
# # 绘制矩形框
# folium.Polygon(
# locations=[[lat1, lng1], [lat1, lng2], [lat2, lng2], [lat2, lng1]],
# color="yellow", # 线条边框颜色
# weight=2, # 线条的宽度
# opacity=0.8, # 线条透明度
# ).add_to(myMap)
#
# # 获取cellIDs
# cells = GoogleS2Util.getCoverCells(lat1, lng1, lat2, lng2, 1, 30, 100)
# for cell in cells:
# # 绘制矩形框
# folium.Polygon(
# locations=GoogleS2Util.cellId2Vertexs(cell),
# color="yellow", # 线条边框颜色
# weight=2, # 线条的宽度
# opacity=0.1, # 线条透明度
# fill=True, # 是否填充内部
# fill_color="red", # 内部颜色
# fill_opacity=0.5 # 内部颜色透明度
# ).add_to(myMap)
#
#
# file_name = "test_debug_analysis.html"
# myMap.save(file_name) # 保存
# webbrowser.get(using='google-chrome').open(file_name, new=2) # 加载
# # 是否包含关系
# loc = GoogleS2Util.cellID2Latlng(3869282349875200000)
# result = GoogleS2Util.cellIsContain(3869280597528543232, GoogleS2Util.latlng2CellID(loc[0], loc[1], 14))
# print(result)
#
# # 获取 cell 的 4个方位
# result = GoogleS2Util.cellId2Vertexs(3869280597528543232)
# print(result)
#
# 获取距离
locA = GoogleS2Util.cellID2Latlng(3869275444641529856)
locB = GoogleS2Util.cellID2Latlng(3869275455378948096)
locC = GoogleS2Util.cellID2Latlng(3869281267543441408)
locA2 = GoogleS2Util.cellID2Latlng2(3869275444641529856)
locB2 = GoogleS2Util.cellID2Latlng2(3869275455378948096)
locC2 = GoogleS2Util.cellID2Latlng2(3869281267543441408)
print(locA, locB, locC)
print(locA2, locB2, locC2)
# result = GoogleS2Util.getDistance(locA[0], locA[1], locB[0], locB[1])
# result2 = GoogleS2Util.getDistance2(locA[0], locA[1], locB[0], locB[1])
# print(result)
# print(result2)
#
# # 获取级数
# result = GoogleS2Util.getLevel(3869280597528543232)
# print(result)
#
# # 获取邻居 cell
# result = GoogleS2Util.getNeighborCells(3869280597528543232, 14)
# print(result)
#
# # 判断是否相邻
# flag = GoogleS2Util.isNeighbor(3869280597528543232, 3869282315515461632)
# print(flag)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。