我有一个Shapely多边形列表和一个像这样的点:
from shapely.geometry import Point, Polygon
polygons = [Polygon(...), Polygon(...), ...]
point = Point(2.5, 5.7)
,我想在列表中找到最接近该点的多边形。我已经知道object.distance(other)
函数可以返回两个几何形状之间的最小距离,并且我考虑过计算循环中的所有距离以找到最接近的多边形:
polygons = [Polygon(...), Polygon(...), ...]
point = Point(2.5, 5.7)
min_dist = 10000
closest_polygon = None
for polygon in polygons:
dist = polygon.distance(point)
if dist < min_dist:
min_dist = dist
closest_polygon = polygon
我的问题是:有没有更有效的方法?
答案 0 :(得分:1)
有一种较短的方法,例如
from shapely.geometry import Point, Polygon
import random
from operator import itemgetter
def random_coords(n):
return [(random.randint(0, 100), random.randint(0, 100)) for _ in range(n)]
polys = [Polygon(random_coords(3)) for _ in range(4)]
point = Point(random_coords(1))
min_distance, min_poly = min(((poly.distance(point), poly) for poly in polys), key=itemgetter(0))
Georgy mentioned(++太棒了!)更加简洁:
min_poly = min(polys, key=point.distance)
但是距离计算通常需要大量计算
答案 1 :(得分:0)
有一种方法可以使可能更快,但是如果不进行任何实际测试,很难确定。
这可能不适用于您的情况,但是基本思想是每次将Shapely
对象添加到数组时,您都会调整不同数组元素的位置,以便始终以这种方式对其进行“排序” 。在Python中,这可以通过heapq
模块来完成。该模块的唯一问题是很难选择一个函数来与不同的对象进行比较,因此您必须执行类似this answer的操作,在该过程中,要为对象创建自定义的类,以将其放入{{1} }这是一个元组。
heapq
元组中的第一个元素是“键”,在这种情况下,它是到点的距离,然后第二个元素是实际的import heapq
class MyHeap(object):
def __init__(self, initial=None, key=lambda x:x):
self.key = key
if initial:
self._data = [(key(item), item) for item in initial]
heapq.heapify(self._data)
else:
self._data = []
def push(self, item):
heapq.heappush(self._data, (self.key(item), item))
def pop(self):
return heapq.heappop(self._data)[1]
对象,您可以像这样使用它:
Shapely
最后,您要查找的对象将位于point = Point(2.5, 5.7)
heap = MyHeap(initial=None, key=lambda x:x.distance(point))
heap.push(Polygon(...))
heap.push(Polygon(...))
# etc...
。
但是,最终,这两种算法似乎(大约)是heap.pop()
,因此任何提高速度都不是一个重要的方法。
答案 2 :(得分:0)
我有一个解决方案,如果您至少有2个多边形的距离不同于0,则可以使用。我们将这2个多边形称为“ basePolygon0”和“ basePolygon1”。这个想法是用每个多边形到每个“基本”多边形的距离构建一个KD tree。 构建完KD树后,我们可以通过计算到每个基础多边形的距离来查询它。
这是一个可行的示例:
from shapely.geometry import Point, Polygon
import numpy as np
from scipy.spatial import KDTree
# prepare a test with triangles
poly0 = Polygon([(3,-1),(5,-1),(4,2)])
poly1 = Polygon([(-2,1),(-4,2),(-3,4)])
poly2 = Polygon([(-3,-3),(-4,-6),(-2,-6)])
poly3 = Polygon([(-1,-4),(1,-4),(0,-1)])
polys = [poly0,poly1,poly2,poly3]
p0 = Point(4,-3)
p1 = Point(-4,1)
p2 = Point(-4,-2)
p3 = Point(0,-2.5)
testPoints = [p0,p1,p2,p3]
# select basis polygons
# it works with any pair of polygons that have non zero distance
basePolygon0 = polys[0]
basePolygon1 = polys[1]
# compute tree query
def buildQuery(point):
distToBasePolygon0 = basePolygon0.distance(point)
distToBasePolygon1 = basePolygon1.distance(point)
return np.array([distToBasePolygon0,distToBasePolygon1])
distances = np.array([buildQuery(poly) for poly in polys])
# build the KD tree
tree = KDTree(distances)
# test it
for p in testPoints:
q = buildQuery(p)
output = tree.query(q)
print(output)
这将产生预期的结果:
# (distance, polygon_index_in_KD_tree)
(2.0248456731316584, 0)
(1.904237866994273, 1)
(1.5991500555008626, 2)
(1.5109986459170694, 3)