Algorithm 找到一个;“完成”;小于O(n^2)的凸壳

Algorithm 找到一个;“完成”;小于O(n^2)的凸壳,algorithm,computational-geometry,convex-hull,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

我在谷歌搜索这个问题上不是很成功,因为大多数关于凸包的讨论都假设你想要一个最小的边界框,并且对于如何将这个最小的外壳边界填充到一个“完整”的外壳非常模糊。这里“完整”只是指位于最小凸包边上的任何点都添加到凸包中

为了说明问题,这里有一个非常简单的例子。假设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]之外的所有顶点。我应该如何对最小外壳进行后期处理以实现“完整”外壳,而不会将复杂性增加到O(n^2)

显然,将GS算法更改为包括共线点(>0到>=0或这里是一个O(logh)-时间算法,给定一个具有h个排序顶点的凸包和一个查询点,测试查询点是否位于外壳上。从外壳上,通过平均其三个顶点计算内部的一个点。将该点称为原点。将平面划分为由从原点到外壳顶点的光线包围的楔体。使用二进制使用方向测试进行搜索,以确定查询点属于哪个楔块。测试它是否位于该楔块的外壳段上


如果您已经实施了格雷厄姆扫描,则仅通过更改测试即可保留共线点,但您需要确定相对于原点的角度,该原点与其他两个外壳点不共线。可以通过取三个不共线的输入点的平均值来获得该点。

nking,我发现当你将比较改为包含0,并(更靠近第一个)断开到角点的距离(甚至仅仅通过比较坐标),那么只有最后一条边受到影响,特别是它跳过了边点

在您的示例中,确实您最终考虑了点5、1和2,但该算法将跳过点1而不是点2(因为5-1-2是顺时针旋转),因此生成的外壳为0 3 6 7 8 5 2

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


当所有点都共线时,可能会出现一种特殊情况-这取决于您是希望包含两次边点(向前和向后)还是仅包含一次。

您说“显然,更改GS算法以包含共线点。”(>0到>=0或这是一个计数器GS示例。当极轴角相等时,无论您如何对点进行排序,在关闭外壳之前,您将被迫选择错误的点,因此您将始终得到一个不完整的外壳。请使用提供的示例尝试GS。嗯,如果我使用排序顺序036748521并仅丢弃点on严格右转,似乎效果不错。但问题是如何获得排序顺序。请参阅我的修订答案。请使用提供的示例尝试GS。“这样一个点可以通过取三个不共线的输入点的平均值来获得”-新点仍然可以与其他输入点共线(甚至与输入点相同),你如何找到正确的三个输入点?@aditsu这不可能发生,因为输入点是一个凸壳,三个非共线点的平均值必然位于内部。哦,“输入”实际上是指“凸壳的输出”“。但是,请稍候,由于原始Graham扫描,您当时已经丢失了边缘点。@aditsu重点是:我们查询所有原始输入点,但查询结构基于不完整集。