Skip to content
Snippets Groups Projects
CollisionDetection.py 3.68 KiB
Newer Older
rachelmoan's avatar
rachelmoan committed
from shapely.geometry import Polygon, Point
import matplotlib.pyplot as plt 
import random
import numpy as np
import sys

def shapes_collide(shape_1, shape_2):
    """
    Determine if two circles, two polygons, or a circle and a polygon intersect.
    True if they do intersect, else false
    inputs:
        - shape_1 (Shapely obj): the first shape
        - shape_2 (shapely obj): the second shape
    output:
        - bool
    """
    return shape_1.intersects(shape_2)

def break_edge_into_segments(node1, node2,edge_dir, delta):
    edge_segments = []
    p = node1
    while np.linalg.norm(p - node1) < np.linalg.norm(node2 - node1):
        p = p + delta*edge_dir
        edge_segments.append(p)

    return edge_segments

def paths_collide(path_1, path_2, delta=.3):
rachelmoan's avatar
rachelmoan committed
    """
    Determine if two paths collide with each other. 
    Return true if a collision is detected.
    inputs:
        - path_1 (list): the first path
        - path_2 (list): the second path
        - delta (float): the amount of an edge that is checked at a time
    """
    min_len = min(len(path_1), len(path_2))
    history = []

    for i in range(min_len-1):
        path1_node1 = np.array([path_1[i][0], path_1[i][1]])
        path1_node2 = np.array([path_1[i+1][0], path_1[i+1][1]])
        path2_node1 = np.array([path_2[i][0], path_2[i][1]])
        path2_node2 = np.array([path_2[i+1][0], path_2[i+1][1]])
rachelmoan's avatar
rachelmoan committed

        edge1 = path1_node2 - path1_node1
        edge2 = path2_node2 - path2_node1
        edge1_dir = edge1 / np.linalg.norm(edge1)
        edge2_dir = edge2 / np.linalg.norm(edge2)

        edge1_segments = break_edge_into_segments(path1_node1,path1_node2, edge1_dir, delta)
        edge2_segments = break_edge_into_segments(path2_node1,path2_node2, edge2_dir, delta)

        num_segs = min(len(edge1_segments), len(edge2_segments))
        edge1_segments = edge1_segments[0:num_segs]
        edge2_segments = edge2_segments[0:num_segs]

        for p1,p2 in zip(edge1_segments, edge2_segments):
            circ1 = Point(p1[0],p1[1])
            circ1 = circ1.buffer(.1)
            circ2 = Point(p2[0],p2[1])
            circ2 = circ2.buffer(.1)

            history.append([circ1,circ2])

            if circ1.intersects(circ2): 
                return True, history

    return False, history
    
def draw_path(ax, path, color):
    for i in range(len(path)-1):
        this_node = path[i]
        next_node = path[i+1]

        ax.plot([this_node[0], next_node[0]], [this_node[1], next_node[1]], '-o', color=color)
rachelmoan's avatar
rachelmoan committed

def draw_edge_collision_check(ax, hist):
    for circs in hist:
        circ1 = circs[0]
        circ2 = circs[1]
        print(circ1)
        ax.plot(*circ1.exterior.xy, color="red")
        ax.plot(*circ2.exterior.xy, color="red")


if __name__ == "__main__":

    path1 = [[1,1], [2,2], [3,3], [4,4]]
    path2 = [[.7,1.5], [2,1.5], [3,2.5]]
rachelmoan's avatar
rachelmoan committed

    collide, hist = paths_collide(path1, path2)
rachelmoan's avatar
rachelmoan committed
    print(collide)

    fig, ax = plt.subplots()

    draw_path(ax,path1,"tab:blue")
    draw_path(ax,path2,"tab:green")

    draw_edge_collision_check(ax, hist)

    plt.show()


    # coords = ((0., 0.), (0., 1.), (1., 1.), (1., 0.), (0., 0.))
    # polygon = Polygon(coords)
    # print(polygon.area)
    # plt.plot(*polygon.exterior.xy)
    # plt.show()

    # p1 = Polygon([(0,0), (1,1), (1,0), (0,0)])
    # p2 = Polygon([(0,1), (1,0), (1,1), (0,1)])
    # plt.plot(*p1.exterior.xy)
    # plt.plot(*p2.exterior.xy)
    # print(p1.intersects(p2))
    # plt.show()

    # circles = []
    # center2 = Point(2, 2)
    # circles.append(center2.buffer(5))
    # center2 = Point(1, 1)
    # circles.append(center2.buffer(5))
    # for circ in circles:
    #     plt.plot(*circ.exterior.xy)

    # plt.show()

    # print(circles[0].intersects(p1))