# Utils for detection functions
# Written by Junjie Ye

from shapely.geometry import Polygon, LineString
import numpy as np

def polygons_overlap(poly1, poly2):
    """
    Determine if two polygons overlap.
    
    poly1 and poly2 are lists of (x, y) tuples representing the vertices of each polygon.
    """
    polygon1 = Polygon(poly1)
    polygon2 = Polygon(poly2)
    
    # Check if the current polygons intersect each other
    if polygon1.intersects(polygon2):
        # Check for proper intersection (excluding boundary touching)
        if polygon1.touches(polygon2):
            # Polygons touch but do not overlap
            return False
        else:
            # Polygons overlap
            return True
    else:
        # Polygons do not intersect and hence do not overlap
        return False

def point_to_segment_dist(point, segment_start, segment_end):
    """Calculate the distance from a point to a line segment."""
    p1 = np.array(point)
    p2 = np.array(segment_start)
    p3 = np.array(segment_end)
    if np.all(p2 == p3):
        return np.linalg.norm(p1 - p2)
    else:
        # Calculate the projection of point p1 onto the line defined by p2 and p3
        t = np.dot(p1 - p2, p3 - p2) / np.dot(p3 - p2, p3 - p2)
        t = max(0, min(1, t))
        # This is the projection point on the line segment
        projection = p2 + t * (p3 - p2)
        return np.linalg.norm(p1 - projection)

def polygon_distance(poly1, poly2):
    """Calculate the minimum distance between two polygons."""
    min_dist = float('inf')
    
    # Check distances from vertices of poly1 to edges of poly2 and vice versa
    for poly in [poly1, poly2]:
        for i in range(len(poly)):
            p1 = poly[i]
            for j in range(len(poly2)):
                p2_start = poly2[j]
                p2_end = poly2[(j + 1) % len(poly2)]
                dist = point_to_segment_dist(p1, p2_start, p2_end)
                min_dist = min(min_dist, dist)
        
        # Swap polygons for the next iteration
        poly1, poly2 = poly2, poly1

    return min_dist

if __name__ == "__main__":
    # Example usage:
    polygon1 = [(0, 0), (5, 0), (5, 5), (0, 5)]  # Square
    polygon2 = [(6, 6), (8, 6), (8, 8), (6, 8)]  # Another square
    polygon3 = [(4, 4), (6, 4), (6, 6), (4, 6)]  # Overlapping square

    print(polygons_overlap(polygon1, polygon2))  # Should return False
    print(polygons_overlap(polygon1, polygon3))  # Should return True


    # Example usage:
    polygon1 = [(0, 0), (5, 0), (5, 5), (0, 5)]  # Square
    polygon2 = [(6, 6), (8, 6), (8, 8), (6, 8)]  # Another square

    distance = polygon_distance(polygon1, polygon2)
    print(f"The minimum distance between the polygons is: {distance}")