📅  最后修改于: 2023-12-03 14:55:50.794000             🧑  作者: Mango
在计算几何中,凸多边形是指多边形中任意两个点的连线都在多边形内部或者边界上的多边形。凸多边形的性质可以用来优化算法,因此检查一个多边形是否为凸多边形是很有必要的。
对于一个凸多边形中相邻的任意三个点 $P_i=(x_i, y_i), P_j=(x_j, y_j), P_k=(x_k, y_k)$,坐标可以用向量表示:
$\vec{v}_{ij} = (x_j - x_i, y_j - y_i)$
$\vec{v}_{jk} = (x_k - x_j, y_k - y_j)$
则叉积为:
$\mathbf{v}{ij} \times \mathbf{v}{jk} = (x_j - x_i)(y_k - y_j) - (x_k - x_j)(y_j - y_i)$
若边 $P_iP_j$ 和 $P_jP_k$ 的叉积为正,则说明 $P_iP_j$ 在 $P_jP_k$ 的顺时针方向上,这种情况在凸多边形中是不可能出现的。
def is_convex(points):
n = len(points)
flag = False
for i in range(n):
x1, y1 = points[i]
x2, y2 = points[(i+1)%n]
x3, y3 = points[(i+2)%n]
cross_product = (x2-x1)*(y3-y2) - (x3-x2)*(y2-y1)
if i == 0:
if cross_product > 0:
flag = True
elif cross_product < 0:
flag = False
else:
return False
else:
if cross_product > 0 and not flag:
return False
elif cross_product < 0 and flag:
return False
return True
对于一个凸多边形中相邻的任意三个点 $P_i=(x_i, y_i), P_j=(x_j, y_j), P_k=(x_k, y_k)$,假设从 $P_i$ 到 $P_j$ 的向量是 $v_1$,从 $P_j$ 到 $P_k$ 的向量是 $v_2$,它们的叉积可以表示为:
$\vec{v_1} \times \vec{v_2} = x_1y_2 + x_2y_3 + x_3y_1 - x_1y_3 - x_2y_1 - x_3y_2$
同样,若叉积为正,则说明 $P_iP_j$ 在 $P_jP_k$ 的顺时针方向上,这种情况在凸多边形中是不可能出现的。
def is_convex(points):
n = len(points)
flag = False
for i in range(n):
x1, y1 = points[i]
x2, y2 = points[(i+1)%n]
x3, y3 = points[(i+2)%n]
cross_product = x1*y2 + x2*y3 + x3*y1 - x1*y3 - x2*y1 - x3*y2
if i == 0:
if cross_product > 0:
flag = True
elif cross_product < 0:
flag = False
else:
return False
else:
if cross_product > 0 and not flag:
return False
elif cross_product < 0 and flag:
return False
return True
方法一和方法二的时间复杂度均为 $O(n)$,其中 $n$ 是多边形的顶点数。但是方法二中的向量叉积法,由于只涉及一次乘法和一次加减法,因此其性能要优于方法一的叉积法。
另外,方法一和方法二均假设输入的多边形中不会出现三点共线的情况。如果要处理三点共线的情况,需要在代码中进行特判。