Detecting Rectangle collision with a Circle

可紊 提交于 2019-12-03 22:44:42

问题


I have a Circle with a center point (Center_X, Center_Y) and I am detecting if a rectangle falls into it's Radius (Radius). How would I be able to perform this task? I have tried using

if (X - Center_X)^2 + (Y - Center_Y)^2 < Radius^2:
        print(1)

Then I try to draw a circle to fit over this area:

Circle = pygame.draw.circle(Window, Blue, (Center_X, Center_Y), Radius, 0)

But it doesn't seem to line up. Is there something I am doing wrong?


回答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

def collision(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 intersect
    if rright < cleft or rleft > cright or rbottom < ctop or rtop > cbottom:
        return False  # no collision possible

    # check whether any point of rectangle is inside circle's radius
    for 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 radius
            if math.hypot(x-center_x, y-center_y) <= radius:
                return True  # collision detected

    # check if center of circle is inside rectangle
    if rleft <= center_x <= rright and rtop <= center_y <= rbottom:
        return True  # overlaid

    return False  # no collision detected



回答2:


You have two common options for this kind of collision detection.

The first is to understand the ways two 2D objects can collide.

  1. A vertex of one can be inside the other
  2. Their sides can cross (even thought no verice is inside)
  3. 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)

  1. Check that their bounding boxes intersect.
  2. Check whether any vertex of the square is inside the
  3. Check if the center of the circle is inside the rectangle
  4. 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.




回答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 = c
    px = x2-x1
    py = y2-y1

    something = px*px + py*py

    u =  ((x3 - x1) * px + (y3 - y1) * py) / float(something)

    if u > 1:
        u = 1
    elif u < 0:
        u = 0

    x = x1 + u * px
    y = y1 + u * py

    dx = x - x3
    dy = y - y3

    dist = 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:



来源:https://stackoverflow.com/questions/24727773/detecting-rectangle-collision-with-a-circle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!