寻找最适合圈子的人


12

下面是一个示例图像,如果我在中间有一个白点,并且我想找到所有可能存在的红色圆圈,则该蓝色圆圈的位置可能最近(显然是我放置它的位置) 。如何找到该位置?

对我来说,性能并不是此应用程序的主要问题。

在此处输入图片说明


1
黑色圆圈的意义是什么?你能把蓝色圆圈放在上面吗?
Ewan

2
为了清楚起见,您想要一个可以放置蓝色圆圈的位置,以使其距白点的距离最短,而不会与其他圆圈重叠?
罗伯特·哈维

3
相关内容:圈子包装
罗伯特·哈维

2
所有圈子是否都会在至少一个地方总是碰到其他圈子?
罗伯特·哈维

Answers:


4

这不是一个通用的解决方案,因为在多种情况下它无法提供距白点最短距离的蓝色圆圈的位置。例如,如果您将100个红球组合在一起,并且白点距离这组红球较远,那么任何一个红球都不会对仅位于白点中心的蓝色圆圈的位置产生任何影响。它也不会显示所有计算详细信息。无论如何,对于配置的子集,其中解决方案(蓝色圆圈)与两个红色圆圈相切,则下面的方法应该起作用:
1)令R为蓝色圆圈的半径
2)在所有红色圆圈对上循环,是的我知道这是O(n2)。
3)对于中心分别在(xi,yi)和(xj,yj)且半径分别为ri和rj的每对圆i,j,计算这对圆之间的距离的平方

d_ij^2=(xi-xj)^2+(yi-yj)^2  

4)将所有成对的圆圈

dij^2<R^2

进入列表。

5)遍历列表,找到与圆i和圆j相切的半径为R的圆的2个解。为此,请结合使用这些方程式和此图像 两个蓝色圆圈代表一对红色圆圈

a = R+ri  
b = R+rj  
c = dij  
α = arccos((b^2+c^2-a^2)/(2bc)  

通过以上信息,您可以找到(X1ij,Y1ij)和(X2ij,Y2ij)与圆i和j相切的两个圆的中心。对于每个候选蓝色圆圈,在所有其他红色圆圈上循环,看看它是否不重叠。如果他们不满意,请检查到白色圆圈的距离。如果您保持较小的距离,那么当您完成对圆对列表的遍历时,我认为您将会找到解决方案。该算法看起来像O(n3)。


只有一个圆圈时不起作用
Ewan

或两个圆圈,但两个圆圈之外都有一个目标点
Ewan

问题是你不能确定自己有所有的情况
Ewan

也。对于这些情况,有独特的解决方案
Ewan

您需要写下解决方案正确的所有假设,或者至少指出所有边界情况。其中一些可能很明显,但有些不是。例如,如果可以绘制一条线将白点与所有红色圆圈分开,并且白点与最近的圆圈相距小于R,则此方法将无效。
弗拉德

2

距该点最近的位置将在该点上或触摸一个圆。

因此,首先检查该点,然后在每个现有圆的边缘周围滚动新的圆,计算到该点的距离,以及如果您在进行过程中重叠并跟踪最小距离点。遍历每个圆圈后停止。

即。检查绿线上的所有点以及白色圆圈。绿线是半径为红色加上蓝色的圆

可能的中心点

您需要检查整个绿线,而不仅仅是交叉点,以便覆盖这些边缘情况。

单圈情况

显然,遍历的步长对于性能而言非常重要。但是,由于您认为性能不是问题,因此请选择与您的输出值的分辨率相对应的值。即浮动,长?

澄清:

我的建议是对每个圆上的所有点进行蛮力测试,以使其在每个点上与所有其他圆重叠。没有聪明。

如果示例图片指示圆圈数和分辨率,则对于标准PC来说应该不成问题

我们有20个平均半径为200的圆,因此大约有20 * 2π* 200点* 20个相交测试= 4800000次迭代

注意:

这样的迭代方法存在缺陷,因为步长(在这种情况下为输出分辨率)会极大地影响结果。

假设我有两个相距2个像素的红色圆圈和一个1像素半径的蓝色圆圈要在它们之间挤压。显然,以两个像素中的任何一个作为蓝色圆圈的中心,它将与红色之一重叠。但是,如果中心位于两个像素之间,则显然有圆圈的空间。

因此,我的评论询问输出的分辨率。你说的可以是任何东西。

您也可以求解半径为蓝色圆形半径的每对圆形的联立方程。

这将为您提供一个点,在该点上,蓝色圆圈将比迭代更准确地接触两个红色圆圈。

然而。在某些情况下,如果仅执行此操作,则会得到错误的答案或没有答案。即。

1个或没有圈子

2个或更多的圆,但目标点距离较远且在其外部。

许多圆,但目标点靠近表面


2
他需要围绕其他圆圈的外侧滚动蓝色圆圈的边缘,这很容易理解。困难的部分是找出方程式/计算来完成。
罗伯特·哈维

1
真?其正好(x-x1)^ 2 +(y-y1)^ 2 =(r + r1)^ 2
Ewan

2
然后,当您尝试下一个要点时,必须再次执行所有操作。我知道OP表示性能不是问题,但它必须在宇宙热死之前完成。
罗伯特·哈维

2
知道是否会获得十次投票的唯一方法是发布您的C#代码并查看会发生什么。
罗伯特·哈维

2
我认为将会发生的是,OP将把它编码为他的作业答案,而我们将再也听不到他的消息
Ewan

1

这个代码包含工作代码,

概念

给定的圆圈是C1,C2 .... Cn

圆Cn的坐标为Cnx,Cny且半径为Cr

所需圆的半径为R

如果蓝色圆圈在X,Y位置并且与其他任何圆圈不冲突,则以下等式为真

(C1x - X)^2 + (C1y - Y)^2 > (C1r + R)^2
(C2x - X)^2 + (C2y - Y)^2 > (C2r + R)^2
....
(Cnx - X)^2 + (Cny - Y)^2 > (Cnr + R)^2

改变第一个方程,

C1x^2 - 2C1x*X + X^2 + C1y^2 - 2C1y*Y + Y^2 > C1r^2 + 2C1r*R + R^2
X^2 + Y^2 - 2C1x*X - 2C1y*Y > C1r^2 + 2C1r*R + R^2 - C1x^2 - C1y^2

因此方程式可以重写为

X^2 + Y^2 - 2C1x*X - 2C1y*Y > C1r^2 + 2C1r*R + R^2 - C1x^2 - C1y^2
X^2 + Y^2 - 2C2x*X - 2C2y*Y > C2r^2 + 2C2r*R + R^2 - C2x^2 - C2y^2
....
X^2 + Y^2 - 2Cnx*X - 2Cny*Y > Cnr^2 + 2Cnr*R + R^2 - Cnx^2 - Cny^2

实作

从白点(Xw,Yw)的坐标开始,

    var isValidLocation = function(x,y,r){
       var valid = true;
       for (var i = 0; i< circles.length; i++){
          var circle = circles[i];
          valid = valid && ((x*x + y*y - 2*circle.x*x - 2*circle.y*y) > (circle.radius*circle.radius + 2*circle.radius*r + r*r - circle.x*circle.x - circle.y*circle.y));
       }
       return valid;
      };

      var find = function(Xw,Yw,Rw){
        var radius = 0;
        while(true){
          for (var x=-1 * radius ;x <= radius; x++) {
            for (var y=-1 * radius;y <= radius; y++) {
               if (isValidLocation(Xw + x,Yw + y, Rw)){
                 drawCircle(Xw + x,Yw + y,Rw,"#0000FF");
                 return;
               }
            }   
          } 
          radius++;
        }
     }; 

发现满足所有方程的第一个坐标是蓝色圆圈的位置


有人可以解释这种方法有什么问题吗?
低飞的鹈鹕

很难读。使用一些好名字和抽象。添加图表会杀死您吗?
candied_orange

据我所知,这种方法尝试仅找到蓝色圆圈的有效展示位置,而不是最近的可能位置。这可能是固定的,但是,该方法还使(很可能是无效的)假设仅存在有限数量的整数值坐标。
布朗

它从白点的坐标开始,然后围绕它展开搜索网格。因此,它将不会遇到坐标数无限的任何情况。最终,它将找到匹配的坐标。
低飞鹈鹕

1
...为了在整数坐标中找到正确的解决方案,您需要使用增大的半径,并使搜索空间围绕白点以该半径作为圆。尽管OP编写效率不是他关心的问题,但是最好不要在每个循环中一次又一次地测试每个已测试的坐标对。
布朗

0
  • ,这是您想要接近的一点
  • P是您要寻找的点(蓝色圆圈的中心
  • r是蓝色圆圈的半径
  • C0 .. Cn是限制蓝色在
  • 扩展的圆是半径为r的之一

    如果O不在圆心处,则需要做一些额外的工作。所以现在假设O == C0

通过使用它们各自的半径加上r来计算所有圆与C0的所有交点,即,使延伸圆与扩展的C0相交。如果没有相交,则您要寻找的点在C0上的任意位置,如果有相交,则对于每个相交,检查它是否在另一个扩展圆内(您可以将自己限制为与C0相交的圆)。以不在另一个扩展圆中的第一个交点作为P,可能会有其他交点。

如果扩展圆和C0之间没有在另一个扩展圆之内的交点,请计算所有扩展圆的交点。然后按照与O的距离顺序检查这些交点,再将这些交点放在另一个扩展的圆内,如果是,则舍弃,如果不是,则得出结果。

如果您设想此设想,请在所有圆周围画一条线以指示您的蓝色圆圈的可能位置,将所有扩展圆的并集将指示您的蓝色圆圈无法覆盖的区域。您要查找的点是不在该联合中的最接近点。如果C0上的某个点不在该联合中作为解决方案,则如果C0被完全覆盖,则P必须位于其他两个扩展圆之间的交点上,并且必须位于未被C覆盖的区域中此联合(即不在扩展的圈子中)。

这是O(n ^ 2),尽管有一些方法可以改善这一点,但是可以使用网格来减少成对搜索的工作量,我也认为圆是根据它们与O的接近程度来排序的(收音机减少两个圆圈)将有助于限制覆盖范围和交叉点搜索的搜索空间


0

可能的解决方案查找

  1. 检查白点本身是否是解决方案。它涵盖了0个红色圆圈的情况,以及当红色圆圈远离白点时的琐碎情况。
  2. 一个红色圆圈。
    1. 白点是圆的中心。可能的解决方案是圆上无数个点,其中心在白点,半径为蓝色圆半径和红色圆直径的总和。我们称之为绿色圆圈
    2. 白点在其他地方。连接白点和红色圆圈中心的线上只有一种可能的解决方案,它是蓝色圆圈的半径,远离红色圆圈与白点的交叉点。
  3. 两个或多个红色圆圈。
    1. 让我们一个接一个地圈出红色圆圈,并根据第2点(一个圆圈)分别为每个圆圈寻找可能的解决方案
    2. 对于每对红色圆圈,让我们检查一下是否可以绘制触摸两个红色圆圈的蓝色圆圈。即,如果它们的中心之间的距离等于或小于其半径加上蓝色圆圈的直径之和。如果可以,那么你有两个(或一个如果红色圆圈正是一个蓝色的圆圈直径的距离)可能的解决方案

可能的解决方案中进行实际解决方案查找

现在,您有了一组可能的解决方案,对它们进行迭代并检查每一个。

  1. 如果这点实际上是解决方案。到这个点,红色圆圈的中心都不要比半径更近。
  2. 如果它比以前找到的解决方案更接近白点。
  3. 如果您有绿色圆圈(点2.1)
    • 如果在各个点之间没有属于绿色圆圈的解决方案,那么绿色圆圈就是答案。
    • 如果您在绿色圆圈上有单独的解决方案,并且只需要任何解决方案,则只需选择其中一个即可。
    • 如果您在绿色圆圈上有单独的解决方案,并且需要无限数量的解决方案,那么您需要解决另一个问题。您需要从绿色圆圈中剪切出每个红色圆圈中由一对独立解定义的所有弧。

注意:我并不是说算法的实现应该被准确描述。您可以尝试使用动态编程来提高性能,或者在显然无法使用的情况下跳过可能的解决方案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.