【问题标题】:How to get the largest simple convex polygon from a complex polygon?如何从复杂多边形中得到最大的简单凸多边形?
【发布时间】:2021-12-28 19:45:13
【问题描述】:

给定一个可能是凹面并且可能有孔的多边形,我如何获得由其顶点子集组成的最大简单凸多边形?

即,给定简单的凹多边形:

p = Polygon([(30, 2.01), (31.91, 0.62), (31.18, -1.63), (28.82, -1.63), (28.09, 0.62),  (30, -0.001970703138552843)])

我想要最大的简单凸多边形(可能相同但没有最左边的点 (28.09, 0.62) 并将 (28.82, -1.63) 替换为 (30, -1.63))。像这样:

这只是一个未测量的示例。可能实际上 (28.09, 0.62)(30, 2.01) 都必须删除,如果这会产生更大的区域,例如可能由切割造成的这里用绿线表示:

但是,假设第一次切割是正确的,如果我们在“另一边”添加一个洞:

p = Polygon([(30, 2.01), (31.91, 0.62), (31.18, -1.63), (28.82, -1.63), (28.09, 0.62),  (30, -0.001970703138552843)], 
[[(30.1,0.62), (30.1,1.25), (31, 1.25), (31,0.62)]])

在这种情况下,最大的简单凸多边形可能会旋转到多边形的另一半,因此它不会丢弃前一个点,而是会丢弃 (30, 2.01) 并替换 ( 31.91, 0.62)(31, -1.63) 之间有一个点。显然,在这种情况下,它会抛出孔的所有顶点。

评论

任何在多边形内部保持完整的孔都会根据定义为多边形引入一个凹角。如果输入多边形中有一个洞,则最多有一条边可以保留在输出多边形中(并且,根据“简单多边形”的定义,该边将是外部坐标的成员)。

这个定义有点草率,所以我应该尽量清楚。所有内部和外部顶点都是输出简单多边形中可能点集的成员。所有与内部和外部边界相交的点(它们之间的线段)也是如此。点的选择应产生一个简单的凸多边形,该多边形内接在源多边形中。如果源多边形是一个简单的凸多边形,它应该返回与输出相同的多边形。很有可能拥有面积相等的整个候选解决方案系列。如果它们是最大的,它们中的任何一个都可以。

草图方法:如果您像示例中的绿线一样丢弃切割,那么剩下的就是从线段中删除带有投影的点。因此,您可以将所有内部和外部点视为一个集合,并排除其中 0 个或更多的子集,然后找到最大的凸多边形。因此,要么只排除该点,要么当排除一个点产生一个新的凹角时,从该角度的那一侧的线段投影到多边形另一侧的线段(这是用于产生第一个示例解决方案图像)。重新审视绿线切割,这些线将多边形平分并与凹角的中心点相切。如果这个二等分必须垂直于从中心点到剩余多边形质心的线,那么这并不复杂。但我不确定那是真的。无论如何,这需要考虑很多多边形。

注意:起初我标记了一个重复,认为这本质上是另一个问题的更复杂版本(Finding largest subset of points forming a convex polygon,但有漏洞)。但是,这种方法不允许在解决方案中添加新顶点。例如,本文中第一个形状的 Delaunay 三角剖分不会产生新点:

[ 'POLYGON ((28.09 0.62, 28.82 -1.63, 30 -0.001970703138552843, 28.09 0.62))', 
  'POLYGON ((28.09 0.62, 30 -0.001970703138552843, 30 2.01, 28.09 0.62))', 
  'POLYGON ((30 2.01, 30 -0.001970703138552843, 31.91 0.62, 30 2.01))', 
  'POLYGON ((31.91 0.62, 30 -0.001970703138552843, 31.18 -1.63, 31.91 0.62))', 
  'POLYGON ((28.82 -1.63, 31.18 -1.63, 30 -0.001970703138552843, 28.82 -1.63))']

提供的尽可能重复的文章仅计算点的子集以找到最大的凸包——即,它没有在线上引入点。

【问题讨论】:

  • 你能举一个例子来说明你希望得到的形状是什么样的吗?一个包含原始顶点子集的简单凸多边形听起来很像 "convex hull" 对我来说
  • 嘿,Cory,我将它添加到第一个样本中.. 问题是,我不确定这个结果是否是 最大的.. 但很可能是。

标签: python shapely


【解决方案1】:

我不确定您的问题是否得到了明确的说明(或者更确切地说,您描述它的方式被简化为一个众所周知的、更简单的问题)。

首先,让我向您介绍凸包的概念:

给定一个点列表,凸包是包含所有点的最小凸(简单)多边形。

CH 的形状本质上就是您在这些点周围“放置一根橡皮筋”以使其接触外部点时所获得的形状。

现在,CH 有一个简单的属性:

给定一组点,它们的 CH 的面积大于(或等于)可能形成的任何其他(简单)多边形的面积。

这是真的,因为 i) 如果它们形成一个凸多边形,那么它们根据定义形成 CH。 ii) 否则,它们会形成一些非凸形。从视觉上看,您可以通过“移除三角形”从 CH 到非凸形形状,该三角形由 CH on 上的 2 个点和一个 inner 点组成。所以你正在删除区域,所以 CH 的区域最大。

所以,由所有顶点组成的最大凸多边形是CH。

现在,关于选择原始顶点的子集:这显然会给你一个更小(或相等)大小的形状。所以选择任何子集是没有意义的,真的。

此外,漏洞并不会真正影响这个论点。保持整体显然对您有利,因为您可以添加孔周围的区域。

所以,最终的答案(除非我遗漏了什么)是您所需要的只是凸包。

幸运的是,有一些很好的 python 库用于计算、绘图和处理凸包。

【讨论】:

  • 是的,我实际上是从凸包开始的。这样做的问题是它不排除由其点集描述的多边形外部的孔或表面。我不是在寻找一组点的凸外包装,而是在寻找内接在我的多边形中的最大凸多边形(实际上可能就是全部,如果它是一个没有孔的凸多边形。)
  • 具体来说,想象一个像字母 H 这样的形状,其中“H”的每个部分都有一个厚度。它的凸包是一个矩形,如 ⬛ 。但这包含不在“H”中的点,这对我来说是个问题。
  • 我投了你一票,因为这是一个可爱而深思熟虑的答案:)
  • 哦,我现在明白你的意思了。让我试试看我能不能想出什么办法
  • 1.首先对您的形状进行 Delaunay 三角剖分,忽略孔。现在,将孔视为一个单独的形状。 2. 找到所有与孔相交的三角形(一个像样的库应该能够做到这一点)。 3. 把这些三角形扔掉,然后构造一个没有它们的新“子集”多边形。 4. 计算新形状的“最大凸子多边形”。这是你的答案。要执行 4.,请查看 this question
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-27
  • 2014-03-13
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
相关资源
最近更新 更多