是否有一个Python模块,我可以创建具有地理位置坐标(纬度和经度)的对象,并查询所有对象是否在给定坐标的5公里距离(即半径)内?
我一直试图将纬度和经度存储为字典中的键(因为它们是按键索引的)并使用一些距离查找算法来查询它们。但这感觉就像一个可怕的黑客。
基本上类似PostGIS for PostgreSQL,但都在我的Python应用程序的内存中。
答案 0 :(得分:17)
是的,请尝试geopy。
import geopy
import geopy.distance
pt1 = geopy.Point(48.853, 2.349)
pt2 = geopy.Point(52.516, 13.378)
dist = geopy.distance.distance(pt1, pt2).km
# 878.25
之后您可以查询您的积分列表:
[pt for pt in points if geopy.distance.distance(orig, pt).km < 5.]
答案 1 :(得分:5)
我知道这不是你的意思,但你可以将GeoDjango与内存中的SQLite数据库一起使用。它是作为Web应用程序公开的一整套GIS工具,使其成为快速开发GIS应用程序的瑞士军刀,尤其适用于小型即席查询。
答案 2 :(得分:2)
GIS中的常用方法是在感兴趣的点周围创建一个缓冲区并查询交叉点。正如@RyanDalton建议的那样,如果你打算做很多地理位置的东西,可以使用Shapely, GIS API for Python。即使您仍然需要空间索引,也很了解Shapely(见下文)。以下是如何在Shapely中创建缓冲区:
distance = 3
center = Point(1, 1)
pts = [Point(1.1, 1.2),Point(1.2,1.2)]
center_buf = a.buffer(distance)
#filters the points list according to whether they are contained in the list
contained = filter(center_buf.contains,pts)
你可以自己索引你的积分(例如,经度来说),如果你没有很多。否则您也可以使用Rtree包,查看名为Using Rtree as a cheapo spatial database的链接!
答案 3 :(得分:1)
你的字典想法听起来并不那么糟糕,但你也需要检查属于“邻近”字典键的点。
如果你找不到合适的工具,并且喜欢编码算法,那么你可以实现一个二进制空间分区树,它可以用来实现类似的东西。
答案 4 :(得分:1)
您可以使用具有Rtree扩展名的SQLite来完成这种存储和查询。如果您的数据大于要使用的内存,或者您希望在程序运行之间保存和操作数据,则此方法很有用。实际的存储和查询代码是在C中,这意味着它必须被编译,但其好处是比纯gep的纯Python解决方案更具性能。 pysqlite或APSW都适用于SQLite访问。 (披露:我是APSW的作者。)
答案 5 :(得分:0)
你看过Shapely了吗?它有一些查询距离内对象的方法。看看Binary Spatial Predicates。它可能就是你要找的东西。
答案 6 :(得分:0)
我有一个类似的问题,看来使用SciPy的cKDTree进行快速最近点查找以及使用GeoPy进行地理距离计算可以很好地工作。
In [1]: import numpy as np
In [2]: from scipy.spatial import cKDTree
In [3]: from geopy import Point, distance
In [4]: points = np.random.sample((100000, 2)) * 180 - 90 # make 100k random lat-long points
In [5]: index = cKDTree(points)
In [6]: %time lat_long_dist, inds = index.query(points[234], 20)
CPU times: user 118 µs, sys: 164 µs, total: 282 µs
Wall time: 248 µs
In [7]: points_geopy = [Point(*p) for p in points]
In [8]: %time geo_dists = [distance.great_circle(points_geopy[234], points_geopy[i]) for i in inds]
CPU times: user 244 µs, sys: 218 µs, total: 462 µs
Wall time: 468 µs
In [9]: geo_dists
Out[9]:
[Distance(0.0),
Distance(29.661520907955524),
...
Distance(156.5471729956897),
Distance(144.7528417712309)]
要获得半径内的所有点,需要做一些额外的工作。
我尝试了Shapely的STRtree,但性能差得多(我安装了pip install shapely[vectorized]
)。