旋转卡壳——合并凸包

出处:http://blog.csdn.net/acmaker/article/details/3561051

合并凸包

考虑如下问题: 给定两个凸多边形, 包含他们并的最小凸多边形是怎样的? 答案即合并凸包后得到的凸多边形。 

合并凸包可以通过一个低效的方式实现: 给定两个多边形的所有顶点, 计算这些点对应的凸包。 更高效的方法是存在的, 他依赖于多边形间的  的查找。 下图描述了这个概念: 

旋转卡壳——合并凸包_第1张图片两个不相交的凸多边形。 合并后的凸包包含两个多边形中的凸包链(途中蓝色粗实线), 通过多边形间的桥进行连接(途中蓝色虚线)


给定两个不相交的多边形, 在多边形间存在两条桥。 多边形相交时, 拥有和顶点数同样数量的桥, 如下图所示: 

旋转卡壳——合并凸包_第2张图片两个相交的凸多边形。 合并凸包只包含多边形间的桥(图中虚线所示)。 存在连接八个顶点的八个桥。


合并操作的核心是分治方法。 他同样用于多边形中。 一个获取凸包的十分简单的方法是将点集分为两部分, 分别计算两个较小点集的凸包, 并且将他们合并。 每个集合再次被分割, 直到元素的个数足够小(比如说三个或者更少) 因此凸包就能被很容易获得了。 
Toussaint 提出利用旋转卡壳来寻找两个凸多边形间的桥。 这个方法的主要优点在于其利用回溯, 并且多边形可以交叠(其他的算法要求多边形不相交)。 下述结论是他的算法的主要过程: 
给定凸多边形 P = { p(1) , ... , p(m) } 和 Q = { q(1) , ... , q(n) },一个点对 (p(i), q(j)) 形成 P 和 Q 之间的桥当且仅当:
  1. (p(i), q(j)) 形成一个并踵点对
  2. p(i-1), p(i+1), q(j-1), q(j+1) 都位于由 (p(i), q(j)) 组成的线的同一侧。
假设多边形以标准形式给出并且顶点是以顺时针序排列, 算法如下:
  1. 分别计算 P 和 Q 拥有最大 y 坐标的顶点。 如果存在不止一个这样的点, 取 x 坐标最大的。
  2. 构造这些点的遂平切线, 以多边形处于其右侧为正方向(因此他们指向 x 轴正方向)。
  3. 同时顺时针旋转两条切线直到其中一条与边相交。 得到一个新的并踵点对 (p(i), q(j)) 。 对于平行边的情况, 得到三个并踵点对。
  4. 对于所有有效的并踵点对 (p(i), q(j)): 判定 p(i-1), p(i+1), q(j-1), q(j+1) 是否都位于连接点 (p(i), q(j)) 形成的线的同一侧。 如果是, 这个并踵点对就形成了一个桥, 并标记他。
  5. 重复执行步骤3和步骤4直到切线回到他们原来的位置。
  6. 所有可能的桥此时都已经确定了。 通过连续连接桥间对应的凸包链来构造合并凸包。
上述的结论确定了算法的正确性。 运行时间受步骤1,5,6约束。 他们都为 O(N) 运行时间(N 是顶点总数)。 因此算法拥有现行的时间复杂度。 

一个凸多边形间的桥实际上确定了另一个有用的概念:多边形间公切线。 同时, 桥也是计算凸多边形交的算法核心。


原文地址:http://cgm.cs.mcgill.ca/~orm/mergech.html

你可能感兴趣的:(旋转卡壳——合并凸包)