[英]How to search point inside polygon without GeoDjango
The situation follows:情况如下:
At this time, I've found GeoDjango which looks a very complex solution to this problem.这个时候,我找到了 GeoDjango,它看起来是一个非常复杂的解决这个问题的方法。 To use it, I need a quite complex setup and I couldn't find any recent (and good) tutorial.
要使用它,我需要一个非常复杂的设置,而且我找不到任何最近的(好的)教程。
I came with this solution:我带来了这个解决方案:
The problem with this solution is quite obvious: Queries may take too long to execute, considering I need to evaluate every polygon.这个解决方案的问题很明显:考虑到我需要评估每个多边形,查询可能需要很长时间才能执行。
Finally: I'm looking for another solution for this problem, and I hope find something that doesn't have setup GeoDjango in my currently running server最后:我正在为这个问题寻找另一种解决方案,我希望找到在我当前运行的服务器中没有设置 GeoDjango 的东西
Determine wheter some point is inside a polygon is not a problem (I found several examples);确定某个点是否在多边形内不是问题(我找到了几个例子); the problem is that retrieve every single polygon from DB and evaluate it does not scale.
问题是从数据库中检索每个多边形并对其进行评估不能缩放。 To solve that, I need to store the polygon in such way I can query it fast.
为了解决这个问题,我需要以可以快速查询的方式存储多边形。
My approach.我的方法。
This solution enables you to store polygons outside of GeoDjango to dramatically speed up point in polygon queries.此解决方案使您能够在 GeoDjango 之外存储多边形,以显着加快多边形查询的速度。
In my case, I needed to find whether the coordinates of my numpy arrays where inside a polygon stored in my geodjango db (land/water masking).就我而言,我需要找出我的 numpy 数组的坐标是否在存储在我的 geodjango db(陆地/水掩蔽)中的多边形内。 This required iterating over every coordinate combination in my arrays to test if it was inside or outside the polygon.
这需要迭代数组中的每个坐标组合以测试它是在多边形内部还是外部。 As my arrays are large, this was taking a very long time using geodjango.
由于我的数组很大,因此使用 geodjango 需要很长时间。
Using django's GEOSGeometry.contains my command looked something like this:使用 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
This was taking 20 s or more on large arrays.这在大型阵列上需要 20 秒或更长时间。 I tried different ways of applying the geometry.contains() function over the array (eg np.vectorize) but this did not lead to any improvements.
我尝试了在数组上应用 geometry.contains() 函数的不同方法(例如 np.vectorize),但这并没有带来任何改进。 I then realised it was the Django contains lookup which was taking too long.
然后我意识到这是 Django contains 查找花费了太长时间。 I also converted the geometry to a shapely polygon and tested shapely's polygon.contains function - no difference or worse.
我还将几何图形转换为匀称的多边形并测试了匀称的多边形.contains 函数 - 没有区别或更糟。
The solution lay in bypassing GeoDjango by using Polygon isInside method.解决方案在于使用Polygon isInside 方法绕过 GeoDjango。 First I created a function to create a Polygon object from my Geos Multipolygon.
首先,我创建了一个函数来从我的 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
Applying this to my problem将此应用于我的问题
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])
This resulted in a roughly 20X improvement in speed.这导致速度提高了大约 20 倍。 Hope this helps someone.
希望这可以帮助某人。
Python 2.7.蟒蛇 2.7。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.