Java:找到凸多边形的最外层顶点

Posted

技术标签:

【中文标题】Java:找到凸多边形的最外层顶点【英文标题】:Java: Finding the Outermost Vertices of a Convex Polygon 【发布时间】:2012-04-15 15:14:20 【问题描述】:

原帖:

我试图找到一个凸多边形的最外层顶点(与多边形外的一个点 P 相关)。目前,我只关心矩形(不过,我想要一种适用于任何凸多边形的算法)。

我的计划是构建一条从外部点P到中心点C的线。根据这个参考线,我将构建从点 P 到点 12 的线34。由于点 24参考线 之间的夹角最大(最正)和最小(最负),它们将是标识为最外层的顶点

这是最适合这项工作的算法吗?如何从参考角度计算角度(最好在 Java 中)?


更新说明:

我已经画了线(参考线为红色)。如您所见,从 P2 的线在 参考线 的一侧创建最大角度,而从 P 到 4 创建另一侧的最大角度。因此,这些是最外层的顶点

【问题讨论】:

嗯,两点 A 和 B 之间的角度应该是 atan2(b.y,b.x) - atan2(a.y,a.x) 但简单地取最大和第二大角度可能无法解决所有情况的问题......我认为。 为什么不只考虑从 P 到 C 画线的最远点? 我想这也可以。 “我正在尝试找到凸多边形的最外层顶点(相对于多边形外部的点 P)。” - 我不明白。你能指点参考吗? 【参考方案1】:

三角函数的使用非常缓慢。您应该使用另一个角度比较。

对于两个平面向量之间的夹角:

cos(OA, OB) = (OAx * OBx + OAy* OBy ) / sqrt((OAx2 + OAy2)* (OBx sub>2 + OBy2))

我认为,您可以比较具有余弦的角度。

【讨论】:

【参考方案2】:

这几乎是convex hull 的问题。您将在多边形周围寻找一组顶点 (x1, x2)。将应用的方法称为“快速船体”,类似于快速排序(每次我们通过时我们都会划分我们的点区域)。 P 可以用作任意起点与其平行终点之间的中点也是一个安全的假设,因此您将在 P 周围得到一个凸包.

生成一些可靠的 Java 需要一段时间(根据我的偶然性),但我认为 Wikipedia 条目将为您提供一个很好的起点。

【讨论】:

对不起...我不认为这与凸包问题非常相似。形状的边界是已知的,我没有使用任何 Minkowski 和。此外,P 计算的起点。我正在寻找与外部点P 相关的最外层顶点。因此,操作是迭代的,不需要逐步除法。 点 1,2,3,4 的凸包是已知的。点 P,1,2,3,4 的凸包是未知的。我认为最外面的点是 P,1,2,3,4 的凸包中与 P 相邻的两个点。注意 1 不是 P,1,2,3,4 的凸包的一部分。 啊。我现在知道了。那么凸包算法是解决这个问题的最快方法吗? @Peter:这将是一个非常快速的解决方法,是的; Quick-hull 平均可以达到 O(N*lg(N)) 的性能,最坏的情况是 O(n^2)(不太可能)。【参考方案3】:

我解决的问题如下:

            // code simplified for demonstration
            double angleBetweenVertices;
            double maxAngleBetweenVertices;
            vectorA.setStartingPoint(outerPoint);
            vectorA.setTerminationPoint(polygonCenter);
            vectorB.setStartingPoint(outerPount);

            // For each vertex, calculate the angle between the outer point, the polygon's center and the vertex
            for (Point2D.Double vertex : vertices)     
                vectorB.setTerminationPoint(vertex);
                double angleBetweenVertices = 
                    Math.toDegrees(
                        Math.atan2(
                            (vectorA.perpDotProduct(vectorB)),
                            (vectorA.dotProduct(vectorB)) 
                        )
                    );

                // Update the min and Max
                if (angleBetweenVertices >= maxAngleBetweenVertices) 
                    maxVertex = vertex;
                    maxAngleBetweenVertices = angleBetweenVertices;
                 else if (angleBetweenVertices <= minAngleBetweenVertices) 
                    minVertex = vertex;
                    minAngleBetweenVertices = angleBetweenVertices;
                
            

【讨论】:

以上是关于Java:找到凸多边形的最外层顶点的主要内容,如果未能解决你的问题,请参考以下文章

为多边形轮廓绘制圆的最有效方法

ZOJ 3537 Cake 求凸包 区间DP

Oracle 空间 - 逆时针检查多边形顶点

多边形扫描算法

9-11

查找给定多边形 w.r.t 的两个“边界”顶点。已知(光源)点