找到包围任意点的最小凸包
计算科学
算法
凸包
2021-12-16 20:17:49
2个回答
通常最好从您能想到的最简单、最容易实现的算法开始,以测试您对问题的直觉是否正确,以及您构建的内容是否符合您的需要。
在这种情况下,这是使用O(N³)算法来查看所有点的组合,并选择形成最小面积包含三角形的三个点。
在随机点集上这样做会给出如下解决方案:
如果这是您想要的,那么您可以考虑找到更快的解决方案。如果没有,您可能需要额外的约束。例如,Delaunay 三角剖分最大化三角剖分中存在的最小角度。您可以使用此处描述的方法找到包含三角形。
执行
#!/usr/bin/env python3
import matplotlib.pyplot as plt
import numpy as np
def gen_data(N: int) -> np.ndarray:
return np.random.rand(N,2)
def sign(p1: np.ndarray, p2: np.ndarray, p3: np.ndarray) -> bool:
return (p1[0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[1] - p3[1])
def point_in_triangle(pt: np.ndarray, tri_pts: np.ndarray) -> bool:
d1 = sign(pt, tri_pts[0,:], tri_pts[1,:])
d2 = sign(pt, tri_pts[1,:], tri_pts[2,:])
d3 = sign(pt, tri_pts[2,:], tri_pts[0,:])
has_neg = (d1 < 0) or (d2 < 0) or (d3 < 0)
has_pos = (d1 > 0) or (d2 > 0) or (d3 > 0)
return not (has_neg and has_pos)
def heron_formula(pts: np.ndarray) -> float:
a = np.sqrt((pts[0,0]-pts[1,0])**2 + (pts[0,1]-pts[1,1])**2)
b = np.sqrt((pts[1,0]-pts[2,0])**2 + (pts[1,1]-pts[2,1])**2)
c = np.sqrt((pts[2,0]-pts[0,0])**2 + (pts[2,1]-pts[0,1])**2)
s = (a + b + c) / 2
return np.sqrt(s*(s-a)*(s-b)*(s-c))
def smallest_triangle(pt_to_find: np.ndarray, pts: np.ndarray) -> np.ndarray:
min_area_tri = np.inf
tri_pts = None
for i in range(len(pts)):
for j in range(i+1,len(pts)):
for k in range(j+1,len(pts)):
if point_in_triangle(pt_to_find, pts[(i,j,k),:]):
area = heron_formula(pts[(i,j,k),:])
if area < min_area_tri:
min_area_tri = area
tri_pts = pts[(i,j,k),:].copy()
if tri_pts is None:
raise Exception("No containing triangle found!")
else:
return tri_pts
pts = gen_data(100)
pt_to_find = gen_data(1)[0,:]
smallest = smallest_triangle(pt_to_find, pts)
print("Best area", heron_formula(smallest))
# Add first point to the end for drawing purposes
smallest = np.vstack((smallest, smallest[0,:]))
plt.scatter(pts[:,0], pts[:,1])
plt.scatter(pt_to_find[0], pt_to_find[1], c="red", s=20)
plt.plot(smallest[:,0], smallest[:,1], '-')
plt.show()
其它你可能感兴趣的问题




