Python中的礼品包装算法

Python中的礼品包装算法,python,algorithm,geometry,Python,Algorithm,Geometry,我一直在尝试用Python实现礼品包装算法,目前我有以下代码: def createIslandPolygon(particleCoords): startPoint = min(particleCoords.iteritems(),key = lambda x: x[1][1])[1] check = 1 islandPolygon = [] particleList = [] for key in particleCoords:

我一直在尝试用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循环,我不知道为什么。有人知道吗

谢谢

(是的,代码很差,我很快就拼凑起来了)

编辑:打印出坐标似乎显示它们在两个坐标之间跳跃。

根据需要执行以下操作:

   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
将告诉您一个角度是在另一个角度的左侧还是右侧,因此您可以使用它来查看一个角度是否更左侧,是否应该使用该角度


如果你沿着点移动,总是选择最左边的角度到下一个点,你会绕着多边形的周长再次到达起点(因为你选择了最左边的点,你知道它必须在周长上,并且会再次到达)

啊,我现在明白为什么它会在两个点之间跳跃了。我现在正在尝试实现你的解决方案,但有一件事我不确定,你说比较两个角度,你的意思是我应该找到它们中最左边的,然后使用它吗?所以通过angleList比较所有角度,直到得到最左边的角度并使用它?正如维基百科伪代码所做的那样,您可以在内存中保留一个角度(迄今为止最左边的角度),并与之进行比较。顺便说一句,确保从正下方到正上方(圆周率弧度转弯)的情况被视为最左侧的角度,同样,从完全向上到完全向下的过程也得到了正确的处理——否则,你的算法可能会在由两个以上点组成的完全笔直的垂直边上随机失效。