【问题标题】:How to search point inside polygon without GeoDjango如何在没有 GeoDjango 的情况下搜索多边形内的点
【发布时间】:2015-03-18 17:04:13
【问题描述】:

情况如下:

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

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

我提出了这个解决方案:

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

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

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

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

【问题讨论】:

  • 你不会为此使用 GeoDjango。您可以改用 Shapely。 streamhacker.com/2010/03/23/python-point-in-polygon-shapely。但是你同时问很多事情。问题是如何将数据存储在数据库中?或者如何判断一个点是否在多边形中?
  • 发送@AntonisChristofides!我添加了更多细节。问题不是确定该点是否在多边形内,而是我需要以一种可以快速查询其中几个的方式存储多边形。现在清楚了吗?看起来Shapely并没有解决问题
  • 也许你需要的是 PostGIS。
  • 这是一个老问题,但添加了这条评论,因为它仍然在这里显眼地出现。使用 geodjango 绝对没有您尝试过的基于 json 的方法复杂。空间数据库是专门为查找空间关系而设计的。很多有才华的人写了很多代码。如果你想用 JSON 重现它,你会很伤心。

标签: python django geolocation geodjango


【解决方案1】:

此解决方案使您能够在 GeoDjango 之外存储多边形,从而显着加快多边形查询中的点。

就我而言,我需要找出我的 numpy 数组的坐标是否在我的 geodjango db 中存储的多边形内(陆地/水掩蔽)。这需要遍历我的数组中的每个坐标组合来测试它是在多边形内部还是外部。由于我的数组很大,因此使用 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 秒或更长时间。我尝试了在数组上应用 geometry.contains() 函数的不同方法(例如 np.vectorize),但这并没有带来任何改进。然后我意识到这是 Django contains 查找耗时太长。我还将几何图形转换为 shapely 多边形并测试了 shapely 的 polygon.contains 函数 - 没有区别或更糟。

解决方案在于使用PolygonisInside 方法绕过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。

【讨论】:

  • 我刚刚发现了 Geos 准备好的几何图形。这使得 .contains 之类的操作更快,并且只需要一行简单的代码: my_polygon = my_polygon.prepared 在执行 .contains 操作之前。这产生了与上述替代解决方案相当的速度。见:docs.djangoproject.com/en/3.0/ref/contrib/gis/geos/…
【解决方案2】:

我的方法。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 2021-05-13
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多