Обнаружение столкновения Rectangle с кругом

У меня есть круг с центральной точкой (Center_X, Center_Y), и я обнаруживаю, что в него попадает прямоугольник Радиус (Радиус). Как я смогу выполнить эту задачу? Я пробовал использовать

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

Затем я пытаюсь нарисовать круг для этой области:

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

Но это не похоже на линию. Есть ли что-то, что я делаю неправильно?

Ответ 1

Вот то, что я описывал в своих комментариях, плюс изменения в правильной обработке случая круга внутри большего прямоугольника, который Майкл Андерсон указал в комментарии:

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 radius
    for x in (rleft, rleft+width):
        for y in (rtop, rtop+height):
            # compare distance between circle center point and each point of
            # the rectangle with the circle 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

У вас есть два общих варианта для такого обнаружения столкновения.

Во-первых, чтобы понять, как могут столкнуться два 2D-объекта.

  • Вершина одного может быть внутри другого
  • Их стороны могут пересекаться (даже не думая, что внутри нет)
  • Можно быть полностью внутренним для другого.

Технически случай 1. может произойти только в том случае, если также имеет место случай 2, но он часто является более дешевой проверкой. Также случай 3 проверяется случаем 1, в случае, когда проверяются обе вершины объектов.

Я бы сделал так. (так как это в порядке дешевизны)

  • Убедитесь, что их ограничивающие прямоугольники пересекаются.
  • Проверьте, находится ли какая-либо вершина квадрата внутри
  • Проверьте, находится ли центр круга внутри прямоугольника
  • Проверьте пересечения границ круга.

Второй и более общий метод основан на понятии продукта/расширения форм. Эта операция позволяет преобразовать вопрос о пересечении в вопрос одержимости точки.

В этом случае пересечение прямоугольника прямоугольника/прямоугольника можно заменить проверкой на точку в закругленном прямоугольнике.

Ответ 3

Используйте функцию dist из кратчайшее расстояние между точкой и сегментом линии

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

Вот тест:

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)

выход:

[1.044030650891055, 1.0394155162323753, 2.202271554554524, 2.0592194189509323]
False

Вот сюжет:

enter image description here