Python中礼品包装算法无法终止
我一直在尝试用Python实现礼物包装算法,目前我有以下代码:
def createIslandPolygon(particleCoords):
startPoint = min(particleCoords.iteritems(),key = lambda x: x[1][1])[1]
check = 1
islandPolygon = []
particleList = []
for key in particleCoords:
particleList.append(particleCoords[key])
currentPoint = startPoint
while(currentPoint != startPoint or check == 1):
islandPolygon.append(currentPoint)
check = 0
angleDict = {}
angleList = []
for point in particleList:
if point != currentPoint:
angleDict[(angleBetweenTwoPoints(currentPoint, point))] = point
angleList.append(angleBetweenTwoPoints(currentPoint, point))
smallestAngle = min(angleList)
currentPoint = angleDict[smallestAngle]
return islandPolygon
还有用于计算极坐标的代码:
def angleBetweenTwoPoints(p1, p2):
p3 = (p1[0], p1[1] + 2)
a = (p1[0] - p2[0], p1[1] - p2[1])
b = (p1[0] - p3[0], p1[1] - p3[1])
theta = ((a[0]*b[0]) + (a[1]*b[1]))
theta = theta / (sqrt((a[0]*a[0]) + (a[1]*a[1])) * sqrt((b[0]*b[0]) + (b[1]*b[1])))
theta = math.acos(theta)
return theta
问题是代码似乎一直停在while循环里,为什么会这样我不太明白。有没有人知道原因?
谢谢。
(是的,代码写得很糟糕,我只是快速拼凑的)
编辑:打印出坐标后发现,它们似乎只在两个坐标之间跳动。
1 个回答
1
根据这个链接,你需要这样做:
pointOnHull = leftmost point in S
i = 0
repeat
P[i] = pointOnHull
endpoint = S[0] // initial endpoint for a candidate edge on the hull
for j from 1 to |S|-1
if (endpoint == pointOnHull) or (S[j] is on left of line from P[i] to endpoint)
endpoint = S[j] // found greater left turn, update endpoint
i = i+1
pointOnHull = endpoint
until endpoint == P[0] // wrapped around to first hull point
你这个是对的:
pointOnHull = leftmost point in S
还有这个:
P[i] = pointOnHull
但是这里有我不太确定的部分:
(S[j] is on left of line from P[i] to endpoint)
你应该找到所有角度中最小的那个角度,但根据维基百科,你想要的是所有角度中最左边的那个。我有一些处理角度的代码:
def normalizeangle(radians):
return divmod(radians, math.pi*2)[1]
def arclength(radians1, radians2 = 0):
radians1, radians2 = normalizeangle(radians1), normalizeangle(radians2)
return min(normalizeangle(radians1 - radians2), normalizeangle(radians2 - radians1))
def arcdir(radians1, radians2 = 0):
radians1, radians2 = normalizeangle(radians1), normalizeangle(radians2)
return cmp(normalizeangle(radians1 - radians2), normalizeangle(radians2 - radians1))
arcdir
可以告诉你一个角度是在另一个角度的左边还是右边,所以你可以用它来判断哪个角度更靠左,应该被选用。
如果你沿着这些点移动,总是选择到下一个点的最左边的角度,你就会绕着多边形的边界走一圈,然后再回到起点(因为你选择了最左边的点,你知道它一定在边界上,并且会再次到达)。