判断两矩形bouding box是否相交或包含
程序员文章站
2024-03-21 22:22:52
...
背景
今天在做一个需求的时候突然想到一个问题,需要来解决两个bounding box是否相交或者包含。看到这个问题的第一反应是写一堆if呗,一个一个判断,然而这样条件是不是太多了,万一自己漏掉一个之后还要被测试同学追杀,不行不行。
继续思考,发现是不是判断某个矩形的顶点顶点在另一个矩形内部就行了?这样if的判断就一下子少了很多,听起来是个不错的选择,但是再经过一些确认后发现,这里其实是有bug的,因为存在矩形相交但是没有一个顶点再另一个矩形内部。于是,为了避免这种盲点的再次出现,我先进行了一波分析,分析了一下两个矩形的可能存在的情况:
经过我仔细的思考,应该就是这8种情况了。于是我又开始思考,这回是从数学角度进行了一波分析,发现矩形有一个特点。
矩形的四条边互相垂直
依据这个特点,我们可以分析一下,矩形的中心一定在两个互相垂直的边的中点的垂线上。
之后我们考虑矩形中心和矩形边长的关系,我们其实可以发现,如果两个矩形相交或包含,他们的中心连线线段的长度一定是小于两个矩形的长宽之和的。这么描述可能不够直观,我们进行一下分解。
将这个长度在平面直角坐标系中表示,这样便有x和y两个分量,同样矩形的长宽也进行同样的解析,分为x和y两个分量。
于是我们可以发现,如果两个矩形相交,他们中心距离的x分量一定是小于等于两矩形长(x分量)之和的一半,他们中心距离的y分量一定小于等于两矩形宽(y分量)之和的一半。
于是我们便可以从这个角度进行coding,而且这样写完代码也很简洁。
解决方案
from decimal import *
def _in_bbox(target_bbox: Tuple[Decimal],
current_pos: Tuple[Decimal]) -> bool:
# bbox (x0, top, x1, bottom)
# 获取两bbox中心的坐标
mid_x = abs((target_bbox[0] + target_bbox[2]) / 2 - (current_pos[0] + current_pos[2]) / 2)
mid_y = abs((target_bbox[1] + target_bbox[3]) / 2 - (current_pos[1] + current_pos[3]) / 2)
# 获取两bbox边长之和
width = abs(target_bbox[0] - target_bbox[2]) + abs(current_pos[0] - current_pos[2])
height = abs(target_bbox[1] - target_bbox[3]) + abs(current_pos[1] - current_pos[3])
if (mid_x <= width/2 and mid_y <= height/2):
return True
else:
return False
如有疑问我们评论区见~