【问题标题】:Combining overlapping circles in a list in Java在Java中的列表中组合重叠的圆圈
【发布时间】:2013-03-05 11:02:23
【问题描述】:

这是我第一次在这里发帖,如果我遗漏了信息或提供了太多信息,或者搞砸了,我深表歉意。如果我这样做了,请告诉我。

所以我有一个圆圈列表,其中许多可能重叠。 我通过以下方式检测重叠(鼻子是我的类,指定圆的大小(半径)和位置):

public boolean isSame(Nose other)
{
    // if the difference between their X and Y positions are both
    // less than half the combined sizes...
    if (Math.abs(other.x - x) < (other.size + size) &&
        Math.abs(other.y - y) < (other.size + size) )
        return true;
    else
        return false;
}

我相信如果圆圈很接近,但不一定重叠,这应该返回 true。这就是我想要的应用程序(对于那些想要真正重叠的人,最重要的答案将对此有所帮助:) How to detect overlapping circles and fill color accordingly?

鉴于这种“重叠”检测,我试图将列表中的“重叠”圆圈与以下代码结合起来(鼻子是一个 ListArray):

for (int i = 0; i < noses.size(); i++)
{
    //for each nose after the current one, check for redundant noses
    for (int j = i+1; j < noses.size(); j++)
    {
        Nose noseI = noses.get(i);
        Nose noseJ = noses.get(j);
        if (noseI.isSame(noseJ))
        {
            noses.set(i, new Nose((noseI.x + noseJ.x),
                                  (noseI.y + noseJ.y),
                                  (noseI.size + noseJ.size)));
            noses.remove(j);
            j--; // decrement back to check the nose that is NOW at that place.
        }
    }
    Nose noseI = noses.get(i).getBig();
    //Add noses[i] to the image being returned
    canvas.drawCircle((float)(noseI.x), (float)(noseI.y), (float)(noseI.size), paint);
}

我相信这种循环查找相似元素并将它们组合起来的方法应该可以工作,因为以下代码可以正常工作(修改自combine items of list):

public static void main(String[] args) {
  List<Integer> list = new LinkedList<>();
  list.add(10);
  list.add(80);
  list.add(5);
  list.add(30);
  list.add(13);
  list.add(18);
  list.add(36);
  System.out.println(list);

  for (int i = 0; i < list.size(); i++)
  {
     for (int j = i + 1; j < list.size(); j++)
     {
        if (Math.abs(list.get(i) - list.get(j)) < 10)
        {
           Integer a = list.get(i);
           Integer b = list.get(j);
           list.set(i, (a + b) / 2);
           list.remove(j);
           j--;
        }
     }
  }

  System.out.println(list);
}

这给了我以下输出:

[10, 80, 5, 30, 13, 18, 36]
[14, 80, 33]

但是,我的实际应用程序始终在其上绘制重叠的圆圈。我真的很困惑为什么,因为我已经用简单的整数检查了组合循环,而且我相当确定我的重叠检测甚至不应该有彼此接近的圆圈,并且所以当然不应该有任何重叠。

【问题讨论】:

  • 重叠圆圈的条件是错误的。如果两个中心之间的距离小于半径之和,则两个圆重叠。距离由((x1-x2)^2 + (y1-y2)^2)的平方根测量
  • 首先,重叠圆圈的条件最终不是问题。没错,它不是检测圆形重叠,而是检测方形重叠,但如前所述,这对于我的应用程序是可以接受的。问题最终在于组合项目列表。当我在我的列表 [第三个代码块] 中添加一个随机的 30,000 个数字时,我发现结果列表 的数字彼此相差 10 以内(它不应该)。我发现通过简单地运行该算法 2 或 3 次(在 30k 个数字上,只需要 3 次迭代)会给我一个正确的列表。
  • 哦!我发现只进行多次迭代的解决方案感觉就像是 hack。这不能证明是正确的。如果有人能够弄清楚 为什么 一个迭代中仍然存在“重叠”值,并且可能是一个正确的解决方案(在它工作之前不只是诉诸运行迭代),我会接受这样的答案。

标签: java arraylist geometry overlapping


【解决方案1】:

重叠的条件可以计算如下:

public boolean isSame(Nose other) {
   double dx       = other.x - x;
   double dy       = other.y - y;
   double distance = Math.sqrt( dx*dx + dy*dy );
   return distance < Math.max( size, other.size );
}

命名很重要isSame没有意义,我建议overlaps就位。

【讨论】:

  • 但是如果两个圆圈彼此“接近”,我的 isSame 将返回 true 的假设是否正确?这是我想要的功能(也是,isSame,如“两个圆圈代表相同的实际鼻子吗?”)。另外,我试图做尽可能多的近似来帮助加快速度,所以我宁愿避免像平方根这样的昂贵运算。如果我的 isSame 没有 做我认为它做的事情,那可以解释我的问题。否则,我仍然想知道为什么我的最终列表有重叠的圆圈。
  • 当您说“重叠”时,您是否认为“完全在同一个地方”?即两个中心彼此非常接近?
  • 没有。该应用程序是面部检测,并且圆圈被绘制在找到的面部的鼻子上,因此两个圆圈“重叠”,它们足够接近以至于它们真的代表同一张脸。因此,出于我的目的,它们实际上不需要重叠才能被视为“重叠”。所以 (()), ()() 都会“重叠”,但 () () [充分分离] 不会。
猜你喜欢
  • 2021-03-21
  • 2016-07-23
  • 2016-07-16
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-29
相关资源
最近更新 更多