Detecting Rectangle Collision With A Circle
Solution 1:
Here's what I was describing in my comments, plus changes to correct handling of the case of a circle inside a larger rectangle which Michael Anderson pointed out in a comment:
import math
defcollision(rleft, rtop, width, height, # rectangle definition
center_x, center_y, radius): # circle definition""" Detect collision between a rectangle and circle. """# complete boundbox of the rectangle
rright, rbottom = rleft + width/2, rtop + height/2# bounding box of the circle
cleft, ctop = center_x-radius, center_y-radius
cright, cbottom = center_x+radius, center_y+radius
# trivial reject if bounding boxes do not intersectif rright < cleft or rleft > cright or rbottom < ctop or rtop > cbottom:
returnFalse# no collision possible# check whether any point of rectangle is inside circle's radiusfor x in (rleft, rleft+width):
for y in (rtop, rtop+height):
# compare distance between circle's center point and each point of# the rectangle with the circle's radiusif math.hypot(x-center_x, y-center_y) <= radius:
returnTrue# collision detected# check if center of circle is inside rectangleif rleft <= center_x <= rright and rtop <= center_y <= rbottom:
returnTrue# overlaidreturnFalse# no collision detected
Solution 2:
You have two common options for this kind of collision detection.
The first is to understand the ways two 2D objects can collide.
- A vertex of one can be inside the other
- Their sides can cross (even thought no verice is inside)
- One can be completely interior to the other.
Technically case 1. can only occur if case 2. also occurs, but it is often a cheaper check. Also case 3 is checked by case 1, in the case where both objects vertices are checked.
I would proceed like this. (as it is in order of cheapness)
- Check that their bounding boxes intersect.
- Check whether any vertex of the square is inside the
- Check if the center of the circle is inside the rectangle
- Check for circle - edge intersections.
The second and more general method is based on the notion of the product / expansion of shapes. This operation allows you to convert the intersection question into a point containment question.
In this case the circle / rectangle box intersection can be replaced with a check for a point in a rounded rectangle.
Solution 3:
Use the dist
function from Shortest distance between a point and a line segment
import math
def dist(p1, p2, c):
x1,y1 = p1
x2,y2 = p2
x3,y3 = cpx= x2-x1py= y2-y1something= px*px + py*pyu= ((x3 - x1) * px + (y3 - y1) * py) / float(something)
if u > 1:
u = 1
elif u < 0:
u = 0
x = x1 + u * pxy= y1 + u * pydx= x - x3dy= y - y3dist= math.sqrt(dx*dx + dy*dy)
return dist
Here is a test:
rect = [[0. , 0. ],
[ 0.2, 1. ],
[ 2.2, 0.6],
[ 2. , -0.4]]
c = 0.5, 2.0
r = 1.0
distances = [dist(rect[i], rect[j], c) for i, j in zip([0, 1, 2, 3], [1, 2, 3, 0])]
print distances
print any(d < r for d in distances)
output:
[1.044030650891055, 1.0394155162323753, 2.202271554554524, 2.0592194189509323]
False
Here is the plot:
Post a Comment for "Detecting Rectangle Collision With A Circle"