寻找一个小于O(n ^ 2)的“完整”凸包

时间:2014-11-21 14:29:34

标签: algorithm computational-geometry convex-hull

我在谷歌搜索这个问题并不是很成功,因为大多数凸包讨论假设你想要一个最小的边界框,并且对如何将这个最小的船体边界填充到一个完整的边界非常模糊。船体。在这里"完成"简单地说,位于最小凸包边缘的任何点都被添加到凸包中。

为了清楚起见,这是一个非常简单的例子。假设我们在2D空间中有n = 9个顶点。为简单起见,我将它们从0到8编入索引。

[0] = (0; 0)
[1] = (0; 1)
[2] = (0; 2)
[3] = (1; 0)
[4] = (1; 1)
[5] = (1; 2)
[6] = (2; 0)
[7] = (2; 1)
[8] = (2; 2)

我们可以在O(nlogn)中找到Graham扫描的最小边界框。 在O(nlogh)中还有其他算法可以做到这一点,但让我们保持简单的开始。最小的船体是[0,2,6,8](或[0 ,8,6,2];这并不重要)。 "完成"船体将是除[4]之外的所有顶点。我应该如何后处理最小的船体以实现'#34;完成"船体没有增加O(n ^ 2)的复杂性?

显然,改变GS算法以包括共线点(> 0到> = 0或< 0到< = 0)不会起作用。我必须使用其他算法吗?

哦,还有一件事:为了这个问题,请假设h~ = n,这样O(n * h)实际上是O(n ^ 2)。


由于人们拒绝相信我提供的示例导致GS在将顶点产品比较更改为包含零时失败。以下是反例的解释:

  1. 通过任何方式找到一个角点(如果你按照wiki所说的那样真的很重要,那就是最低的Y,然后是最低的X,或者是最低的X然后是最低的Y,或倒序)

  2. 向凸包添加角落

  3. 按极角对剩余点进行排序(再次,只要在Ox或Oy轴上完成,只要所有动作都正确调整就无所谓了)

    < / LI>

    这些点对将具有相等的极角:[1,2],[3,6],[4,8]。如果你允许他们任意排队,这肯定会杀死GS,因为你可能会尝试0 6 3 7,之后GS将永久地从凸包中移除3作为无效顶点(同样适用于[ 1,2对]。

    正如我所见,典型的极角等级决胜局是根据它们与角点的距离对它们进行排序。但是,如果您决定先订购距离较远的点,那么GS必须采用0 6 3 7,其中3表示为非船体点。 另一方面,如果您排序的角点距离角点更近,则将采用[...] 5 1 2 0,这将导致GS将2标记为非船体点。

    问题是,我们能否通过精心设计的极角分拣策略或后处理来解决这个问题。

2 个答案:

答案 0 :(得分:2)

这是一个O(log h)时间算法,给定一个具有排序顺序的h顶点的凸包和一个查询点,测试查询点是否位于船体上。从船体中,通过平均其三个顶点来计算内部的点。称此为原点。将平面划分为由原点穿过船体顶点的光线限定的楔形。使用带有方向测试的二分查找来确定查询点属于哪个楔形。测试它是否位于楔形船体段上。

如果您已经实施了Graham扫描,则可以通过更改测试来保留共线点,但是您需要确定相对于与其他两个船体点不共线的原点的角度。这个点可以通过取三个不共线的输入点的平均值来获得。

答案 1 :(得分:0)

经过一番思考后,我发现当你将比较改为包含0,并且通过(更接近第一个)距角点(甚至简单地通过比较坐标)来断开关系时,只有最后一个边受到影响,具体而言它会跳过边缘点。

在你的例子中,你确实最终考虑了第5点,第1点和第2点,但算法将跳过点1而不是2(因为5-1-2是顺时针转弯),因此得到的船体是0 3 6 7 8 5 2。

处理这个问题的一个简单方法是以相反的顺序遍历排序点,并将所有与你的角和最后一个船体点共线的点添加到船体,直到你到达非共线点。

当所有点都是共线时,可能会出现一种特殊情况 - 这取决于您是想要包括边缘点两次(前进和后退)还是只需要一次。