问题描述
我正在尝试从点列表中获取凸包,这是基于Graham Scan方法的。
points = []
for element in elements:
#getpoints function returns four corners of element bounding box with z overwritten to 0 so that we are working in 2D coordinates.
for p in getPoints(element):
points.append(p)
p0 = None
points.sort(key=lambda x: x.X)
points.sort(key=lambda x: x.Y)
#isolate lower left point
p0 = points.pop(0)
#sort by angle to x axis
points.sort(key=lambda x: DB.XYZ.BasisX.AngleTo(x-p0))
# We know the second point is correct,we are starting by checking the third point.
stack = [p0,points.pop(0),points.pop(1)]
while len(points) > 0:
vector1 = stack[-2] - stack[-1]
vector2 = points[0] - stack[-1]
angle1 = math.atan2(vector1.X,vector1.Y)
angle2 = math.atan2(vector2.X,vector2.Y)
angleDiff = angle1 - angle2
if angleDiff >= 0:
stack.pop(-1)
######stack.append(points.pop(0)) I don't think this is needed,but it doesn't solve my problem when removed.
else:
stack.append(points.pop(0))
curves = []
for i,point in enumerate(stack):
curves.append(DB.Line.CreateBound(point,stack[i-1]))
“凸包”的输出明显不正确:
为澄清起见进行编辑:
获得有利于最左边的最低点。 按与x轴的角度对所有其他点进行排序。 将前三个点添加到堆栈中。 循环, 如果下一个排序点将产生顺时针旋转,请移除堆栈顶部。 否则,如果它创建了逆时针旋转,则将候选排序点添加到堆栈顶部。
我将着手整理一个可复制的案子。
YouTube链接带有图形的说明。
所需的输出:
解决方法
我用python重建了它并使其工作。我认为问题出在我如何计算angleDiff
的地方,这样可以更容易地查看叉积z值的符号。
{@ {1}}确实会跳过一个值,谢谢杰森。
在最初的示例中,我也倒退了stack = [p0,points.pop(0),points.pop(1)]
。应该是vector1
,不是 stack[-1] - stack[-2]
stack[-2] - stack[-1]