- 问题描述:给定一个二维封闭图形点集,判断图形中各点的凹凸性。
- 方法:使用矢量判断凹凸性,检测多边形的凸点。参考:判断平面多边形的凹凸性
- 关键点:
(1)通过矢量判断时,需找到图形中第一个凸点:y坐标最大的点,若y坐标最大点不止一个,则寻找其中x坐标最大点
(2)叉乘公式: 向量A(x1,y1),向量B(x2,y2)
叉乘结果 = x1 * y2 - x2 * y1
(3)第一个凸点的叉乘必为正,如果其他点叉乘结果为负,则说明该点为凹点。
下面是该问题的python实现
import numpy as np
def find_ymax(data):
"""寻找封闭图形中y坐标最大的点
若y坐标最大点不止一个,则寻找其中x坐标最大点
Args:
data (list): 封闭图形点集
Returns:
封闭图形中第一个凸点
"""
ploy = np.array(data)
y = ploy[:,1]
y_max = y.max()
Conv_list = list()
for p in data:
if p[1] == y_max:
Conv_list.append(p)
if len(Conv_list) != 1:
temp_list = []
for p in Conv_list:
temp_list.append(p[0])
return Conv_list[temp_list.index(max(temp_list))]
else:
return Conv_list[0]
def Conv(data):
"""对多边形各点进行凹凸性判断
Args:
data (list): 封闭图形点集
Returns:
[list]: 多边形中凹点坐标集合
"""
Norm_dot = find_ymax(data)
num = len(data)
Ind = data.index(Norm_dot)
Conv_dots = []
# 第一个凸点的两条向量边叉乘
# if num == 0:
# Vec_A = [data[num][0] - data[Tonum - 1][0] , data[num][1] - data[Tonum - 1][1]]
# Vec_B = [data[num+1][0] - data[num][0] , data[num+1][1] - data[num][1]]
# elif num == Tonum - 1:
# Vec_A = [data[num][0] - data[num - 1][0] , data[num][1] - data[num - 1][1]]
# Vec_B = [data[0][0] - data[num][0] , data[0][1] - data[num][1]]
# else:
# Vec_A = [data[num][0] - data[num - 1][0] , data[num][1] - data[num - 1][1]]
# Vec_B = [data[num+1][0] - data[num][0] , data[num+1][1] - data[num][1]]
Vec_A = [data[Ind%num][0] - data[(Ind-1)%num][0], data[Ind%num][1] - data[(Ind-1)%num][1]]
Vec_B = [data[(Ind+1)%num][0] - data[Ind%num][0], data[(Ind+1)%num][1] - data[Ind%num][1]]
Vect_Norm = (Vec_A[0] * Vec_B[1]) - (Vec_A[1] * Vec_B[0])
# 向量法判断图形中每个点的凹凸性
for i in range(num):
V_A = [data[(i)%num][0] - data[(i-1)%num][0], data[(i)%num][1] - data[(i-1)%num][1]]
V_B = [data[(i+1)%num][0] - data[(i)%num][0], data[(i+1)%num][1] - data[(i)%num][1]]
Vec_Cross = (V_A[0] * V_B[1]) - (V_A[1] * V_B[0])
if (Vec_Cross * Vect_Norm) < 0:
Conv_dots.append(data[(i) % num])
return Conv_dots
data = [[20,12],[25,0],[30,15],[15,17],[15,20],[10,20],[10,10]]
print(Conv(data))
如有不足,还请各位大佬不吝赐教!