欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

判断两矩形bouding box是否相交或包含

程序员文章站 2024-03-21 22:22:52
...

背景

今天在做一个需求的时候突然想到一个问题,需要来解决两个bounding box是否相交或者包含。看到这个问题的第一反应是写一堆if呗,一个一个判断,然而这样条件是不是太多了,万一自己漏掉一个之后还要被测试同学追杀,不行不行。

继续思考,发现是不是判断某个矩形的顶点顶点在另一个矩形内部就行了?这样if的判断就一下子少了很多,听起来是个不错的选择,但是再经过一些确认后发现,这里其实是有bug的,因为存在矩形相交但是没有一个顶点再另一个矩形内部。于是,为了避免这种盲点的再次出现,我先进行了一波分析,分析了一下两个矩形的可能存在的情况:

判断两矩形bouding box是否相交或包含
经过我仔细的思考,应该就是这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

如有疑问我们评论区见~