python中的加速地理定位算法

2024-04-23 14:36:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组100k的地理位置(lat/lon)和一个六边形网格(4k个多边形)。我的目标是计算每个多边形内的点的总数。在

我目前的算法使用2个for循环来循环所有地理点和所有多边形,如果我增加多边形的数量,这真的很慢。。。你如何加速算法?我上传了一个最小的例子,它创建了100k个随机地理点,并使用了561个网格单元。。。在

我还看到读取geo json文件(包含4k个多边形)需要一些时间,也许我应该将多边形导出为csv?在

六边形_网格.geojson文件: https://gist.github.com/Arnold1/9e41454e6eea910a4f6cd68ff1901db1

最小python示例: https://gist.github.com/Arnold1/ee37a2e4b2dfbfdca9bfae7c7c3a3755


Tags: 文件httpsgithubcom算法网格目标地理位置
1条回答
网友
1楼 · 发布于 2024-04-23 14:36:42

您不需要显式地测试每个六边形,看是否有一个给定的点位于其中。在

现在我们假设,所有的点都在六边形网格的边界内。因为你的六边形形成了一个规则的格子,你只需要知道哪个六边形的中心离每个点最近。在

使用^{}可以非常有效地计算出:

import numpy as np
from scipy.spatial import cKDTree
import json

with open('/tmp/grid.geojson', 'r') as f:
    data = json.load(f)

verts = []
centroids = []

for hexagon in data['features']:

    # a (7, 2) array of xy coordinates specifying the vertices of the hexagon.
    # we ignore the last vertex since it's equal to the first
    xy = np.array(hexagon['geometry']['coordinates'][0][:6])
    verts.append(xy)

    # compute the centroid by taking the average of the vertex coordinates
    centroids.append(xy.mean(0))

verts = np.array(verts)
centroids = np.array(centroids)

# construct a k-D tree from the centroid coordinates of the hexagons
tree = cKDTree(centroids)

# generate 10000 normally distributed xy coordinates
sigma = 0.5 * centroids.std(0, keepdims=True)
mu = centroids.mean(0, keepdims=True)
gen = np.random.RandomState(0)
xy = (gen.randn(10000, 2) * sigma) + mu

# query the k-D tree to find which hexagon centroid is nearest to each point
distance, idx = tree.query(xy, 1)

# count the number of points that are closest to each hexagon centroid
counts = np.bincount(idx, minlength=centroids.shape[0])

绘制输出:

^{pr2}$

enter image description here

我可以想出几种不同的方法来处理不在网格范围内的点,具体取决于所需的精度:

  • 可以排除六边形顶点外部边界矩形之外的点(即x < xminx > xmax等)。但是,这将无法排除沿栅格边缘的“间隙”内的点。

  • 另一个简单的选择是根据六边形中心的间距在distance上设置一个截止线,这相当于对外部六边形使用圆形近似。

  • 如果精度很重要,那么可以定义一个对应于六边形网格外部顶点的matplotlib.path.Path,然后使用它的^{} method来测试点是否包含在其中。与其他两种方法相比,这可能会更慢,代码更复杂。

相关问题 更多 >