""" Geographic utilities: point-in-polygon testing via ray casting. """ def point_in_polygon(lat: float, lon: float, polygon_coords: list) -> bool: """Check if a point is inside a polygon (supports Polygon and MultiPolygon).""" if not polygon_coords: return False # MultiPolygon: check each polygon if isinstance(polygon_coords[0], list) and isinstance(polygon_coords[0][0], list): for polygon in polygon_coords: if polygon and isinstance(polygon[0], list): ring = polygon[0] if isinstance(polygon[0][0], list) else polygon if point_in_ring(lat, lon, ring): return True return False # Single Polygon: use first ring (outer boundary) ring = polygon_coords[0] if isinstance(polygon_coords[0], list) else polygon_coords return point_in_ring(lat, lon, ring) def point_in_ring(lat: float, lon: float, ring: list) -> bool: """Ray casting algorithm for point-in-ring test.""" n = len(ring) inside = False x, y = lon, lat p1x, p1y = ring[0] for i in range(1, n + 1): p2x, p2y = ring[i % n] if y > min(p1y, p2y): if y <= max(p1y, p2y): if x <= max(p1x, p2x): xinters = (y - p1y) * (p2x - p1x) / (p2y - p1y) if p1y != p2y else p1x if p1x == p2x or x <= xinters: inside = not inside p1x, p1y = p2x, p2y return inside