恐怕我不熟悉您正在使用的库,但我认为我对您可以使用的算法有一个合理的想法,我将介绍如何使用 vanilla python 实现它,然后我相信您可以使用这些库对其进行改进并实现它。此外,我并不是说这是实现这一目标的最佳方式,但我想以相当快的速度得到我的回应,所以就这样吧。
现在,这个想法来自于在算法中使用两个向量的叉积来找到一组点的凸集,例如Graham's Scan。假设我们有两个点 p1 和 p2,它们定义了点向量 p1 和 p2,从原点 (0,0) 到 (x1, y1) 和 (x2, y2) 分别。 p1 x p2 的叉积得到第三个向量 p3,它垂直于 p1 和 p2,大小由向量包围的平行四边形的面积给出。
一个非常有用的结果是矩阵的行列式
/ x1, x2 \
\ y1, y2 /
...即 x1*y2 - x2*y1 给出向量 p3 的大小,符号表示 p3 是否“从”平面中“出来”或“进入”它。这里的关键点是,如果这个量级是正的,那么 p2 就在 p1 的“左边”,如果它是负的,那么 p2 就是“ p1 的右侧”。
希望这个 ascii 艺术示例会有所帮助:
. p2(4, 5)
/
/
/
/_ _ _ _ _. p1(5, 0)
x1*y2 - x2*y1 = 5*4 - 0*5 = 20 所以 p2 在 p1
的“左边”
最后谈谈为什么这对我们有用!如果我们有一个多边形的顶点列表和图中的一组其他点,那么对于多边形的每条边,我们都可以获得该边的向量。我们还可以获得将起始顶点连接到图中所有其他点的向量,并通过测试这些向量是位于边的左侧还是右侧,我们可以消除每条边的一些点。在该过程结束时未删除的所有点都是多边形内的那些点。无论如何,写一些代码来更清楚地理解这一点!
如果您以逆时针方向绘制多边形,则按照您访问它们的顺序获取多边形的顶点列表,例如某个五边形可能是:
poly = [(1, 1), (4, 2), (5, 5), (3, 8), (0, 4)]
获取一个包含图中所有其他点的集合,我们将逐渐从该集合中移除无效点,直到过程结束时留下的正是多边形内的那些点。
points = set(['(3, 0), (10, -2), (3,3), ...])
代码本身的主要部分实际上非常紧凑,因为我花了多长时间来写它是如何工作的。 to_right 接受两个表示向量的元组,如果 v2 位于 v1 的右侧,则返回 True。然后,循环将遍历多边形的所有边缘,如果点位于任何边缘的右侧,则从工作集中删除它们。
def to_right(v1, v2):
return (v1[0]*v2[1] - v1[1]*v2[0]) < 0
for i in range(len(poly)):
v1 = poly[i-1]
v2 = poly[i]
for p in points:
if(to_right(v2-v1, p-v1)):
points.remove(p)
编辑:为了澄清,如果它们在右边而不是左边,它们被删除的事实与指定多边形顶点的顺序有关。如果它们按顺时针顺序排列,则您可能希望消除左侧点。对于这个问题,我目前没有特别好的解决方案。
无论如何,希望我对这些东西是正确的,即使不是 OP,它也会对某人有所帮助。该算法的渐近复杂度为 O(mn),其中 n 是图中的点数,m 是多边形的顶点数,因为在最坏的情况下,所有点都位于多边形内,我们必须检查每个点对于每条边,都不会被删除。