Geometry 凸多边形的分解

Geometry 凸多边形的分解,geometry,Geometry,这个问题有点复杂。我写了一个算法,用于将一个多边形分解为凸次多边形,但现在我很难证明它不是最优的(即使用Steiner点(添加的顶点)的凸多边形的最小数量)。我的教授坚持认为,像这样的贪婪算法是做不到的,但我想不出一个反例 因此,如果有人能证明我的算法是次优(或最优),我将不胜感激 用图片解释我的算法的最简单方法(这些图片来自较旧的次优版本) 我的算法所做的是围绕我穿过的点延伸线段,直到它碰到另一条边上的点 如果此范围内没有顶点,则会创建一个新顶点(红点)并连接到该顶点: 如果该范围内有一个

这个问题有点复杂。我写了一个算法,用于将一个多边形分解为凸次多边形,但现在我很难证明它不是最优的(即使用Steiner点(添加的顶点)的凸多边形的最小数量)。我的教授坚持认为,像这样的贪婪算法是做不到的,但我想不出一个反例

因此,如果有人能证明我的算法是次优(或最优),我将不胜感激

用图片解释我的算法的最简单方法(这些图片来自较旧的次优版本)

我的算法所做的是围绕我穿过的点延伸线段,直到它碰到另一条边上的点

如果此范围内没有顶点,则会创建一个新顶点(红点)并连接到该顶点:

如果该范围内有一个或多个顶点,则它将连接到最近的顶点。这通常会生成具有最少数量的凸多边形的分解:

然而,在某些情况下,它可能会失败——在下图中,如果它碰巧先连接中间的绿线,这将创建一个额外的不需要的多边形。为此,我建议再次检查我们添加的所有边(对角线),并检查它们是否仍然是必需的。如果没有,请将其移除:

然而,在某些情况下,这是不够的。见下图:

用a-c替换a-b和c-d将产生更好的解决方案。但在这种情况下,没有要删除的边,因此这会带来问题。在这种情况下,我建议一个优先顺序:当决定反射顶点连接到哪个顶点时,它应该选择优先级最高的顶点:

最低)最近顶点

med)最近反射顶点

最高)向后工作时也在范围内的最近反射(难以解释)--

在中,我们可以看到反射顶点9选择连接到12(因为它是最近的),而连接到5则更好。顶点5和12都在扩展线段10-9和8-9定义的范围内,但应优先考虑顶点5,因为9在4-5和6-5给出的范围内,但不在13-12和11-12给出的范围内。i、 例如,边9-12在9处消除反射顶点,但不消除12处的反射顶点,但它可以消除5处的反射顶点,因此应优先考虑5

此修改版本的边缘5-12可能仍然存在,但可以在后处理过程中删除

我错过了什么案子吗


伪代码(由John Feminella请求)——缺少图3和图5中的位

assume vertices in `poly` are given in CCW order
let 'good reflex' (better term??) mean that if poly[i] is being compared with poly[j], then poly[i] is in the range given by the rays poly[j-1], poly[j] and poly[j+1], poly[j]

for each vertex poly[i]
    if poly[i] is reflex
        find the closest point of intersection given by the ray starting at poly[i-1] and extending in the direction of poly[i] (call this lower bound)
        repeat for the ray given by poly[i+1], poly[i] (call this upper bound)

        if there are no vertices along boundary of the polygon in the range given by the upper and lower bounds
            create a new vertex exactly half way between the lower and upper bound points (lower and upper will lie on the same edge)
            connect poly[i] to this new point
        else
            iterate along the vertices in the range given by the lower and upper bounds, for each vertex poly[j]
                if poly[j] is a 'good reflex'
                    if no other good reflexes have been found
                        save it (overwrite any other vertex found)
                    else
                        if it is closer then the other good reflexes vertices, save it
                else
                    if no good reflexes have been found and it is closer than the other vertices found, save it
            connect poly[i] to the best candidate
        repeat entire algorithm for both halves of the polygon that was just split
// no reflex vertices found, then `poly` is convex
save poly

结果发现还有一个我没有预料到的例子:[图5]

我的算法将尝试将顶点1连接到4,除非我添加另一个检查以确保它可以。因此,我建议使用上面提到的优先级方案将“范围内”的所有内容填充到优先级队列中,然后取优先级最高的一个,检查它是否可以连接,如果不能,将其弹出并使用下一个。我认为,如果我对算法进行了正确的优化,那么我的算法就是O(rnlogn)


我把我的发现放在了一起。我倾向于移动东西,所以趁热拿

但应优先考虑顶点5,因为9在4-5和6-5给出的范围内


如果4-5和6-5更加凸,以至于9不在它们的范围内,你会怎么做?然后按照你的规则,正确的做法是连接9到12,因为12是最近的反射顶点,这是次优的。

我相信规则的五角星(例如,具有共线线段的交替点)是你寻求的反例

根据评论进行编辑

根据我修改后的理解,一个修改后的答案是:尝试一个锐角五角星(例如,一个手臂足够窄,只有与你正在工作的反射点相对的手臂的三个点在被认为是“良好反射点”的范围内)。至少从纸面上看,它似乎给出了比最优值更多的结果。然而,最后一次阅读您的代码时,我想知道:您所说的“最近的”(即最接近什么)是什么意思

注意

尽管我的回答被接受了,但这并不是我们最初认为的反例。正如@Mark在评论中指出的那样,它从4到5的时间与最优值的时间完全相同

触发器,触发器

经过进一步思考,我认为我毕竟是对的。在锐角星中,只要确保一对臂具有共线边,就可以保持四的最佳界。但是算法找到了五个,即使修补了

我明白了:

移除固定链接

最佳情况是:


删除死掉的ImageShack链接

我认为您的算法不可能是最优的,因为它没有使用任何最优度量。您可以使用其他指标,如“最近”顶点和检查“必要”对角线

为了在你的算法和优化算法之间形成一个楔子,我们需要通过寻找顶点紧密的形状来利用这个缺口,这样会严重分解。例如(忽略这些行,我在InterTubNet上发现了这个):

您无法防止最中间的点通过凹形“间隙”连接,凹形“间隙”位于多边形外部

你的算法也很复杂,可能做得太多了——就像复杂的代码一样,你可能会发现其中的错误,因为复杂的代码会做出复杂的假设

考虑更广泛的初始阶段,将形状分解为更多、更简单的形状(如三角形),然后使用迭代或遗传算法重新组合它们。你将需要这样一个阶段来组合凸多边形之间任何不必要的分割,到那时你可能已经限制了你的多边形