1
1
"""
2
2
This is a Python implementation for collision detection between geometric shapes.
3
- The implementation supports detecting intersections between basic shapes like circles
4
- and rectangles in 2D space.
3
+ The implementation supports detecting intersections between basic shapes like
4
+ circles and rectangles in 2D space.
5
5
6
6
Question :-
7
- Given two geometric shapes and their positions in 2D space, determine if they intersect
8
- or overlap with each other. The shapes can be:
7
+ Given two geometric shapes and their positions in 2D space, determine if they
8
+ intersect or overlap with each other. The shapes can be:
9
9
- Circles (defined by center point and radius)
10
10
- Rectangles (defined by center point and dimensions)
11
11
12
12
The implementation uses Axis-Aligned Bounding Box (AABB) technique for efficient
13
13
rectangle collision detection.
14
-
15
- Example:
16
- >>> detector = CollisionDetector()
17
- >>> # Test circle-circle collision
18
- >>> circle1, circle2 = Circle(5), Circle(3)
19
- >>> detector.detect_circle_collision(circle1, circle2, (0, 0), (7, 0))
20
- True # circles overlap as distance (7) < sum of radii (8)
21
- >>> detector.detect_circle_collision(circle1, circle2, (0, 0), (9, 0))
22
- False # circles don't overlap as distance (9) > sum of radii (8)
23
- >>> # Test rectangle-rectangle collision
24
- >>> rect1, rect2 = Rectangle(4, 6), Rectangle(2, 2)
25
- >>> detector.detect_aabb_collision(rect1, rect2, (0, 0), (1, 1))
26
- True # rectangles overlap
27
- >>> detector.detect_aabb_collision(rect1, rect2, (0, 0), (5, 5))
28
- False # rectangles don't overlap
29
- >>> # Test circle-rectangle collision
30
- >>> circle, rect = Circle(2), Rectangle(4, 4)
31
- >>> detector.detect_circle_rectangle_collision(circle, rect, (0, 0), (3, 0))
32
- True # shapes overlap as circle edge reaches rectangle
33
- >>> detector.detect_circle_rectangle_collision(circle, rect, (0, 0), (5, 0))
34
- False # shapes don't overlap
35
14
"""
36
15
37
16
from __future__ import annotations
38
17
39
- import math
40
18
from dataclasses import dataclass
19
+ import math
41
20
from typing import Tuple
42
21
43
22
from geometry import Circle , Rectangle
47
26
48
27
@dataclass
49
28
class AABB :
50
- """
51
- Axis-Aligned Bounding Box representation of a rectangle.
29
+ """Axis-Aligned Bounding Box representation of a rectangle.
30
+
52
31
Stores the minimum and maximum coordinates of the box.
53
32
"""
33
+
54
34
min_x : float
55
35
min_y : float
56
36
max_x : float
@@ -70,39 +50,45 @@ def from_rectangle(cls, rect: Rectangle, center: Point) -> AABB:
70
50
71
51
72
52
class CollisionDetector :
73
- """
74
- A class that provides methods for detecting collisions between different geometric shapes.
53
+ """Provides methods for detecting collisions between different geometric shapes.
54
+
75
55
Supports collision detection between:
76
56
- Circle to Circle
77
57
- Rectangle to Rectangle (using AABB)
78
58
- Circle to Rectangle
79
59
"""
80
60
81
61
@staticmethod
82
- def detect_circle_collision (circle1 : Circle , circle2 : Circle , pos1 : Point , pos2 : Point ) -> bool :
83
- """
84
- Detect collision between two circles at given positions.
62
+ def detect_circle_collision (
63
+ circle1 : Circle ,
64
+ circle2 : Circle ,
65
+ pos1 : Point ,
66
+ pos2 : Point ,
67
+ ) -> bool :
68
+ """Detect collision between two circles at given positions.
69
+
85
70
Returns True if circles overlap or touch, False otherwise.
86
71
"""
87
- # Calculate distance between circle centers using Pythagorean theorem
88
72
dx = pos2 [0 ] - pos1 [0 ]
89
73
dy = pos2 [1 ] - pos1 [1 ]
90
74
distance = math .sqrt (dx * dx + dy * dy )
91
-
92
- # Circles collide if distance is less than or equal to sum of radii
75
+
93
76
return distance <= (circle1 .radius + circle2 .radius )
94
77
95
78
@staticmethod
96
- def detect_aabb_collision (rect1 : Rectangle , rect2 : Rectangle , pos1 : Point , pos2 : Point ) -> bool :
97
- """
98
- Detect collision between two rectangles using AABB method.
79
+ def detect_aabb_collision (
80
+ rect1 : Rectangle ,
81
+ rect2 : Rectangle ,
82
+ pos1 : Point ,
83
+ pos2 : Point ,
84
+ ) -> bool :
85
+ """Detect collision between two rectangles using AABB method.
86
+
99
87
Returns True if rectangles overlap, False otherwise.
100
88
"""
101
- # Convert rectangles to AABB representation
102
89
box1 = AABB .from_rectangle (rect1 , pos1 )
103
90
box2 = AABB .from_rectangle (rect2 , pos2 )
104
91
105
- # Check for overlap in both x and y axes
106
92
return (
107
93
box1 .min_x <= box2 .max_x
108
94
and box1 .max_x >= box2 .min_x
@@ -112,37 +98,34 @@ def detect_aabb_collision(rect1: Rectangle, rect2: Rectangle, pos1: Point, pos2:
112
98
113
99
@staticmethod
114
100
def detect_circle_rectangle_collision (
115
- circle : Circle , rect : Rectangle , circle_pos : Point , rect_pos : Point
101
+ circle : Circle ,
102
+ rect : Rectangle ,
103
+ circle_pos : Point ,
104
+ rect_pos : Point ,
116
105
) -> bool :
117
- """
118
- Detect collision between a circle and a rectangle.
106
+ """Detect collision between a circle and a rectangle.
107
+
119
108
Returns True if shapes overlap, False otherwise.
120
109
"""
121
- # Convert rectangle to AABB
122
110
box = AABB .from_rectangle (rect , rect_pos )
123
111
124
- # Find the closest point on rectangle to circle center
125
112
closest_x = max (box .min_x , min (circle_pos [0 ], box .max_x ))
126
113
closest_y = max (box .min_y , min (circle_pos [1 ], box .max_y ))
127
114
128
- # Calculate distance between closest point and circle center
129
115
dx = circle_pos [0 ] - closest_x
130
116
dy = circle_pos [1 ] - closest_y
131
117
distance = math .sqrt (dx * dx + dy * dy )
132
118
133
- # Collision occurs if distance is less than circle radius
134
119
return distance < circle .radius
135
120
136
121
137
122
if __name__ == "__main__" :
138
- # Run doctest examples
139
123
import doctest
124
+
140
125
doctest .testmod ()
141
126
142
- # Additional test cases
143
127
detector = CollisionDetector ()
144
-
145
- # Test circle-circle collision
128
+
146
129
print ("\n Testing circle-circle collision:" )
147
130
circle1 , circle2 = Circle (5 ), Circle (3 )
148
131
test_cases = [
@@ -155,7 +138,6 @@ def detect_circle_rectangle_collision(
155
138
result = detector .detect_circle_collision (circle1 , circle2 , pos1 , pos2 )
156
139
print (f"{ desc } : { '✓' if result == expected else '✗' } " )
157
140
158
- # Test rectangle-rectangle collision
159
141
print ("\n Testing rectangle-rectangle collision:" )
160
142
rect1 , rect2 = Rectangle (4 , 6 ), Rectangle (2 , 2 )
161
143
test_cases = [
@@ -168,7 +150,6 @@ def detect_circle_rectangle_collision(
168
150
result = detector .detect_aabb_collision (rect1 , rect2 , pos1 , pos2 )
169
151
print (f"{ desc } : { '✓' if result == expected else '✗' } " )
170
152
171
- # Test circle-rectangle collision
172
153
print ("\n Testing circle-rectangle collision:" )
173
154
circle , rect = Circle (2 ), Rectangle (4 , 4 )
174
155
test_cases = [
@@ -178,5 +159,7 @@ def detect_circle_rectangle_collision(
178
159
((0 , 0 ), (3 , 3 ), True , "Corner overlap" ),
179
160
]
180
161
for circle_pos , rect_pos , expected , desc in test_cases :
181
- result = detector .detect_circle_rectangle_collision (circle , rect , circle_pos , rect_pos )
162
+ result = detector .detect_circle_rectangle_collision (
163
+ circle , rect , circle_pos , rect_pos
164
+ )
182
165
print (f"{ desc } : { '✓' if result == expected else '✗' } " )
0 commit comments