如何在没有GeoDjango的情况下搜索多边形内的点

时间:2015-01-20 12:51:28

标签: python django geolocation geodjango

情况如下:

  • 每个供应商都有一些服务区域,用户使用GoogleMaps(多边形)定义了这些区域。
  • 我需要将这些数据存储在数据库中,并对此进行简单(但快速)的查询。
  • 查询应如下所示:“列出包含x,y的服务区域的所有供应商”或“其中多边形(服务区域)x,y在哪里?”

此时,我发现GeoDjango看起来是一个非常复杂的解决方案。要使用它,我需要一个非常复杂的设置,我找不到任何最近的(和好的)教程。

我带来了这个解决方案:

  • 将每个多边形作为Json存储到数据库中
  • 应用一种方法来确定某些x,y是否属于任何多边形

此解决方案的问题非常明显:考虑到我需要评估每个多边形,查询可能需要很长时间才能执行。

最后:我正在为这个问题寻找另一个解决方案,我希望在我当前运行的服务器中找到没有设置GeoDjango的东西

确定多边形内部的某些点不是问题(我找到了几个例子);问题是从DB检索每个多边形并评估它不会缩放。为了解决这个问题,我需要以这样的方式存储多边形,以便我可以快速查询它。

2 个答案:

答案 0 :(得分:0)

我的方法。

  1. 查找多边形C++ code的质心。
  2. 存储在数据库中
  3. 找到从顶点到质心(pythag)的最长距离
  4. 以半径形式存储
  5. 使用质心和数字搜索数据库半径作为边界框
  6. 如果一个或多个结果在结果多边形上使用多边形点

答案 1 :(得分:0)

此解决方案使您可以将多边形存储在GeoDjango之外,从而大大加快多边形查询的速度。

在我的情况下,我需要确定是否在geopjango db(土地/水遮罩)中存储的多边形内部的numpy数组的坐标。这需要遍历数组中的每个坐标组合以测试它在多边形内部还是外部。由于我的数组很大,因此使用geodjango花费了很长时间。

使用django的GEOSGeometry.contains我的命令看起来像这样:

import numpy as np
from django.contrib.gis.geos import Point

my_polygon = model.geometry  # get model multipolygon field
lat_lon = zip(latitude.flat, longitude.flat)  # zip coordinate arrays to tuple
mask = np.array([my_polygon.contains(Point(l)) for l in lon_lat])  # boolean mask

这在大型阵列上花费了20 s或更长时间。我尝试了在数组上应用geometry.contains()函数的不同方法(例如np.vectorize),但这并没有带来任何改进。然后我意识到这是Django包含查找的时间太长。我还将几何图形转换为形状多边形并测试了形状的多边形。包含功能-没什么不同或更差。

解决方案在于使用Polygon isInside方法绕过GeoDjango。首先,我创建了一个从我的Geos Multipolygon创建Polygon对象的函数。

from Polygon import Polygon

def multipolygon_to_polygon(multipolygon):
    """
    Convert a Geos Multipolygon to python Polygon
    """

    polygon = multipolygon[0] # select first polygon object
    nrings = polygon.num_interior_rings # get number of rings in polygon

    poly = Polygon()  
    poly.addContour(polygon[0].coords)  # Add first ring coordinates tuple

    # Add subsequent rings
    if nrings > 0:
        for i in range(nrings):
            print("Adding ring %s" % str(i+1))
            hole = True
            poly.addContour(polygon[i+1].coords, hole)

    return poly

将此应用于我的问题

my_polygon = model.geometry  # get model multipolygon field
polygon = multipolygon_to_polygon(my_polygon)  # convert to python Polygon
lat_lon = zip(bands['latitude'].flat, bands['longitude'].flat)  # points tuple
land_mask = array([not polygon.isInside(ll[1], ll[0]) for ll in lat_lon])

这使速度提高了大约20倍。希望这对某人有帮助。

Python 2.7。