【问题标题】:Rectangle/Rectangle Collision Detection矩形/矩形碰撞检测
【发布时间】:2019-01-25 17:06:38
【问题描述】:

我正在尝试解决两个矩形相互交叉/重叠的问题。发生这种情况时,我想知道交集是真还是假。我找到了一个解决方案,但是它是用 C 或 C++ 编写的。我想用 Python 编写这些代码。

这里是来源:http://www.jeffreythompson.org/collision-detection/rect-rect.php

【问题讨论】:

  • 你的问题是什么?
  • 到目前为止你取得了什么成就?
  • 听起来像一个简单的几何/数学问题。一旦你理解了基础数学,用任何编程语言实现一个解决方案应该是微不足道的。

标签: python-3.x rectangles


【解决方案1】:

这是我写过的第一行 Python 代码(不过我知道 C++)

def rectRect(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h):

    # are the sides of one rectangle touching the other?

    return r1x + r1w >= r2x and \   # r1 right edge past r2 left
        r1x <= r2x + r2w and \  # r1 left edge past r2 right
        r1y + r1h >= r2y and \   # r1 top edge past r2 bottom
        r1y <= r2y + r2h    # r1 bottom edge past r2 top

恕我直言 rectRect 是一个非常糟糕的函数名称,但是我将它从链接代码中保留下来。

【讨论】:

    【解决方案2】:

    以下是一个简单的类,可以执行矩形-矩形相交以及点到矩形相交。与早期解决方案的区别在于,跟随 sn-p 甚至可以检测到旋转的矩形。

    import numpy as np
    import matplotlib.pyplot as plt
    
    
    class Rectangle:
        def __init__(self, center: np.ndarray, dims: np.ndarray, angle: float):
            self.corners = self.get_rect_points(center, dims, angle)
            self.area = dims[0] * dims[1]
    
        @staticmethod
        def get_rect_points(center: np.ndarray, dims: np.ndarray, angle: float):
            """
            returns four corners of the rectangle.
            bottom left is the first conrner, from there it goes
            counter clockwise.
            """
            center = np.asarray(center)
            length, breadth = dims
            angle = np.deg2rad(angle)
            corners = np.array([[-length/2, -breadth/2],
                                [length/2, -breadth/2],
                                [length/2, breadth/2],
                                [-length/2, breadth/2]])
            rot = np.array([[np.cos(angle), np.sin(angle)], [-np.sin(angle), np.cos(angle)]])
            corners = rot.dot(corners.T) + center[:, None]
            return corners.T
    
        def is_point_in_collision(self, p: np.ndarray):
            """
            check if a point is in collision with the rectangle.
            """
            def area_triangle(a, b, c):
                return abs((b[0] * a[1] - a[0] * b[1]) + (c[0] * b[1] - b[0] * c[1]) + (a[0] * c[1] - c[0] * a[1])) / 2
    
            area = 0
            area += area_triangle(self.corners[0], p, self.corners[3])
            area += area_triangle(self.corners[3], p, self.corners[2])
            area += area_triangle(self.corners[2], p, self.corners[1])
            area += area_triangle(self.corners[1], p, self.corners[0])
            return area > self.area
    
        def is_intersect(self, rect_2: Rectangle):
            """
            check if any of the four corners of the
            rectangle is in collision
            """
            if not np.all([self.is_point_in_collision(c) for c in rect_2.corners]):
                return True
            return False
    
    
    def plot_rect(p1, p2, p3, p4, color='r'):
        ax.plot([p1[0], p2[0]], [p1[1], p2[1]], color)
        ax.plot([p2[0], p3[0]], [p2[1], p3[1]], color)
        ax.plot([p3[0], p4[0]], [p3[1], p4[1]], color)
        ax.plot([p4[0], p1[0]], [p4[1], p1[1]], color)
        mid_point = 0.5 * (p1 + p3)
        plt.scatter(mid_point[0], mid_point[1], marker='*')
        plt.xlim([-1, 1])
        plt.ylim([-1, 1])
    

    以下是两个示例:

    样本 1:

    ax = plt.subplot(111)
    st = Rectangle((0.067, 0.476),(0.61, 0.41), 90)
    gripper = Rectangle((-0.367, 0.476),(0.21,0.16), 45)
    plot_rect(*st.corners)
    plot_rect(*gripper.corners)
    plt.show()
    print(f"gripper and rectangle intersect: {st.is_intersect(gripper)}")
    

    示例 2:

    ax = plt.subplot(111)
    st = Rectangle((0.067, 0.476),(0.61, 0.41), 90)
    gripper = Rectangle((-0.167, 0.476),(0.21,0.16), 45)
    plot_rect(*st.corners)
    plot_rect(*gripper.corners)
    plt.show()
    print(f"gripper and rectangle intersect: {st.is_intersect(gripper)}")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-12
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多