找到包含其他圆圈的最小圆圈?

时间:2010-01-18 08:30:13

标签: c# math geometry

如果圆圈由其中心的X,Y和半径定义,那么如何找到包含给定圈数的圆?一个圆圈,是可能的最小圆圈,完全包含任意大小和位置的2个或更多圆圈。

起初我尝试通过找到中心的中点并且是新圆的中点来尝试包围2个圆,而半径等于2个初始圆的半径的一半,并且它们的中心之间的距离的一半但不知怎的,它总是变得有点偏。找到半径似乎问题似乎总是存在问题,但我对此感到头疼,我无法使其发挥作用。

我不一定需要一种方法来查找包含3个或更多圆圈的圆圈。我可以找到一个包含2的圆圈,取圆圈并用另一个圆圈包围它,另一个圆圈,最后的圆圈应包含整个步骤中给出的所有圆圈。

9 个答案:

答案 0 :(得分:11)

给定两个圆,中心为[x1,y1],[x2,y2],半径为R1和R2。封闭圆的中心是什么?

假设R1不大于R2。如果第二个圆圈较小,则只需交换它们。

  1. 计算圆圈中心之间的距离。

    D = sqrt((x1-x2)^ 2 +(y1-y2)^ 2)

  2. 第一个圆圈是否完全位于第二个圆圈内?因此,如果(D + R1)< = R2,那么我们就完成了。将较大的圆圈作为封闭圆圈返回,其中心为[x1,x2],半径为R2。

  3. 如果(D + R1)> R2,然后包围圆的半径为(D + R1 + R2)/ 2

  4. 在后一种情况下,围绕圆的中心必须位于连接两个中心的线上。所以我们可以把新中心写成

    center = (1-theta)*[x1,y1] + theta*[x2,y2]
    

    其中theta由

    给出
    theta = 1/2 + (R2 - R1)/(2*D)
    

    请注意,theta将始终为正数,因为我们已确保(D + R1)> R2。同样,我们应该能够确保theta永远不会大于1.这两个条件确保封闭中心严格位于两个原始圆心之间。

答案 1 :(得分:5)

它被称为最小封闭圆(“MEC”),或者有时是“最小的封闭圆”。

一个不错的网站:http://www.personal.kent.edu/~rmuhamma/Compgeometry/MyCG/CG-Applets/Center/centercli.htm

答案 2 :(得分:3)

我打算反对这个,现在
请参阅下面的讨论。

原创想法

我会考虑一种迭代的推拉方法。

  1. 猜猜中心的位置(最简单的是所有中心的平均位置)
  2. 将向量计算到每个圆上的最远点。它们总是朝向该圆心的方向,长度为distance_to_center_of_circle[i]+radius_of_circle[i],并随着时间的推移形成矢量和。另请注意,当前位置的必要半径是这些长度的最大值。
  3. 从2开始(例如)1/5或1/10的向量和,并从2为新点重做计算
  4. 如果新点需要比旧点小的圆,则将新点作为当前点,否则,拆分差值,减小建议步长的大小(比如说它的一半)。
  5. 转到3
  6. 当它停止[+]收敛时你就完成了。

    Nikie戳了戳直到......

    按要求澄清第二步。调用要测试的位置\vec{P}(向量)。[++]调用每个圆\vec{p}_i的中心(也是向量),每个圆的半径为r_i。形成总和\sum_i=1^n \hat{p_i - P}*|(p_i-P)|+r_i)。[+++]总和的每个元素指向从当前评估点到相关圆的中心的方向,但是更长r_i。总和本身就是一个矢量。

    半径R需要将P中的所有圆圈括起来max(|p_i-P|_r_i)

    病理案例

    我不认为nikie带来的特殊情况是一个问题,但它让我陷入了这种算法失败的情况。失败的是未能改进解决方案,而不是分歧,但仍然......

    考虑位于

    的半径1的四个圆
    (-4, 1)
    (-5, 0)
    (-4, 1)
    ( 5, 0)
    

    (-1, 0)的起始位置。通过设计对称,使所有距离沿x轴。

    正确的解决方案是(0, 0),半径为6,但是在步骤2中计算的向量大约是::计算得很快:: (-.63, 0),指向错误的方向,导致永远不会找到改进原点。

    现在,上面的算法将实际选择(-2, 0)作为起始点,它给出了一个初始向量和::计算狂怒::约+1.1。因此,(3)中步长的错误选择将导致不太理想的解决方案。 ::叹息::

    可能的解决方案:

    • 在(3)中抛出一个随机分数(比如+1/5和-1/5)可能加权为正数。
    • 在(4)中如果步骤被拒绝,只需返回步骤3而不改变步长限制。

    然而,在这一点上,它并不比纯随机游走好多了,并且你没有一个容易知道它何时收敛的条件。 MEH。

    [+]当然,或者减慢到令你满意的程度。 [++]使用乳胶表示法。 [+++]这里\hat{}表示规范化的向量指向与参数相同的方向。

答案 3 :(得分:3)

由于我的不精确解决方案不受欢迎。这是获得确切解决方案的方法。但它的缓慢(O(N ^ 4)?)和计算上令人讨厌。 (与不精确的方法不同)

首先你需要知道,给定三个圆圈,我们可以找到一个与它们相切的圆,而不是包含所有三个圆。这是Apollonius的一个圈子。您可以从mathworld获取算法。

接下来,您可以显示N个圆圈的最小封闭圆与N个圆圈中的至少3个圆相切。

要查找此圈子,请执行以下操作

  1. 循环遍历所有圆圈 - O(N ^ 3)
  2. 找到这3个圆圈的封闭Apollonius圆圈 - 计算上讨厌的
  3. 如果它包含所有圆圈,则将其添加到潜在列表中 - 检查是否为O(N)
  4. 解决方案是半径最小的潜力
  5. 可能有一些技巧可以加快速度,但它应该为您提供准确的解决方案。 将Smallest Enclosing Circle算法用于线性时间的一些“技巧”可能适用于此,但我怀疑它们不会是微不足道的适应。

答案 4 :(得分:3)

你手边的问题被称为球体的最小封闭球体。我已经写了关于它的论文,见"Smallest enclosing ball of balls",苏黎世联邦理工学院。

您可以在Computational Geometry Algorithms Library (CGAL)Bounding Volumes中找到非常有效的C ++实现。 (不需要使用所有CGAL;只需提取所需的源文件和头文件即可启动并运行。)

注意:如果您正在寻找一种算法来计算仅有点的最小封闭球,那么还有其他实现,请参阅this post

答案 5 :(得分:2)

我已经采取了你们有些人的意见,这是我发现的解决方案:

public static Circle MinimalEnclosingCircle(Circle A, Circle B) {
            double angle = Math.Atan2(B.Y - A.Y, B.X - A.X);
            Point a = new Point((int)(B.X + Math.Cos(angle) * B.Radius), (int)(B.Y + Math.Sin(angle) * B.Radius));
            angle += Math.PI;
            Point b = new Point((int)(A.X + Math.Cos(angle) * A.Radius), (int)(A.Y + Math.Sin(angle) * A.Radius));
            int rad = (int)Math.Sqrt(Math.Pow(a.X - b.X, 2) + Math.Pow(a.Y - b.Y, 2)) / 2;
            if (rad < A.Radius) {
                return A;
            } else if (rad < B.Radius) {
                return B;
            } else {
                return new Circle((int)((a.X + b.X) / 2), (int)((a.Y + b.Y) / 2), rad);
            }
        }

圆圈由其中心的X,Y和半径定义,均为整数。有一个构造函数是Circle(int X,int Y,int Radius)。在突破了一些旧的概念之后,我认为最好的方法是找到距离最远的圆上的2个点。一旦我有了,中点将是中心,一半的距离将是半径,因此我有足够的定义一个新的圆。如果我想要包含3个或更多个圆圈,我首先在2个圆圈上运行它,然后我在生成的包围圆圈和另一个圆圈上运行它,依此类推,直到包含最后一个圆圈。可能有一种更有效的方法可以做到这一点,但现在它起作用了,我很满意。

我对回答自己的问题感到很奇怪,但如果没有每个人的想法和链接,我都无法找到解决方案。谢谢大家。

答案 6 :(得分:0)

只需理解circle的方程式并导出一个方程式(或一系列)来找到答案,然后开始实施。也许我们能够帮助你,因为你已经做了一些事情。

答案 7 :(得分:0)

因此,如果您不需要精确的圆,则此近似可能会这样做。

  1. 取您所有圈子中心的平均值称为此 第X点
  2. 设R1是从X到圆心的最大距离。
  3. 设R2为圆的最大半径
  4. 所有圆圈必须落在以X为中心的圆内,半径为R1 + R2

答案 8 :(得分:0)

这不是一个小问题。我没有阅读上面的所有答案,所以如果我重复一个人已经说过的话,那就是我的错。

每个圆圈c_i由3个参数x_i,y_i,r_i

定义

需要找到3个参数x *,y *,r *表示最佳圆C *

C *是这样的,它包含所有i的c_i

设d_i = ||(x,y) - (x_i,y_i)|| + r_i

然后,如果r是包含所有c_i的圆的半径,那么对于所有i,r&gt; = d_i

我们希望r尽可能小

所以,r * = max(d_i)

因此,我们希望最小化d_i

的最大值

所以(x *,y *)由max(d_i)的arg min给出。并且一旦找到(x *,y *),就可以容易地计算r *并且将等于max(d_i)。这是一个极小极大的问题。

为了让事情更容易理解,只考虑2个圆圈,我们如何找到(x *,y *)?

(x *,y *)可以通过找到最小化(d_1-d_2)^ 2的(x,y)来找到。在一般情况下

让e_ij =(d_i - d_j)^ 2

然后为i!= j定义e = \ sum e_ij(有n在此总和中选择2个术语)

(x *,y *)= arg min of e

这是需要解决的问题。

提示:如果对于所有i,r_i = 0,那么当输入是一堆点时,这会减少到传统的最小封闭圆问题,并且我们希望找到涵盖所有这些的最小圆。