使用Python Shapely查找多边形的最大内接矩形

时间:2015-03-11 14:10:53

标签: python gis point-in-polygon shapely

我试图在六个多边形中找到数百万个点。这是我的代码:

def find_shape(longitude,latitude):
    if longitude != 0 and latitude != 0:
        point = shapely.geometry.Point(longitude,latitude)
    else:
        return "Unknown"
    for current_shape in all_shapes:
        if current_shape['bounding_box'].contains(point):
            if current_shape['shape'].contains(point):
                return current_shape['properties']['ShapeName']
                break
    return "Unknown"

我已经阅读了其他问题,这些问题涉及改善多边形点查询的性能。他们建议Rtrees。但是,似乎这对于有多个多边形(36,000 in one question100,000 in another)的情况很有用,并且不希望将它们全部循环。

我已经设置了一个边框,如您所见。这是我的形状设置代码:

with fiona.open(SHAPEFILE) as f_col:
    all_shapes = []
    for shapefile_record in f_col:
        current_shape = {}
        current_shape['shape'] = shapely.geometry.asShape(shapefile_record['geometry'])
        minx, miny, maxx, maxy = current_shape['shape'].bounds
        current_shape['bounding_box'] = shapely.geometry.box(minx, miny, maxx, maxy)
        current_shape['properties'] = shapefile_record['properties']
        all_shapes.append(current_shape)

检查另一个非常简化的形状版本是否有用,即由最大的内切矩形(或三角形)构成的那个?

检查匀称的文档,似乎没有这个功能。也许有些simplify()的设置?当然,我总是希望确保新的简化形状不会超出原始形状的范围,因此我不必在实际形状上调用contains()。我还认为我希望尽可能简化新的简化形状,以提高速度。

任何其他建议也值得赞赏。谢谢!

编辑:在等待回复的过程中,我想到了创建符合我要求的简化形状的想法:

current_shape['simple_shape'] = current_shape['shape'].simplify(.5)
current_shape['simple_shape'] = current_shape['simple_shape'].intersection(current_shape['shape'])

以下是我在测试每个点时如何使用它:

if current_shape['simple_shape'].contains(point):
    return current_shape['properties']['ShapeName']
elif current_shape['shape'].contains(point):
    return current_shape['properties']['ShapeName']

这并不完美,因为形状并不像在完成必要的intersection()之后那么简单。然而,这种方法使处理时间减少了60%。在我的测试中,简单多边形用于85%的点查询。

编辑2 :关于GIS StackExchange的另一个相关问题: Python Efficiency — Need suggestions about how to use OGR and Shapely in more efficient way。这涉及约3,000个多边形中的150万个点。

1 个答案:

答案 0 :(得分:4)

我会使用R-Tree。 但我会将所有点(而不是多边形的边界框)插入到R树中。

使用r树索引例如:http://toblerity.org/rtree/

from rtree import index
from rtree.index import Rtree

idx = index.Index();

//插入一个点,即左侧==右侧&& top == bottom,基本上会将单个点条目插入索引

for current_point in all_points:
    idx.insert(current_point.id, (current_point.x, current_point.y, current_point.x, current_point.y))

//现在遍历你的多边形

for current_shape in all_shapes:
   for n in idx.intersect( current_shape['bounding_box'] )
      if current_shape['shape'].contains(n):
         # now we know that n is inside the current shape

因此,您最终会在较大的R-Tree上进行六次查询,而不是在一个小型R-Tree上进行数百万次查询。