让我们说我有两个方格,我知道他们的位置,一个红色和蓝色的方块:
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)?
我认为这很容易,但我很难想出一个很好的方法来覆盖所有这些情况..有谁可以帮助我在这里?
此致 汤姆
答案 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);
要处理这种情况,您只需要在所有条件下交换Bot
和Top
坐标。例如,最后一个现在看起来如下
bool intersects =
redTopX <= blueBotX && redBotX >= blueTopX &&
redTopY <= blueBotY && redBotY >= blueTopY;
答案 1 :(得分:2)
假设两个方块都对齐,正如您所指出的那样:
如果以下所有内容成立,则方块相交:
(说服自己这是真的!)
答案 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中,并搜索范围角落的位置。