矩形相交问题
数据结构
// 定义一个点类型
struct point{
double x;
double y;
};
// 定义一个矩形类型
struct rect {
struct point pt1; // 矩形的左上角顶点
struct point pt2; // 矩形的右下角定点
}
规定坐标轴采用下图所示坐标轴
判断一个点在一个矩形中
// 规定矩形包含上边和左边,不包含下边和右边
int ptInRect(struct point pt, struct rect rt){
return (pt.x >= rt.pt1.x && pt.x < rt.pt2.x
& pt.y >= rt.pt1.y && pt.y < rt.pt2.y);
}
判断两个矩形是否相交
方法一
通过矩形的重心来判断
由数学知识,如果两个矩形相交,则这两个矩形的重心的连线在x轴的投影会小于这个两个矩形的宽的和的一半,并且在y轴的投影会小于这两个矩形的高的和的一半。
// 检测两个矩形是否相交
// 方法根据重心判断
int checkCross(struct rect rt1, struct rect rt2){
struct point pt1; // rt1的重心
struct point pt2; // rt2的重心
double width1; // rt1的宽
double height1; // rt1的高
double width2; // rt2的宽
double height2; // rt2的高
// 获得矩形的重心
pt1.x = (rt1.pt1.x + rt1.pt2.x);
pt1.y = (rt1.pt1.y + rt1.pt2.y);
pt2.x = (rt2.pt1.x + rt2.pt2.x);
pt2.y = (rt2.pt1.y + rt2.pt2.y);
// 获得矩形的宽度和高度
width1 = rt1.pt2.x - rt1.pt1.x;
height1 = rt1.pt2.y - rt1.pt1.y;
width2 = rt2.pt2.x - rt2.pt1.x;
height2 = rt2.pt2.y - rt2.pt1.y;
// 判断并返回
return (fabs(pt2.x - pt1.x) < (width1 / 2 + width2 / 2)
&& fabs(pt2.y - pt1.y) < (height1 /2 + height2 / 2));
}
这种方法只能用来检测,但是如果想要获得两个矩形的重叠矩形的坐标就很难。
方法二
假设法,通过假设矩形重叠来逆推结果,如果矩形真的相交可以很方便获得重叠矩形的坐标。
假设两个矩形重叠,则可以通过这两个矩形的坐标计算出重叠矩形的坐标。如果这个矩形rt(p1, p2)存在,则必须有:
p1.x < p2.x && p1.y < p2.y
#define min(x, y) (((x) < (y)) ? (x) : (y))
#define max(x, y) (((x) > (y)) ? (x) : (y))
// 检测两个矩形是否相交
// 假设法
int checkCross(struct rect rt1, struct rect rt2){
struct rect overlap;
// 获得重叠矩阵的坐标
overlap.pt1.x = max(rt1.pt1.x, rt2.pt1.x);
overlap.pt1.y = max(rt1.pt1.y, rt2.pt1.y);
overlap.pt2.x = min(rt1.pt2.x, rt2.pt2.x);
overlap.pt2.y = min(rt1.pt2.y, rt2.pt2.y);
// 判断是否重叠,并返回
return (overlap.pt1.x < overlap.pt2.x
&& overlap.pt1.y < overlap.pt2.y);
}
拓展
- 求两个矩形相交的面积
- 求三个矩形相交的面积
- ...