使用C++判断两矩形是否相交

本文介绍了一种简单的矩形碰撞检测算法,通过判断矩形顶点是否位于另一个矩形内部来确定两个矩形是否相交,并提供了一种更优化的检测方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设有矩形RECT1和RECT2、有八个顶点

 1 bool test_collision__2(SDL_Rect *rect1, SDL_Rect *rect2)
 2 {
 3     int x1_1 = rect1->x;
 4     int y1_1 = rect1->y;
 5     int x1_2 = rect1->x + rect1->w;
 6     int y1_2 = rect1->y;
 7     int x1_3 = rect1->x;
 8     int y1_3 = rect1->y + rect1->h;
 9     int x1_4 = rect1->x + rect1->w;
10     int y1_4 = rect1->y + rect1->h;
11 
12 
13 
14     int x2_1 = rect2->x;
15     int y2_1 = rect2->y;
16     int x2_2 = rect2->x + rect2->w;
17     int y2_2 = rect2->y;
18     int x2_3 = rect2->x;
19     int y2_3 = rect2->y + rect2->h;
20     int x2_4 = rect2->x + rect2->w;
21     int y2_4 = rect2->y + rect2->h;
22 
23     // 判断矩形一的四个顶点之一是否在矩形二中
24     if( (x1_1 > x2_1 && x1_1 < x2_4) && (y1_1 > y2_1 && y1_1 < y2_4) )
25     {
26         return true;
27     }
28 
29     if( (x1_2 > x2_1 && x1_2 < x2_4) && (y1_2 > y2_1 && y1_2 < y2_4) )
30     {
31         return true;
32     }
33 
34     if( (x1_3 > x2_1 && x1_3 < x2_4) && (y1_3 > y2_1 && y1_3 < y2_4) )
35     {
36         return true;
37     }
38 
39     if( (x1_4 > x2_1 && x1_4 < x2_4) && (y1_4 > y2_1 && y1_4 < y2_4) )
40     {
41         return true;
42     }
43 
44     // 判断矩形二的四个顶点之一是否在矩形一中
45 
46     if( (x2_1 > x1_1 && x2_1 < x1_4) && (y2_1 > y1_1 && y2_1 < y1_4) )
47     {
48         return true;
49     }
50 
51     if( (x2_2 > x1_1 && x2_2 < x1_4) && (y2_2 > y1_1 && y2_2 < y1_4) )
52     {
53         return true;
54     }
55 
56     if( (x2_3 > x1_1 && x2_3 < x1_4) && (y2_3 > y1_1 && y2_3 < y1_4) )
57     {
58         return true;
59     }
60 
61     if( (x2_4 > x1_1 && x2_4 < x1_4) && (y2_4 > y1_1 && y2_4 < y1_4) )
62     {
63         return true;
64     }
65 
66 
67 
68     return false;
69 }

判断的方法狠简单、如果矩形相交、那么肯定存在至少一个矩形的顶点存在于另一个矩形内、所谓在矩形内、也就是这个顶点的坐标的X值和Y值分别位于矩形的左上角(x_min, y_min)坐标与右下角(x_max, y_max)坐标之间、也就当x_min < x < x_max且y_min < y < y_max时、这个顶点存在于

 

实际上、上面这么描述并不对、这个算法充其量就是边界算法、因为下面这种情况是两个矩形的四个顶点都不矩形中、但因为这种是特殊的简化情况、一旦碰壁就停止、那么也没什么所谓、如果是需要计算碰壁后能穿透的情况下、这种蛮力算法就无能为力了

 

 

 

 

假设有矩形1的左上角点(x1,y1)和右下角点(x2, y2)、和矩形2从左上角点(x3,y3)和右下角点(x4,y4)、可根据以下算法判断是否相交

优化算法:

 1 // 判断两矩形是否相交、原理狠简单、如果相交、肯定其中一个矩形的顶点在另一个顶点内、
 2 bool test_collision(SDL_Rect *rect1, SDL_Rect *rect2)
 3 {
 4     int x1 = rect1->x;
 5     int y1 = rect1->y;
 6     int x2 = rect1->x + rect1->w;
 7     int y2 = rect1->y + rect1->h;
 8 
 9     int x3 = rect2->x;
10     int y3 = rect2->y;
11     int x4 = rect2->x + rect2->w;
12     int y4 = rect2->y + rect2->h;
13 
14     return ( ( (x1 >=x3 && x1 < x4) || (x3 >= x1 && x3 <= x2) ) &&
15         ( (y1 >=y3 && y1 < y4) || (y3 >= y1 && y3 <= y2) ) ) ? true : false;
16 
17 }

 

 

参考资料:

http://zh.wikipedia.org/wiki/%E7%9B%B8%E4%BA%A4

http://zh.wikipedia.org/zh/%E7%9B%B4%E7%BA%BF

判断线段与矩形是否相交可以分为种情况: 1. 线段的两个端点都在矩形内部: 这种情况比较简单,只需要判断线段的两个端点是否都在矩形内部即可。可以通过比较端点的坐标与矩形的边界坐标来实现。如果两个端点都在矩形内部,则线段与矩形相交。 2. 线段的两个端点不都在矩形内部: 这种情况稍微复杂一些,需要判断线段是否矩形的四条边相交。可以将矩形的四条边分别表示成直线方程,然后判断线段是否与这些直线相交。如果线段与矩形的任意一条边相交,则线段与矩形相交。 下面是一段示例代码,演示了如何判断线段与矩形相交: ```c++ #include <iostream> using namespace std; struct Point { double x, y; }; struct Segment { Point start, end; }; struct Rectangle { Point leftTop, rightBottom; }; // 计算点间的距离 double distance(Point p1, Point p2) { double dx = p1.x - p2.x; double dy = p1.y - p2.y; return sqrt(dx * dx + dy * dy); } // 判断是否矩形内部 bool inRectangle(Point p, Rectangle rect) { return p.x >= rect.leftTop.x && p.x <= rect.rightBottom.x && p.y >= rect.leftTop.y && p.y <= rect.rightBottom.y; } // 判断线段是否矩形相交 bool isIntersect(Segment seg, Rectangle rect) { // 判断线段两个端点是否都在矩形内部 if (inRectangle(seg.start, rect) && inRectangle(seg.end, rect)) { return true; } // 判断线段是否矩形的四条边相交 Point p1 = rect.leftTop; Point p2 = {rect.rightBottom.x, rect.leftTop.y}; Point p3 = rect.rightBottom; Point p4 = {rect.leftTop.x, rect.rightBottom.y}; Segment edge1 = {p1, p2}; Segment edge2 = {p2, p3}; Segment edge3 = {p3, p4}; Segment edge4 = {p4, p1}; Segment edges[] = {edge1, edge2, edge3, edge4}; for (int i = 0; i < 4; i++) { Segment edge = edges[i]; // 判断线段是否与边相交 double d1 = (seg.end.x - seg.start.x) * (edge.start.y - seg.start.y) - (seg.end.y - seg.start.y) * (edge.start.x - seg.start.x); double d2 = (seg.end.x - seg.start.x) * (edge.end.y - seg.start.y) - (seg.end.y - seg.start.y) * (edge.end.x - seg.start.x); if (d1 * d2 <= 0) { double d3 = (edge.end.x - edge.start.x) * (seg.start.y - edge.start.y) - (edge.end.y - edge.start.y) * (seg.start.x - edge.start.x); double d4 = (edge.end.x - edge.start.x) * (seg.end.y - edge.start.y) - (edge.end.y - edge.start.y) * (seg.end.x - edge.start.x); if (d3 * d4 <= 0) { return true; } } } return false; } int main() { Segment seg = {{1, 1}, {3, 3}}; Rectangle rect = {{2, 2}, {4, 4}}; if (isIntersect(seg, rect)) { cout << "线段与矩形相交" << endl; } else { cout << "线段与矩形相交" << endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值