【问题标题】:seeking approximate algorithm to find largest clear circle in an area寻找近似算法来找到一个区域中最大的清晰圆
【发布时间】:2015-06-22 16:04:26
【问题描述】:

相关:Is there a simple algorithm for calculating the maximum inscribed circle into a convex polygon?

我正在编写一个图形程序,其目标是艺术而非数学。它使用几何图元,例如线段或小角度的弧线,逐步组成图片。在此过程中,它会寻找开放区域以填充更多细节;随着可用的开放区域变得更小,细节变得更精细,所以它是松散的分形。

在给定的步骤中,为了决定下一步做什么,我们想知道:仍然没有现有几何图元的最大圆形区域在哪里?

问题的一些限制

  • 不需要精确。一个足够接近的答案就可以了。
  • 不精确应该在保守方面犯错:几乎最大的圆圈是可以接受的,但不是完全空的圆圈是不可接受的。
  • CPU 效率是重中之重,因为它会经常被调用。
  • 程序将在浏览器中运行,因此内存效率也是一个优先事项。
  • 我必须设置细节级别的限制,大概是受内存空间的限制。
  • 我们可以以任何所需的方式跟踪已绘制的图元,例如空间索引。不需要这些的精确性;例如存储边界框而不是弧线就可以了。然而,我们拥有的精度越高越好,因为它可以让程序绘制到更高级别的细节。但是,鉴于图元的数量会随着细节水平呈指数增长,我们希望过去细节的存储随着图元的数量线性增加。

总结优先顺序

  1. 内存效率
  2. CPU 效率
  3. 精度

附言

我用圆圈来设计这个问题,但如果更容易找到最大的透明黄金矩形(或黄金椭圆),那也可以。

附言

这张图片让我对我想要实现的目标有所了解。这是一个卷须绘制程序的开始,其中决定在哪里发芽以及多大, 不考虑剩余的开放空间。但现在我们想知道,接下来哪里有画卷须的空间,有多大?之后呢?

【问题讨论】:

    标签: algorithm graphics computational-geometry


    【解决方案1】:

    一种非常有效的方法是将您的区域递归地划分为矩形子区域,并在必要时将它们分割以将占用区域与未占用区域分开。然后,您只需要每次都跟踪最大的未占用区域。见https://en.wikipedia.org/wiki/Quadtree - 但你不需要分成正方形。

    给定任何矩形,您可以在其内部画一条线,这样该线任一侧的矩形中至少有一个是黄金矩形。因此,您可以在一个矩形内递归地建立分区,以便除一个由分区形成的矩形之外的所有矩形都是黄金矩形,并且剩下的添加矩形非常小。您可以这样做来创建类似四叉树的结构,其中几乎所有剩余的矩形都是黄金矩形。

    【讨论】:

      【解决方案2】:

      这似乎是一种随机算法可能会有所帮助的情况。随机选择点,如果由于某种原因不合适,则拒绝并选择更多点,然后找到从您的选择到已包含的每个数字的最小距离。具有最大值的随机点将是您的选择。

      随着图形复杂度的增加,样本点的数量可能不得不增加。

      可以通过检查好选择附近的点来改进随机算法。继续检查邻居,直到无法再改进为止。

      【讨论】:

      • 好的。但是,随着已经包含的图形数量的增加(随着详细程度呈指数增长),找到从每个随机点到已包含的每个图形的最小距离可能会成为一项非常昂贵的操作。你有什么想法让这更容易处理吗? (顺便说一句,我刚刚在问题中添加了一张图片。)
      • 一旦你随机选择了一个中心,你可以通过二分搜索找到最大半径,如果你可以确定一个圆是否包含另一个元素。您提供的示例图形很有趣,因为它连接到边缘,因此当且仅当它与图形相交时,圆才包含一个元素,这很容易通过在绘制圆之前检查圆上点的颜色来确定。你的程序是这样的吗?
      【解决方案3】:

      这是一种简单的方法,每次更新使用固定数量的内存和时间,无论您使用多少绘图图元。需要多少内存(以及每次更新的时间)可以根据您需要多高的“分辨率”来控制:

      1. 将空间划分为点网格。我们将维护一个二维数组 d[],它记录从网格点 (x, y) 到条目 d[x, y] 中任何已绘制图元的最小距离。最初,将此数组中的每个元素设置为无穷大(或某个巨大的数字)。
      2. 每当您绘制一些图元时,迭代所有网格点 (x, y),计算从 (x, y) 到刚刚绘制的图元的最小距离(或一些保守的近似值)。例如,如果刚刚绘制的图元是以 (p, q) 为中心的半径为 r 的圆,那么这个距离将为 sqrt((x-p)^2 + (y-q)^2) - r。然后用这个新的距离值更新 d[x, y]如果它小于它的当前值
      3. 可以在不接触任何已绘制图元的情况下绘制最大圆的网格点是距离迄今为止绘制的任何图元最远的网格点。要找到它,只需扫描 d[] 以找到它的最大值,并记下相应的索引 (x, y)。 d[x, y] 将是您可以安全地用于该圆的最大半径。

      根据需要重复步骤 2 和 3。

      几点:

      • 对于具有面积的图元,您可以将 0 或负值分配给图元内部网格点对应的所有 d[x,y]。
      • 对于任何凸图元,您通常可以通过从刚绘制的图元边界“向外”扫描行(或列)来避免更新大部分 d[] 数组:从当前网格点到图元的距离永远不会减少,所以如果这个距离变得大于 d[] 中的先前最大值,那么我们知道我们可以停止扫描这一行,因为我们将在其上计算的进一步距离值可能不会小于它的现有距离。

      【讨论】:

      • 我喜欢这个想法,尤其是最后一个要点。它让我想起了一些扩散受限的聚合 (en.wikipedia.org/wiki/…)。顺便说一句,我刚刚在问题中添加了一个说明性图像。
      • 也许可以通过使用图形本身的最低有效位来减少内存需求。
      • @EdwardDoolittle:你能详细说明一下吗?我不明白如何使用图形的 LSB。你的意思是从画布/屏幕上读取像素颜色数据吗?
      • @LarsH:恐怕我看不到与扩散限制聚合的联系,但这可能是因为我不知道它是如何工作的 :)
      • @LarsH 是的,完全正确。已分配内存来表示图像。颜色数据的 MSB 将对应于图形的可见颜色变化。 LSB 可用于存储其他信息,例如建议答案中的距离信息。根据颜色分辨率,LSB 信息或多或少是肉眼不可见的。您需要确定颜色分辨率是否足够高,以及信息是否可以足够快地读取/写入。根据浏览器/系统可能会有差异。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-03
      • 2011-02-07
      • 2012-02-28
      • 2015-10-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多