所以,我有一组点(x,y),我希望能够绘制这些点作为顶点的最大多边形。我可以在matplotlib中使用patches.Polygon(),但这只是按照我给它们的顺序在点之间绘制线条。这不会自动做我想要的。例如,如果想要绘制一个正方形,并通过增加x对点进行排序,然后通过增加y,我将不会得到一个正方形,而是两个连接三角形。 (“越过”线)
所以现在的问题是找到一种方法来对点列表进行排序,这样当迭代这个列表时,我就会“绕过多边形”。
或者Matplotlib中是否有其他功能可以为我做这个?
答案 0 :(得分:4)
正如所建议的那样,一个简单的解决方案是计算从某个内点到所有点的角度并对它们进行排序。
所以这里有一个numpy
函数来计算ccworder
:
In []: def ccworder(A):
..: A= A- mean(A, 1)[:, None]
..: return argsort(arctan2(A[1, :], A[0, :]))
..:
简单的演示:
In []: A
Out[]:
array([[0, 0, 1, 1],
[0, 1, 1, 0]])
In []: ccworder(A)
Out[]: array([0, 3, 2, 1])
<强>更新强>
看起来这种排序可能在某种程度上是繁琐的计算,但numpy
可以提供很好的抽象,使它们非常简单。
警告:正如乔和其他人所指出的那样,只有当所有点都准备好在凸包上时,这个ccworder
才会在凸包上形成正确的顺序。即不知怎的,订单丢失,因为它似乎是OP的情况,它可以恢复。当然,还有其他情况ccworder
使用完全。
答案 1 :(得分:2)
我不知道Matplotlib,但您需要/想要的是绘制点集的凸包。可以将凸包视为一个弹性绳索,放置在点集周围。弹性绳索所采用的形状是凸包。 计算凸包时有不同的算法,因此检查Matplotlib是否支持任何。如果没有,请查看这些链接,了解如何实施的链接。
答案 2 :(得分:2)
如果您已经知道船体点,那么通过连接这些点绘制多边形实际上很容易在Matplotlib中完成,因为多边形在Matplotlib中实现为 路径 即可。我将从matplotlib.path class开始。
如果您不知道船体点,那么我同意Elmar - 凸壳是您想要的算法。我已经在NumPy中编码了这个算法并将其绘制在Matplotlib中。我的代码借鉴了SciPy Cookbook中的优秀食谱here。此配方包括NumPy实现以及在Matplotlib中绘制给定点集周围的凸包所需的完整代码。
此外,Matplotlib包含一个名为 delauney 的软件包,您可能已经猜到了使用delaunay三角剖分来测试曲面。正如您可能知道的那样,这与通过voronoi tesselation的凸包有关 - 即,每个voronoi单元的边界都是从凸包计算中创建的。
答案 3 :(得分:2)
从您的评论到其他答案,您似乎已经获得了定义凸包的点集,但它们没有被排序。订购它们的最简单方法是在凸包内部取一个点作为新坐标系的原点。然后,相对于这个新帧,将点(最可能)的笛卡尔坐标转换为极坐标。如果您根据极角坐标订购点,则可以绘制凸包。仅当您的点集定义了凸(非凹)外壳时,此方法才有效。
答案 4 :(得分:2)
然后,如何自己进行排序?
比方说,凸包点集在python中存储为列表 points , C 是凸包点集中的某种内点,你可以像以下伪代码一样准备一个比较器:
def cmpAngle(p1, p2):
vector1 = p1 - C
vector2 = p2 - C
return dotProduct(vector1, vector2)
points.sort(cmp=cmpAngle)
我们的想法是利用点积来计算相对旋转的排序。
答案 5 :(得分:1)
这里你有一个凸包的python实现(这是你正在寻找的):
答案 6 :(得分:0)
我使用scipy.spatial来解决这类问题。它具有绘制凸壳的特定功能。见here。也许这比你想要的火力更大。