非凸多边形内最大的圆
如何找到可以容纳在凹多边形内的最大圆?
只要能够实时处理具有约 50 个顶点的多边形,暴力算法就可以。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如何找到可以容纳在凹多边形内的最大圆?
只要能够实时处理具有约 50 个顶点的多边形,暴力算法就可以。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(7)
解决这个问题的关键是首先进行观察:适合任意多边形的最大圆的中心是以下点:
为什么?因为圆的边缘上的每个点到圆心的距离都相等。根据定义,最大的圆将具有最大的半径,并且至少在两个点上接触多边形,因此如果您找到距离多边形最远的点,您就找到了圆的中心。
这个问题出现在地理学中,并且可以以任意精度迭代解决。它被称为“难以到达的极点”问题。请参阅难以到达的极点:地球上最偏远地点的计算算法。
基本算法的工作原理如下:
需要注意的是,如何测试一个点是否在多边形内部:这部分问题的最简单解决方案是将一条射线投射到该点的右侧。如果它穿过奇数条边,则它在多边形内。如果是偶数,则在外面。
此外,就测试到任何边的距离而言,您需要考虑两种情况:
(2)很容易。到边缘的距离是到两个顶点的距离中的最小值。对于 (1),该边缘上最近的点将是从您正在测试的点开始与边缘以 90 度角相交的点。请参阅点到射线或线段的距离。
The key to solving this problem is first making an observation: the center of the largest circle that will fit inside an arbitrary polygon is the point that is:
Why? Because every point on the edge of a circle is equidistant from that center. By definition, the largest circle will have the largest radius and will touch the polygon on at least two points so if you find the point inside furthest from the polygon you've found the center of the circle.
This problem appears in geography and is solved iteratively to any arbitrary precision. Its called the Poles of Inaccessibility problem. See Poles of Inaccessibility: A Calculation Algorithm for the Remotest Places on Earth.
The basic algorithm works like this:
One note, How to test if a point is inside the polygon or not: The simplest solution to this part of the problem is to cast a ray to the right of the point. If it crosses an odd number of edges, it's within the polygon. If it's an even number, it's outside.
Also, as far as testing the distance to any edge there are two cases you need to consider:
(2) is easy. The distance to the edge is the minimum of the distances to the two vertices. For (1), the closest point on that edge will be the point that intersects the edge at a 90 degree angle starting from the point you're testing. See Distance of a Point to a Ray or Segment.
如果有人正在寻找实际的实现,我设计了一种更快的算法,可以在给定的精度下解决这个问题,并将其作为一个 JavaScript 库。它类似于@cletus描述的迭代网格算法,但它保证获得全局最优,并且在实践中也快了20-40倍。
看看: https://github.com/mapbox/polylabel
In case anyone is looking for a practical implementation, I designed a faster algorithm that solves this problem for a given precision and made it a JavaScript library. It's similar to the iterative grid algorithm described by @cletus, but it's guaranteed to obtain global optimum, and is also 20-40 times faster in practice.
Check it out: https://github.com/mapbox/polylabel
摘要:理论上,这可以在 O(n) 时间内完成。实际上,您可以在 O(n log n) 时间内完成。
广义 Voronoi 图。
如果您将多边形的顶点和边视为一组位点,并将内部细分为“最近邻单元”,那么您将得到所谓的(广义)Voronoi 图。 Voronoi 图由节点和连接节点的边组成。节点的间隙是到其定义的多边形面的距离。
(这里的多边形即使有孔,原理仍然有效。)
现在的关键观察是最大内切圆的中心接触多边形的三个面(顶点或边),并且没有其他面可以更接近。因此中心必须位于 Voronoi 节点上,即间隙最大的节点。
在上面的示例中,标记最大内切圆中心的节点接触多边形的两条边和一个顶点。
顺便说一句,中轴是 Voronoi 图,其中删除了从反射顶点发出的 Voronoi 边。因此,最大内接圆的中心也位于中轴上。
来源:我的一篇博客文章,涉及概括某点的最大内切圆。在那里您可以找到有关 Voronoi 图及其与最大内切圆的关系的更多信息。
算法与
您实际上可以计算 Voronoi 图。 Fortune 给出了点和线段的最坏情况 O(n log n) 算法,Voronoi 图的扫描线算法,SoCG'86。 Held 发布了软件包 Vroni,预期为 O (n log n) 时间复杂度,实际上也计算最大内切圆。 boost 中似乎有一个实现, 也。
对于简单多边形(即没有孔),Chin 等人提出了一种在 O(n) 时间内运行的时间最优算法,在线性时间内查找简单多边形的中轴,1999。
蛮力。
但是,正如您所说,您是使用暴力算法就可以了:简单地尝试所有三元组(顶点和边)怎么样?对于每个三元组,您找到候选 Voronoi 节点,即到三个位点的等距位点,并检查是否有任何其他位点与候选最大内切圆相交。如果存在交叉点,您将解雇该候选人。从所有三胞胎中找出最大的一个。
请参阅我的硕士论文中的第 3 章,了解有关计算等距位点的更多详细信息三个站点。
Summary: In theory, this can be done in O(n) time. In practice you can do it in O(n log n) time.
Generalized Voronoi diagrams.
If you consider the vertices and edges of the polygon as a set of sites and tessellate the interior into the "nearest neighbor cells" then you get the so-called (generalized) Voronoi diagram. The Voronoi diagram consists of nodes and edges connecting them. The clearance of a node is the distance to its defining polygon faces.
(Here the polygon even has holes; the principle still works.)
The key observation now is that the center of the maximum inscribed circle touches three faces (vertices or edges) of the polygon, and no other face can be closer. So the center has to lie on a Voronoi node, i.e, the node with the largest clearance.
In the example above the node that marks the center of the maximum inscribed circle touches two edges and a vertex of the polygon.
The medial axis, by the way, is the Voronoi diagram with those Voronoi edges removed that emanate from reflex vertices. Hence, the center of the maximum inscribed circle also lies on the medial axis.
Source: A blog article of mine that deals with generalizations of maximum inscribed circles at some point. There you can find more on Voronoi diagrams and their relation to maximum inscribed circles.
Algorithms & implementations.
You could actually compute the Voronoi diagram. A worst-case O(n log n) algorithm for points and segments is given by Fortune, A sweepline algorithm for Voronoi diagrams, SoCG'86. Held published the software package Vroni with an expected O(n log n) time complexity, which actually computes the maximum inscribed circle, too. And there seems to be an implementation in boost, too.
For simple polygons (i.e., without holes) a time-optimal algorithm that runs in O(n) time is due to Chin et al., Finding the Medial Axis of a Simple Polygon in Linear Time, 1999.
Brute force.
However, as you stated that you are fine with a brute-force algorithm: What about simply trying out all triplets of sites (vertices and edges). For each triplet you find candidate Voronoi nodes, i.e., equidistant loci to the three sites and check whether any other site would intersect the candidate maximum inscribed circle. If there is an intersection you dismiss the candidate. Take the greatest you can find over all triplets.
See chapter 3 in my Master thesis about more details on computing equidistant loci for three sites.
O(n log(n)) 算法:
An O(n log(n)) algorithm:
我实现了一段基于cv2的python代码,以获取掩模/多边形/轮廓内的最大/最大内切圆。它支持非凸/空心形状。
红色圆圈是最大内切圆
来源:https://gist.github.com/DIYer22/f82dc329b27c2766b21bec4a563703cc
I implemented a piece of python code based on cv2 to get the maximum/largest inscribed circle inside mask/polygon/contours. It supports non-convex/hollow shape.
Red circle is max inscribed circle
Source: https://gist.github.com/DIYer22/f82dc329b27c2766b21bec4a563703cc
我使用直骨架将图像放置在多边形内,分三个步骤:
尝试一下:https://smartdiagram.com/simple-infographics-3d -charts-2/
I used Straight Skeletons to place an image inside a polygon with three steps:
Try it at: https://smartdiagram.com/simple-infographics-3d-charts-2/
O(n log X) 算法,其中 X 取决于您想要的精度。
对圆的最大半径 R 进行二分搜索:
在每次迭代中,对于给定的半径 r,将每条边 E“向内”推 R,以获得 E'。对于每条边 E',将半平面 H 定义为多边形“内部”的所有点的集合(使用 E' 作为边界)。现在,计算所有这些半平面 E' 的交集,这可以在 O(n) 时间内完成。如果交点非空,那么如果以交点中的任意点为圆心绘制半径为 r 的圆,则该圆将位于给定多边形内。
An O(n log X) algorithm, where X depends on the precision you want.
Binary search for largest radius R for a circle:
At each iteration, for a given radius r, push each edge E, "inward" by R, to get E'. For each edge E', define half-plane H as the set of all points "inside" the the polygon (using E' as the boundary). Now, compute the intersection of all these half-planes E', which could be done in O(n) time. If the intersection is non-empty, then if you draw a circle with radius r using any point in the intersection as the center, it will be inside the given polygon.