def intersection_projected(rays, buildings):
    """ 3d intersection point between rays and buildings (always the lowest height and assuming buildings have nonbounded heights). Empty Point if no intersection
    Parameters
    ----------
    rays : (n) shapely LineStrings (3d) 

    buildings : (n) polygons (2d) 

    Returns
    -------
    Points: (n) shapely Points (3d) 

    """

    intersections = (building.exterior & ray for building,
                     ray in zip(buildings, rays))

    def lowest(points):
        if points.geom_type == 'Point':
            return points
        # coords = np.asarray(points)
        # # lowest = np.nonzero(coords[:, 2] == min(coords[:, 2]))
        # lowest = np.argmin(coords[:, 2]
        # return points[lowest]
        return min(points, key=lambda x: x.z)

    return (points if points.is_empty else lowest(points) for points in intersections)