将圆连接成多边形的算法
Algorithm for joining circles into a polygon
将重叠的圆组合成多边形的最佳方法是什么?
我得到了一个具有固定直径的圆的中心点列表。
我需要将任何重叠的圆连接在一起,并输出生成的多边形中的点列表。
这似乎是一个相当普遍的问题(GIS 系统、矢量等)。这可以通过 Google 地图 API 来完成,但我正在寻找实际的算法。
我试图通过计算每个圆周围的点来解决这个问题。
然后删除位于任何圆圈内的所有点。
这为我提供了所需多边形中正确的点列表。
但是,点的顺序是这个解决方案的问题。每个圆的点都存储在一个数组中。将它们与 2 个重叠的圆正确合并是相对简单的。然而,当处理多个重叠的圆圈时,它会变得复杂。
希望您有一些想法来使这个解决方案有效或使用另一种算法来达到预期的结果。
提前致谢!
您应该可以使用如下方法:
- 首先,确定属于同一组重叠圆圈的圆圈。显然,如果两个圆心的绝对距离小于它们的半径之和,则两个圆重叠。对于每个圆圈,将它迭代的圆圈存储在 hashmap/dictionary 中。 (您可以使用 union-find algorithm, or disjoint sets 将其扩展到整个圈子组,但这并不是真正需要的。)
- 创建属于一个圆的点时,记住每个点的左右邻居。您只需将它们存储在有序数组中即可免费获得。
- 删除 "inner" 个点,即距离与第一个圆相交的任何圆心小于一个半径的点。
- 将那些未被移除的内部点的邻居标记为圆的 "loose ends"。
- 将未移除的点(包括松散的末端)连接到它们原来的左右相邻点。
- 对于每个松散端点,找到同一组中不同圆的最近松散端并将它们连接起来。
这里有一张图片来说明该方法。
- 红点是 "inner" 个被移除的点
- 蓝点 "loose ends" 是 "inner" 点的邻居;每个 "loose end" 都有另一个 "loose end" 不同的圆圈,距离 "point-distances" 不到两个
- 绿点可以很容易地按照它们在圆圈周围的排列顺序连接到它们的邻居(包括 "loose ends")。
您可以进一步减少可能组合的数量,方法是区分 left 和 right 松散的末端,并利用每个 left 松散的事实一个圆圈的末端必须连接到另一个圆圈的右端。对于一组中的 n
个圆圈,只剩下 (n-1)!
种连接这些圆圈的方法,而不管每个圆圈的点数如何。
如果您只考虑组中那些实际上与松散端的圆相交的圆(只需将它们存储在 hashmap/dictionary 中),即使这样也可以进一步减少。因此,如果您有 n
个圆圈平均与 k
个其他圆圈相交,则只有 n*k
种可能的组合。
你也可以利用另一个松散端的距离不能超过圆上两点之间距离的两倍。我们称此距离为 d
,然后您可以创建分辨率为 d
的空间地图(例如散列图或二维数组)并将每个松散的一端分配给该地图中的单元格,然后将另一个松散的一端分配给该地图中的单元格end 必须与第一个松散端的周围单元格中的一个相同。
因此,点之间可以相互连接的方式的数量大大减少(特别是,它们在最终图像中的连接方式是不允许的开始):即使使用蛮力,这也应该是可行的,除非你在同一组中有 很多 的重叠圆圈,并且你可以使用更智能的 nearest-neighbor search 算法.
更新:一段时间后回顾这个答案,您似乎可以很容易地确定 "loose end" 点的匹配对:假设您在圆圈 A 中有一个 "right" 松散端,那么匹配 "left" 松散端必须属于其半径与下一个 "inner" 点重叠到第一个 "loose end" 的圆。因此,如果您将该关系存储在另一个映射中,您可以立即确定匹配的松散端。 (如果一个内点与多个其他圆重叠,则地图应包含重叠最多的圆。)
这是 O(n log n) 时间算法的草图。
用你最喜欢的algorithm/library计算圆心上的Delaunay triangulation。
删除不重叠的圆圈之间的边。
绕着每个连通分量的无限面走一圈。使用 doubly connected edge list 表示很容易做到这一点,其中边列表的排序用于指示平面图的拓扑结构。这个边界上的每一个half-edge都变成一个顶点,属于它的尾点的弧段结束,属于它的头点的弧段开始。
(可选)用折线近似每个弧段
如果 Google 的任何人正在阅读本文,请注意我没有查看相关代码。
将重叠的圆组合成多边形的最佳方法是什么?
我得到了一个具有固定直径的圆的中心点列表。
我需要将任何重叠的圆连接在一起,并输出生成的多边形中的点列表。
这似乎是一个相当普遍的问题(GIS 系统、矢量等)。这可以通过 Google 地图 API 来完成,但我正在寻找实际的算法。
我试图通过计算每个圆周围的点来解决这个问题。
然后删除位于任何圆圈内的所有点。
这为我提供了所需多边形中正确的点列表。
但是,点的顺序是这个解决方案的问题。每个圆的点都存储在一个数组中。将它们与 2 个重叠的圆正确合并是相对简单的。然而,当处理多个重叠的圆圈时,它会变得复杂。
希望您有一些想法来使这个解决方案有效或使用另一种算法来达到预期的结果。
提前致谢!
您应该可以使用如下方法:
- 首先,确定属于同一组重叠圆圈的圆圈。显然,如果两个圆心的绝对距离小于它们的半径之和,则两个圆重叠。对于每个圆圈,将它迭代的圆圈存储在 hashmap/dictionary 中。 (您可以使用 union-find algorithm, or disjoint sets 将其扩展到整个圈子组,但这并不是真正需要的。)
- 创建属于一个圆的点时,记住每个点的左右邻居。您只需将它们存储在有序数组中即可免费获得。
- 删除 "inner" 个点,即距离与第一个圆相交的任何圆心小于一个半径的点。
- 将那些未被移除的内部点的邻居标记为圆的 "loose ends"。
- 将未移除的点(包括松散的末端)连接到它们原来的左右相邻点。
- 对于每个松散端点,找到同一组中不同圆的最近松散端并将它们连接起来。
这里有一张图片来说明该方法。
- 红点是 "inner" 个被移除的点
- 蓝点 "loose ends" 是 "inner" 点的邻居;每个 "loose end" 都有另一个 "loose end" 不同的圆圈,距离 "point-distances" 不到两个
- 绿点可以很容易地按照它们在圆圈周围的排列顺序连接到它们的邻居(包括 "loose ends")。
您可以进一步减少可能组合的数量,方法是区分 left 和 right 松散的末端,并利用每个 left 松散的事实一个圆圈的末端必须连接到另一个圆圈的右端。对于一组中的 n
个圆圈,只剩下 (n-1)!
种连接这些圆圈的方法,而不管每个圆圈的点数如何。
如果您只考虑组中那些实际上与松散端的圆相交的圆(只需将它们存储在 hashmap/dictionary 中),即使这样也可以进一步减少。因此,如果您有 n
个圆圈平均与 k
个其他圆圈相交,则只有 n*k
种可能的组合。
你也可以利用另一个松散端的距离不能超过圆上两点之间距离的两倍。我们称此距离为 d
,然后您可以创建分辨率为 d
的空间地图(例如散列图或二维数组)并将每个松散的一端分配给该地图中的单元格,然后将另一个松散的一端分配给该地图中的单元格end 必须与第一个松散端的周围单元格中的一个相同。
因此,点之间可以相互连接的方式的数量大大减少(特别是,它们在最终图像中的连接方式是不允许的开始):即使使用蛮力,这也应该是可行的,除非你在同一组中有 很多 的重叠圆圈,并且你可以使用更智能的 nearest-neighbor search 算法.
更新:一段时间后回顾这个答案,您似乎可以很容易地确定 "loose end" 点的匹配对:假设您在圆圈 A 中有一个 "right" 松散端,那么匹配 "left" 松散端必须属于其半径与下一个 "inner" 点重叠到第一个 "loose end" 的圆。因此,如果您将该关系存储在另一个映射中,您可以立即确定匹配的松散端。 (如果一个内点与多个其他圆重叠,则地图应包含重叠最多的圆。)
这是 O(n log n) 时间算法的草图。
用你最喜欢的algorithm/library计算圆心上的Delaunay triangulation。
删除不重叠的圆圈之间的边。
绕着每个连通分量的无限面走一圈。使用 doubly connected edge list 表示很容易做到这一点,其中边列表的排序用于指示平面图的拓扑结构。这个边界上的每一个half-edge都变成一个顶点,属于它的尾点的弧段结束,属于它的头点的弧段开始。
(可选)用折线近似每个弧段
如果 Google 的任何人正在阅读本文,请注意我没有查看相关代码。