角和矩形的交点

import math
from shapely.geometry import Polygon
import geopandas as gpd

import matplotlib.pyplot as plt


def calc_theta(point1, point2):
    delta_x = point2[0] - point1[0]
    delta_y = point2[1] - point1[1]
    if delta_x > 0:  # 第一第四象限,直接用反正切函数
        return math.atan(delta_y / delta_x)
    elif delta_x == 0 and delta_y > 0:
        return math.pi / 2
    elif delta_x == 0 and delta_y < 0:
        return -math.pi / 2
    elif delta_y >= 0:
        return math.atan(delta_y / delta_x) + math.pi
    else:
        return math.atan(delta_y / delta_x) - math.pi


def calc_cross(bbox, center, theta1, theta2):
    [xmin, ymin, xmax, ymax] = bbox
    [x, y] = center
    up_right_theta = calc_theta(center, [xmax, ymax])
    up_left_theta = calc_theta(center, [xmin, ymax])
    down_right_theta = calc_theta(center, [xmax, ymin])
    down_left_theta = calc_theta(center, [xmin, ymin])
    # 第一个交点
    if down_right_theta < theta1 < up_right_theta:  # 和(xmax,?)相交,(?-y)/(xmax-x)=tan(theta1)
        cross_point1 = [xmax, math.tan(theta1) * (xmax - x) + y]
        cross_flag1 = 0  # 和x=xmax相交
    elif up_right_theta <= theta1 <= up_left_theta:  # 和(?,ymax)相交,(ymax-y)/(?-x)=tan(theta1)
        cross_point1 = [(ymax - y) / math.tan(theta1) + x, ymax]
        cross_flag1 = 1  # 和y=ymax相交
    elif down_left_theta <= theta1 <= down_right_theta:  # 和(?,ymin)相交,(ymin-y)/(?-x)=tan(theta1)
        cross_point1 = [(ymin - y) / math.tan(theta1) + x, ymin]
        cross_flag1 = 3  # 和y=ymin相交
    else:  # 和(xmin,?)相交,(?-y)/(xmin-x)=tan(theta1)
        cross_point1 = [xmin, math.tan(theta1) * (xmin - x) + y]
        cross_flag1 = 2  # 和x=xmin相交
    # 第二个交点
    if down_right_theta < theta2 < up_right_theta:  # 和(xmax,?)相交,(?-y)/(xmax-x)=tan(theta1)
        cross_point2 = [xmax, math.tan(theta2) * (xmax - x) + y]
        cross_flag2 = 0
    elif up_right_theta <= theta2 <= up_left_theta:  # 和(?,ymax)相交,(ymax-y)/(?-x)=tan(theta1)
        cross_point2 = [(ymax - y) / math.tan(theta2) + x, ymax]
        cross_flag2 = 1
    elif down_left_theta <= theta2 <= down_right_theta:  # 和(?,ymin)相交,(ymin-y)/(?-x)=tan(theta1)
        cross_point2 = [(ymin - y) / math.tan(theta2) + x, ymin]
        cross_flag2 = 3
    else:  # 和(xmin,?)相交,(?-y)/(xmin-x)=tan(theta1)
        cross_point2 = [xmin, math.tan(theta2) * (xmin - x) + y]
        cross_flag2 = 2

    return {"points": [cross_point1, cross_point2], "flag": [cross_flag1, cross_flag2]}


def make_polygon(bbox, center, cross_point, cross_flag):
    [xmin, ymin, xmax, ymax] = bbox
    cross_point1 = cross_point[0]
    cross_point2 = cross_point[1]
    cross_flag1 = cross_flag[0]  #
    cross_flag2 = cross_flag[1]

    if cross_flag1 == 0 and cross_flag2 == 0:
        if cross_point1[1] < cross_point2[1]:
            point_list = [center, cross_point1, cross_point2]
        else:
            point_list = [center, cross_point1, [xmax, ymax], [xmin, ymax], [xmin, ymin], [xmax, ymin], cross_point2]
    elif cross_flag1 == 0 and cross_flag2 == 1:
        point_list = [center, cross_point1, [xmax, ymax], cross_point2]
    elif cross_flag1 == 0 and cross_flag2 == 2:
        point_list = [center, cross_point1, [xmax, ymax], [xmin, ymax], cross_point2]
    elif cross_flag1 == 0 and cross_flag2 == 3:
        point_list = [center, cross_point1, [xmax, ymax], [xmin, ymax], [xmin, ymin], cross_point2]

    elif cross_flag1 == 1 and cross_flag2 == 0:
        point_list = [center, cross_point1, [xmin, ymax], [xmin, ymin], [xmax, ymin], cross_point2]
    elif cross_flag1 == 1 and cross_flag2 == 1:
        if cross_point1[0] > cross_point2[0]:
            point_list = [center, cross_point1, cross_point2]
        else:
            point_list = [center, cross_point1, [xmin, ymax], [xmin, ymin], [xmax, ymin], [xmax, ymax], cross_point2]
    elif cross_flag1 == 1 and cross_flag2 == 2:
        point_list = [center, cross_point1, [xmin, ymax], cross_point2]
    elif cross_flag1 == 1 and cross_flag2 == 3:
        point_list = [center, cross_point1, [xmin, ymax], [xmin, ymin], cross_point2]

    elif cross_flag1 == 2 and cross_flag2 == 0:
        point_list = [center, cross_point1, [xmin, ymin], [xmax, ymin], cross_point2]
    elif cross_flag1 == 2 and cross_flag2 == 1:
        point_list = [center, cross_point1, [xmin, ymin], [xmax, ymin], [xmax, ymax], cross_point2]
    elif cross_flag1 == 2 and cross_flag2 == 2:
        if cross_point1[1] > cross_point2[1]:
            point_list = [center, cross_point1, cross_point2]
        else:
            point_list = [center, cross_point1, [xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax], cross_point2]
    elif cross_flag1 == 2 and cross_flag2 == 3:
        point_list = [center, cross_point1, [xmin, ymin], cross_point2]

    elif cross_flag1 == 3 and cross_flag2 == 0:
        point_list = [center, cross_point1, [xmax, ymin], cross_point2]
    elif cross_flag1 == 3 and cross_flag2 == 1:
        point_list = [center, cross_point1, [xmax, ymin], [xmax, ymax], cross_point2]
    elif cross_flag1 == 3 and cross_flag2 == 2:
        point_list = [center, cross_point1, [xmax, ymin], [xmax, ymax], [xmin, ymax], cross_point2]
    else:
        if cross_point1[0] < cross_point2[0]:
            point_list = [center, cross_point1, cross_point2]
        else:
            point_list = [center, cross_point1, [xmax, ymin], [xmax, ymax], [xmin, ymax], [xmin, ymin], cross_point2]

    return point_list

def angle_intersect_rectangle(bbox,center,theta1,theta2):
    dic=calc_cross(bbox,center,theta1,theta2)
    cross_point=dic["points"]
    cross_flag=dic["flag"]
    point_list=make_polygon(bbox,center,cross_point,cross_flag)
    point_list=[tuple(point) for point in point_list]
    return Polygon(point_list)
if __name__ == '__main__':
    while 1:
        # bbox=[xmin,ymin,xmax,ymax]
        bbox = eval(input("输入bbox:"))
        [xmin, ymin, xmax, ymax] = bbox
        # center=[xc,yc]
        center = eval(input("输入center:"))

        th1 = eval(input("输入角度1:"))
        th2 = eval(input("输入角度2:"))

        theta1 = th1 / 180 * math.pi
        theta2 = th2 / 180 * math.pi



        polygon=gpd.GeoSeries(angle_intersect_rectangle(bbox,center,theta1,theta2))
        boundary=gpd.GeoSeries(Polygon([(xmin,ymin),(xmax,ymin),(xmax,ymax),(xmin,ymax)]))
        ax=polygon.plot(color="red")
        boundary.boundary.plot(ax=ax,color="yellow")
        plt.show()

你可能感兴趣的:(角和矩形的交点)