寻找一个圆是否在另一个圆内部

11

我有点困难。我的作业要求我查找第二个圆是否与第一个圆重叠、包含或不相交。然而,我无法检查它们是否重叠以及第二个圆是否在第一个圆内。

这里是我的代码(变量 x1、x2、y1、y2、r1、r2、distance 被使用):

if (distance > (r1 + r2)) {
        // No overlap
        System.out.println("Circle2 does not overlap Circle1");
    } else if (distance <= Math.abs(r1 + r2)) {
        // Overlap
        System.out.println("Circle2 overlaps Circle1");
    } else if ((distance <= Math.abs(r1 - r2)) {
        // Inside
        System.out.println("Circle2 is inside Circle1");
}

我担心问题在于重叠和内部检查,但我无法弄清楚如何正确设置它,以便可以可靠地检查第二个圆是否在第一个圆内。

任何帮助或建议都将不胜感激,因为我尝试了多种方法,但每次解决方案都令我难以理解。


1
首先 - 什么是距离?它是圆心之间的距离吗?其次 - 确定哪个半径更大可能有帮助吗? - user1118321
所有变量都由用户输入。是的,距离是使用距离公式计算出两个圆心之间的距离。 - Battleroid
我刚刚谷歌搜索了解这个问题,并找到了这个网址http://gamedev.stackexchange.com/questions/7172/how-to-find-out-if-two-circles-intersect-each-other - Jayy
我认为中心之间的距离是关键......以及测试的顺序...... - Rob
太棒了,谢谢!这会帮助我很多。 - Battleroid
这并不是圆可能处于的所有状态。圆A可以在圆B内部,或圆B可以在圆A内部,或它们可以是同一个圆。 - McKay
7个回答

14

在重叠之前,您只需要检查内部是否存在,因为内部的距离小于等于重叠的距离。

if (distance > (r1 + r2)) 
{
    // No overlap
    System.out.println("Circle2 does not overlap Circle1");
}
else if ((distance <= Math.abs(r1 - r2)) 
{
    // Inside
    System.out.println("Circle2 is inside Circle1");
}
else              // if (distance <= r1 + r2)
{
   // Overlap
   System.out.println("Circle2 overlaps Circle1");
} 

根据Chris的评论修改的答案


是的,那就是我的问题。我之前试过一次,但我想我用了错误的比较顺序进行排序。再次感谢。 - Battleroid
1
你的代码里有不必要的部分。由于r1和r2都是>0的(我假设它们是半径),所以r1+r2不需要abs函数。如果你将这个检查与第一个检查进行比较,那么你会注意到如果第一个检查为false,它总是会尝试,因此你可以跳过条件并使最后一个成为普通的else。 - Chris
我知道我只是重新排列了原始问题中的代码,但这是一个很好的要点,我会在注释中加入。 - Dampsquid
你所做的表明那是正确的测试,尽管它实际上并不正确。如果你有正确的测试,无论以哪种顺序进行都没有关系。你答案有效的唯一原因是因为你的最后一个测试恰好总是评估为真。 - Chris

9

这个问题最好先通过视觉方式解决,然后再编写代码。您似乎已经掌握了不在内部和完全在内部的正确逻辑。

处理这个问题的简单方法是,如果它们既不完全在内部也不完全在外部,则它们必须重叠。这绝对是我编写代码的方式。数学上比其他两种情况要棘手一些。

if (distance > (r1 + r2)) {
    // No overlap
    System.out.println("Circle2 does not overlap Circle1");
} else if ((distance <= Math.abs(r1 - r2)) {
    // Inside
    System.out.println("Circle2 is inside Circle1");
{ else {
    // Overlap
    System.out.println("Circle2 overlaps Circle1");
}

实际情况为: r2>r1-dr2 < r1+d 通过对称性,我们不需要做两次(如果您在两个变量中交换r2和r1并重新排列一下,您会得到相同的方程式)。
除非有必要,否则最好将其保留在“else”类别中而不是为其编码。

2

两点之间的距离可以用勾股定理来描述:

  distance = sqrt( travelled_x_squared + travelled_y_squared );

当然,这当然可以转化为代码:
  distance = Math.sqrt(  (x1-x2)*(x1-x2) + (y1 - y2)*(y1 - y2) );

接触点间距离为 r1 + r2。

编辑提示之前: 您需要计算两圆之间的夹角。

然后,计算从圆1到圆2的距离。如果小于半径1 + 半径2,则在内部。

atan2可能是一个感兴趣的函数。

或者直接使用勾股定理计算距离。


2
角度完全无关紧要。您始终可以只考虑通过两个中心的线以及沿着这些线的距离(距离,r1,r2)。 - Chris
@Chris 是的,那就是勾股距离。 - Captain Giraffe
我不确定这解释了为什么你认为需要角度。这只会让事情变得更加复杂,而且atan2对于这个问题并不感兴趣,会导致你走向错误的解决方案... - Chris
@Chris 我只是想提供一些标记为Java、数学和作业的建议,希望能有所帮助。每个途径都有其独特的回报,没有一个会导致错误的解决方案。我不知道你为什么要这样写。 - Captain Giraffe
我不相信任何被认为正确的解决方案会使用三角函数。我甚至不确定你需要xn,yn,因为我们已经知道了两点之间的距离。如果你开始使用角度,你很可能会做一些可以大大简化的事情。例如,即使假设我们没有距离,你也可以使用arctan从给定的x和y计算出角度,然后使用sin/cos计算出两点之间的距离,但这仍然不是一个好的方法(因此我会说是错误的),因为你可以使用勾股定理来做它(就像你做的那样)。 - Chris

2

您已经非常接近成功了,只是条件的顺序有误。

if (distance > (r1 + r2)) {
        // No overlap
        System.out.println("Circle2 does not overlap Circle1");
    } else if ((distance <= Math.abs(r1 - r2)) {
        // Inside
        System.out.println("Circle2 is inside Circle1");
    } else {
        // Overlap
        System.out.println("Circle2 overlaps Circle1");
}

在“非重叠”情况后检查“内部”情况,以确保它不会被意外地视为重叠。然后,所有其余的都必须是重叠。


你和Dampsquid是对的。我以前试过,但我弄错了比较,所以每次都返回错误。 - Battleroid

2

如果距离和较小半径之和小于另一个半径,那么较小的圆应该在较大的圆内。

注:此处指两个圆的位置关系。

只有当中心彼此足够接近时,才会出现重叠或不重叠的圆形。 - Jonathan Drapeau
1
@JonathanDrapeau。抱歉,但这不是真的。至少,只要距离意味着两个圆心之间的距离。如果圆心之间的距离足够远,使得圆相交,则可能有两种情况:a)一个圆的中心在另一个圆内=> d + r2> r1 || d + r1> r2; 或b)没有圆心在另一个圆内=> d> r1 || d> r2已经成立。 - Matthias

1

这是一个简单的任务,

计算两个圆的半径之和,即 r1 + r2。 现在找到两个圆心之间的距离,即 sqrt((x1-x2)^2 + (y1-y2)^2)。 如果 r1+r2 = sqrt((x1-x2)^2 + (y1-y2)^2),它们只是相切。 如果 r1+r2 > sqrt((x1-x2)^2 + (y1-y2)^2),圆重叠(相交)。 如果 r1+ r2 < sqrt((x1-x2)^2 + (y1-y2)^2),圆不相交。


-1
/**
   *
   * @param values { x0, y0, r0, x1, y1, r1 }
   * @return true if circles is intersected
   */
  public static boolean isCircleIntersect(double... values)
  {
    /* check using mathematical relation: ABS(R0-R1) <= SQRT((x0-x1)^2+(y0-y1)^2) <= (R0+R1) */
    if (values.length == 6)
    {
      /* get values from first circle */
      double x0 = values[0];
      double y0 = values[1];
      double r0 = values[2];
      /* get values from second circle */
      double x1 = values[3];
      double y1 = values[4];
      double r1 = values[5];
      /* returun result */
      return (Math.abs(r0 - r1) <= Math.sqrt(Math.pow((x0 - x1), 2) + Math.pow((y0 - y1), 2)))
              && (Math.sqrt(Math.pow((x0 - x1), 2) + Math.pow((y0 - y1), 2)) <= (r0 + r1));
    }
    else
    {
      /* return default result */
      return false;
    }
  }

你应该使用代码按钮将其格式化为源代码。 - Thom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接