11"""
22This 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.
55
66Question :-
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:
99- Circles (defined by center point and radius)
1010- Rectangles (defined by center point and dimensions)
1111
1212The implementation uses Axis-Aligned Bounding Box (AABB) technique for efficient
1313rectangle 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
3514"""
3615
3716from __future__ import annotations
3817
39- import math
4018from dataclasses import dataclass
19+ import math
4120from typing import Tuple
4221
4322from geometry import Circle , Rectangle
4726
4827@dataclass
4928class AABB :
50- """
51- Axis-Aligned Bounding Box representation of a rectangle.
29+ """Axis-Aligned Bounding Box representation of a rectangle.
30+
5231 Stores the minimum and maximum coordinates of the box.
5332 """
33+
5434 min_x : float
5535 min_y : float
5636 max_x : float
@@ -70,39 +50,45 @@ def from_rectangle(cls, rect: Rectangle, center: Point) -> AABB:
7050
7151
7252class 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+
7555 Supports collision detection between:
7656 - Circle to Circle
7757 - Rectangle to Rectangle (using AABB)
7858 - Circle to Rectangle
7959 """
8060
8161 @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+
8570 Returns True if circles overlap or touch, False otherwise.
8671 """
87- # Calculate distance between circle centers using Pythagorean theorem
8872 dx = pos2 [0 ] - pos1 [0 ]
8973 dy = pos2 [1 ] - pos1 [1 ]
9074 distance = math .sqrt (dx * dx + dy * dy )
91-
92- # Circles collide if distance is less than or equal to sum of radii
75+
9376 return distance <= (circle1 .radius + circle2 .radius )
9477
9578 @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+
9987 Returns True if rectangles overlap, False otherwise.
10088 """
101- # Convert rectangles to AABB representation
10289 box1 = AABB .from_rectangle (rect1 , pos1 )
10390 box2 = AABB .from_rectangle (rect2 , pos2 )
10491
105- # Check for overlap in both x and y axes
10692 return (
10793 box1 .min_x <= box2 .max_x
10894 and box1 .max_x >= box2 .min_x
@@ -112,37 +98,34 @@ def detect_aabb_collision(rect1: Rectangle, rect2: Rectangle, pos1: Point, pos2:
11298
11399 @staticmethod
114100 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 ,
116105 ) -> bool :
117- """
118- Detect collision between a circle and a rectangle.
106+ """Detect collision between a circle and a rectangle.
107+
119108 Returns True if shapes overlap, False otherwise.
120109 """
121- # Convert rectangle to AABB
122110 box = AABB .from_rectangle (rect , rect_pos )
123111
124- # Find the closest point on rectangle to circle center
125112 closest_x = max (box .min_x , min (circle_pos [0 ], box .max_x ))
126113 closest_y = max (box .min_y , min (circle_pos [1 ], box .max_y ))
127114
128- # Calculate distance between closest point and circle center
129115 dx = circle_pos [0 ] - closest_x
130116 dy = circle_pos [1 ] - closest_y
131117 distance = math .sqrt (dx * dx + dy * dy )
132118
133- # Collision occurs if distance is less than circle radius
134119 return distance < circle .radius
135120
136121
137122if __name__ == "__main__" :
138- # Run doctest examples
139123 import doctest
124+
140125 doctest .testmod ()
141126
142- # Additional test cases
143127 detector = CollisionDetector ()
144-
145- # Test circle-circle collision
128+
146129 print ("\n Testing circle-circle collision:" )
147130 circle1 , circle2 = Circle (5 ), Circle (3 )
148131 test_cases = [
@@ -155,7 +138,6 @@ def detect_circle_rectangle_collision(
155138 result = detector .detect_circle_collision (circle1 , circle2 , pos1 , pos2 )
156139 print (f"{ desc } : { '✓' if result == expected else '✗' } " )
157140
158- # Test rectangle-rectangle collision
159141 print ("\n Testing rectangle-rectangle collision:" )
160142 rect1 , rect2 = Rectangle (4 , 6 ), Rectangle (2 , 2 )
161143 test_cases = [
@@ -168,7 +150,6 @@ def detect_circle_rectangle_collision(
168150 result = detector .detect_aabb_collision (rect1 , rect2 , pos1 , pos2 )
169151 print (f"{ desc } : { '✓' if result == expected else '✗' } " )
170152
171- # Test circle-rectangle collision
172153 print ("\n Testing circle-rectangle collision:" )
173154 circle , rect = Circle (2 ), Rectangle (4 , 4 )
174155 test_cases = [
@@ -178,5 +159,7 @@ def detect_circle_rectangle_collision(
178159 ((0 , 0 ), (3 , 3 ), True , "Corner overlap" ),
179160 ]
180161 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+ )
182165 print (f"{ desc } : { '✓' if result == expected else '✗' } " )
0 commit comments