在Python中从一组角度生成多边形?

时间:2013-06-21 18:52:29

标签: python geometry polygons

大家好(第一次在这里发帖,所以我希望我没有做任何可怕的错误)......

我正在尝试在Python中随机生成一组带有3到 2l 边的凸多边形,这样每个多边形的每一边都与预定的 l 之一平行线。如果有人知道这样做的方式(有或没有像CGAL或Shapely这样的计算几何包的帮助),那就太棒了。

我从包含 2l 角度的列表开始(每条线的方向,每条线的方向+平行边的pi)。对于我制作的每个多边形,我从该列表中随机选择3到 2l 角度,按递增顺序排序,使得没有角度与之前的角度相差大于pi,以确保角度为能够定义多边形。然而,在那之后我无法确保我生成的多边形保持凸起并且仅包含与我选择的线平行的边。我的代码目前看起来像这样:

def generate(l, n, w, h):
    """Generate n polygons with sides parallel to 
    at most l vectors in a w x h plane."""
    L = []
    polygons = []
    while len(L) < 2*l:
        i = random.uniform(0, math.pi)
        if i != math.pi and not i in L:
            L.append(i)
            L.append(i+math.pi)
    L.sort()
    while len(polygons) < n:
        Lp = list(L)
        rm = random.randint(0, 2*l-3)
        #Filter out rm lines, if possible
        for i in range(rm):
            i = random.randint(0, len(Lp)-1)
            for j in range(i, len(Lp)) + range(0, i):
                nxt = Lp[(j+1)%len(Lp)]
                prv = Lp[(j-1)%len(Lp)]
                if prv < nxt < prv+math.pi or nxt < (prv+math.pi)%(2*math.pi)-1e-14 < prv:
                    del Lp[j]
                    break

        # Choose a "center point, then generate a polygon consisting of points
        # a fixed distance away in the direction perpendicular to each angle.
        # This does not work however; resulting polygons may have sides not 
        # parallel to one of the original lines.
        cx, cy = random.uniform(-w/2,w/2), random.uniform(-h/2,h/2)
        points = []
        r = random.uniform(10,100) 
        for theta in Lp:
            # New point is r away from "center" in direction
            # perpendicular to theta
            x = cx + r * math.sin(theta)
            y = cy - r * math.cos(theta)
            points.append(polygon.Vector(x,y))     
        polygons.append(polygon.Polygon(points))
    return polygons

1 个答案:

答案 0 :(得分:0)

问题在于你的角度选择。你必须尊重两个约束。

第一个约束凸多边形的角度总和为180*(n-2)度,其中n是凸多边形的边数[src ]

第二个约束给定两行,您有两个角度选择: AngleChoice

您必须选择绿色角度。您的选择标准在您的描述中不是很清楚,因此我无法确定是否存在错误。为了选择好的角度,我认为最简单的方法是考虑每条线的方向向量。计算u最后一行的方向向量(指向新行)。计算v,新行的方向向量。如果(u^v) > 0v没有正确定位,那么您想要-v。如果(u^v) < 0v正确定向,则另外。 详细信息: u^v = u.x*v.y -u.y*v.x

所以这引导我们进入第二个约束。考虑u边的方向向量和u_next下一边的方向向量,我们有u^u_next < 0

我认为第二个约束就足够了。我们不需要第一个(但是知道一般知识仍然很好)。

该怎么做以下是我为您的问题所做的事情:

  1. 选择随机行。计算方向向量u0,例如u0.x > 0。用u初始化方向向量的列表listDV。注意:如果u.x = 0,请选择u,例如u.y > 0
  2. 虽然{listDV.last^listDV.first < 0){选择随机行,计算方向向量u,例如listDV.last^u < 0,请在listDV}的末尾推送。
  3. 弃掉listDV
  4. 的最后一个向量

    所以现在你有一个方向向量列表,它们与你的行平行。该列表形成一个凸多边形。

    接下来将创建多边形。如果您需要帮助,请告诉我们!