0

我正在尝试创建一个函数,True如果给定的 (x,y) 点位于凸多边形内,则该函数将返回。我试图让它没有 numpy 或任何类似的导入,只是纯 python 代码。

我已经找到了一个示例解决方案,乍一看似乎还可以,但它不能正常工作,我不知道为什么。代码如下:

def point_in_poly(x,y,poly):

  n = len(poly)
  inside = False

  p1x,p1y = poly[0]
  for i in range(n+1):
      p2x,p2y = poly[i % n]
      if y > min(p1y,p2y):
          if y <= max(p1y,p2y):
              if x <= max(p1x,p2x):
                  if p1y != p2y:
                      xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
                  if p1x == p2x or x <= xints:
                      inside = not inside
      p1x,p1y = p2x,p2y

  return inside

如果我对 (9,9) 进行测试,对于以下多边形,它会给我True

polygon = [(0,10),(10,10),(10,0),(0,0)]
point_x = 9
point_y = 9
print point_in_poly(point_x,point_y,polygon)

但是当我改变多边形点的顺序时,对于同一个点,它给了我False

polygon = [(0,0), (0,10), (10,0), (10,10)]
point_x = 9
point_y = 9
print point_in_poly(point_x,point_y,polygon)

有人知道原因吗?谢谢!

4

3 回答 3

5

在特定情况下,您遇到的问题是特殊的:polygon = [(0,0), (0,10), (10,0), (10,10)]

更改多边形中点的顺序会对算法产生重大影响。

如果您在图表上绘制多边形,您会看到您有一个水平沙漏形状。多边形边界自身重叠。在地理空间分析中,这种重叠是不允许的,因为在视觉和逻辑上,您现在有两个具有共同交点的闭合多边形。顺便说一句,大多数地理空间软件也不能很好地处理三角形。

在这种情况下,9,9 处的点将欺骗上述方法中使用的光线投射算法,因为它可以轻松地两次穿过重叠的多边形边界。

请运行以下代码以查看发生了什么。(9,9) 就行了,这个算法没有考虑到它。(5,8) 在外面:

import turtle as t
polygon = [(0,0), (0,100), (100,0), (100,100)]
t.goto(0,0)
fp = None
for p in polygon:
  t.goto(p)
  if not fp: fp=p
t.goto(fp)
t.up()
t.goto(90,90)
t.write("90,90")
t.dot(10)
t.goto(50,80)
t.write("50,80")
t.dot(10)
t.done()

此代码处理 (9,9) 边缘情况: http: //geospatialpython.com/2011/08/point-in-polygon-2-on-line.html

上面的代码绘制了这个图像。

于 2013-05-04T17:30:19.837 回答
0

该点9,0不在[(0,10),(10,10),(10,0),(0,0)]其边缘的多边形内。根据算法的具体情况,可以考虑精确位于边缘的点。

于 2013-05-01T20:25:33.100 回答
0

对于有很多点的多边形,通常需要先检查点是否落在边界框之外:

def point_in_poly(x, y, poly):
    # Check bounding box first
    xl = [p[0] for p in poly]
    yl = [p[1] for p in poly]
    if x < min(xl) or x > max(xl) or y < min(yl) or y > max(yl):
       return False
   # Now check all points.

您可以在Paul Bourke 的网页之一找到许多处理多边形和网格的算法。

但是,对于许多此类算法,使用 numpy 是值得的,因为必须为poly数组中的每个点完成许多步骤。

于 2013-05-01T21:21:39.967 回答