Python怎么实现绘制凸包
更新时间:2023-10-06凸包的定义
凸包是指包围给定点集的最小凸多边形,即能包含所有点,且多边形上的所有角都是不大于180度的角。
在凸包的计算中,常用的方法是Graham扫描法和Jarvis旋转法。
Graham扫描法
Graham扫描法是一种基于极角排序的方法,步骤如下:
1. 找到点集中的最低点(最左下角)。
2. 将所有点按照与最低点的极角排序。
3. 从排序后的点集中依次取出点,如果该点与前两个点构成的向量产生了右转,那么将前一个点移除,直到找到左转或形成直线。
4. 最后得到的序列即为凸包的顶点。
import math def orientation(p, q, r): """ 计算点p,q,r的方向 返回值: -1: 右转 0: 共线 1: 左转 """ val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]) if val == 0: return 0 return 1 if val > 0 else -1 def convex_hull(points): # 如果点个数小于等于2,直接返回所有点 if len(points) <= 2: return points hull = [] # 保存结果的凸包 l = 0 # 最左下角的点的索引 # 找到最左下角的点 for i in range(1, len(points)): if points[i][1] < points[l][1] or (points[i][1] == points[l][1] and points[i][0] < points[l][0]): l = i p = l # 当前处理的点 q = 0 # 上一次放在结果里的点 while True: # 将当前点加入凸包 hull.append(points[p]) # 查找下一个点 q = (p + 1) % len(points) for i in range(len(points)): if orientation(points[p], points[i], points[q]) == -1: q = i p = q if p == l: break return hull
Jarvis旋转法
Jarvis旋转法是一种逐步递增的方法,步骤如下:
1. 找到点集中的最左点(最左上方)。
2. 从最左点开始,按照逆时针方向找到与当前点构成最大极角的点,顺时针遍历所有点。
3. 找到一个新的点后,将其加入凸包,并将其作为下一步查找的起始点。
4. 当找到的点与起始点重合时,终止,得到的序列即为凸包的顶点。
def leftmost_point(points): """ 找到最左点的索引 """ leftmost = 0 for i in range(1, len(points)): if points[i][0] < points[leftmost][0]: leftmost = i return leftmost def convex_hull(points): left = leftmost_point(points) hull = [] n = len(points) p = left q = None while True: hull.append(points[p]) q = (p+1) % n for i in range(n): if orientation(points[p], points[i], points[q]) == -1: q = i p = q if p == left: break return hull
总结
无论是Graham扫描法还是Jarvis旋转法都可以用来实现凸包的计算。Graham扫描法在整个过程中需要对点进行排序,然后在每一步查找时都需要计算极角,因此时间复杂度为O(nlogn)。Jarvis旋转法在每一步查找时需要顺时针遍历所有点,因此时间复杂度为O(nh),其中h是凸包的边数,在最坏情况下h=n,所以Jarvis旋转法的时间复杂度为O(n^2)。
凸包是在计算几何中常见的问题,可以应用在面积计算、碰撞检测等领域。在Python中,可以通过编写相应的算法来实现凸包的计算。