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
接受表示向量的两个元组,并返回True
如果v2
位于v1
的右侧。然后,循环只需遍历多边形的所有边缘,并从工作集中删除点,如果它们在任何边缘的右侧。
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)
编辑:为了澄清,如果点在多边形的左侧而不是右侧,则会被删除与指定多边形顶点的顺序有关。如果它们按顺时针顺序排列,则希望消除左侧点。目前我没有特别好的解决方案。
无论如何,希望我关于这些内容的理解是正确的,并且对某人有所帮助,即使不是原帖作者。该算法的渐近复杂度为O(mn),其中n是图中点的数量,m是多边形的顶点数,在最坏情况下所有点都在多边形内部,我们必须检查每个边上的每个点,而没有任何一个点会被删除。
matplotlib.path.Path.contains_points
替代。 - ali_m