问题 确定是否可以使用单个三角形扇形绘制2d多边形


起初,我认为这个问题等同于确定多边形是否是凸面,但似乎仍然可以通过一个三角形扇形绘制非凸多边形。 考虑这种形状,一个非凸多边形。可以很容易地想象一些中心点区域允许用三角形扇形绘制这个多边形(尽管会有其他中心点不会)。给定一个固定的中心点,我希望能够确定定义多边形的2d点的集合是否允许使用单个三角形扇形绘制它。

似乎关键是要确保从中心点到任何顶点绘制的线条没有“妨碍”,这意味着顶点的其他边缘线。但是,重要的是尽可能使计算成本低廉,并且我不确定这样做是否有一个很好的数学捷径。

最终,我将要让多边形的顶点移动,并且我需要确定一个顶点被允许移动的“边界”,因为其余的是固定的(并且可能稍后甚至允许直接同时反应移动)还有2个邻居),以保持多边形能够在单个三角形扇形中绘制。但这是未来,希望对整个多边形的测试可以分解为一个计算子集,以假设已经凸多边形来测试单个顶点运动的边界。


9590
2018-04-25 17:07


起源

这是一个有趣的问题。或许接近它的一种方法是首先用例如凸面计算凸包。一个 格雷厄姆扫描。然后定义最接近所有顶点的算术平均值的顶点作为中心顶点。最后看看从中心顶点到任何其他顶点的线段是否与凸包的边缘相交。 - smocking
实际上,我意识到凸壳当然会给你错误的边缘。你已经知道了边缘吗? - smocking
如果将每条边视为一个点(在齐次坐标系中),则可以使用凸包算法来解决问题。如果任何多边形边缘对应于由其他边缘形成的船体内的“负点”,则无法将多边形绘制为三角形扇形。 - comingstorm


答案:


如果从锚点到每个顶点的角度沿相同方向移动,则可以将多边形绘制为三角形扇形。测试这个的最简单方法是检查连续顶点的叉积的点积。

它看起来像这样:

vector lastCross = cross_product( vector(vertex[0] - center), vector(vertex[numVerts - 1] - center) );

canBeFan = true;
for (n = 1; canBeFan && n < numVerts; ++n) {
    vector testCross = cross_product( vector(vertex[n] - center), vector(vertex[n - 1] - center) );
    if (0.0 >= dot_product(testCross, lastCross) ) {
        canBeFan = false;
    }
}

2
2018-04-25 17:35



这不是凸多边形的测试吗? - user173342
@ user173342不,测试凸多边形是类似的,但这是测试每对边的角度之间的差异。 - IronMensan


你要找的房产是“星形“。星形多边形是通过具有整个多边形可见的点来定义的。

要测试多边形是星形,可以构造整个多边形可见的区域。该区域将是一个凸集,因此您可以将其与半平面相交 O(log(n))

这意味着您可以与边缘形成的半平面相交,并检查生成的可见区域是否为非空 O(n log n)


13
2018-04-25 17:25



并且由于指定了固定的中心点,您可以简单地确保该点位于所有半空间中。 - bames53


看起来所有潜在的中心点都需要位于多边形每个边缘的内侧。因此,将所有边缘视为半空格,并确定它们的交点是否为空。

正如@jpalecek所说,这个术语是 星形。如果您的多边形是星形,则会有一个凸多边形(原始内部),其点可以查看原始的所有边 - 相反,如果不存在这样的子多边形,则原始不是星形,你不能用三角扇绘制它。

确定这个子多边形基本上是一个  应用 凸壳 问题;它可以用来计算 O(n log n)


1
2018-04-25 17:37