如何检测某个范围(部分)是否位于其他范围内?

时间:2010-05-28 16:28:09

标签: algorithm math comparison tree

让我们说我有两个方格,我知道他们的位置,一个红色和蓝色的方块:

redTopX;
redTopY;
redBotX;
redBotY;
blueTopX;
blueTopY;
blueBotX;
blueBotY;

现在,我想检查方形蓝色是否(部分地)位于方形红色内(或周围)。这可能发生在很多情况下,正如您在我创建的图像中看到的那样,可以更好地说明我的情况: alt text http://www.feedpostal.com/etc/ranges.gif

请注意,总是只有一个蓝色和一个红色方块,我只是添加了多个,所以我不需要重绘18次。

我原来的逻辑很简单,我会检查方形蓝色的所有角落,看看它们是否都在方红色内:

if (
((redTopX >= blueTopX) && (redTopY >= blueTopY) && (redTopX <= blueBotX) && (redTopY <= blueBotY)) || //top left
((redBotX >= blueTopX) && (redTopY >= blueTopY) && (redBotX <= blueBotX) && (redTopY <= blueBotY)) || //top right
((redTopX >= blueTopX) && (redBotY >= blueTopY) && (redTopX <= blueBotX) && (redBotY <= blueBotY)) || //bottom left
((redBotX >= blueTopX) && (redBotY >= blueTopY) && (redBotX <= blueBotX) && (redBotY <= blueBotY)) //bottom right
) {
    //blue resides in red
}

不幸的是,这种逻辑存在一些缺陷。例如,如果红色环绕蓝色(如情况1)?

我认为这很容易,但我很难想出一个很好的方法来覆盖所有这些情况..有谁可以帮助我在这里?

此致 汤姆

6 个答案:

答案 0 :(得分:6)

检查红色矩形是否完全位于蓝色矩形的测试如下所示

bool outside = 
  redBotX > blueTopX || redTopX < blueBotX || 
  redBotY > blueTopY || redTopY < blueBotY;

现在,负面的将告诉你红色矩形是否与蓝色矩形相交

bool intersects =
  !(redBotX > blueTopX || redTopX < blueBotX || 
    redBotY > blueTopY || redTopY < blueBotY);

如果您愿意,可以应用De Morgan规则并将其重写为

bool intersects =
  redBotX <= blueTopX && redTopX >= blueBotX && 
  redBotY <= blueTopY && redTopY >= blueBotY;

当然,上述测试假设坐标是“标准化*,即

assert(redBotX <= redTopX && redBotY <= redTopY);
assert(blueBotX <= blueTopX && blueBotY <= blueTopY);

此外,比较可能是严格的或非严格的,具体取决于您是否考虑将矩形与交叉相交。

编辑:我看到您对矩形坐标使用不同的约定:Top是较低的坐标,Bot是较高的坐标,即

assert(redTopX <= redBotX && redTopY <= redBotY);
assert(blueTopX <= blueBotX && blueTopY <= blueBotY);

要处理这种情况,您只需要在所有条件下交换BotTop坐标。例如,最后一个现在看起来如下

bool intersects =
  redTopX <= blueBotX && redBotX >= blueTopX && 
  redTopY <= blueBotY && redBotY >= blueTopY;

答案 1 :(得分:2)

假设两个方块都对齐,正如您所指出的那样:

如果以下所有内容成立,则方块相交:

  1. Red的左侧侧是Blue的右侧侧的左侧
  2. Red的右侧侧是Blue的左侧侧的右侧
  3. Red的顶部 底部
  4. Red的底部 顶部
  5. (说服自己这是真的!)

答案 2 :(得分:1)

两个矩形相交的一个公式是

! ( (redTopX > blueBotX) || (blueTopX > redBotX) || (redTopY < blueBotY) || (blueTopY < redBotY))

您可以使用DeMorgan的定理来简化。

答案 3 :(得分:1)

if (blueTopY < redBotY) return (0);
if (blueBotY > redTopY) return (0);
if (blueBotX < redTopX) return (0);
if (blueTopX > redBotX) return (0);
return (1); // there must clash

答案 4 :(得分:1)

for each blue corner:
  if corner is between all four red sides:
    return true
return false

答案 5 :(得分:1)

对于更高维度的范围,或者如果您想检查很多范围,可能值得将您的范围(例如他们的中心)存储在R tree中,并搜索范围角落的位置。