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:
cross_point1 = [xmax, math.tan(theta1) * (xmax - x) + y]
cross_flag1 = 0
elif up_right_theta <= theta1 <= up_left_theta:
cross_point1 = [(ymax - y) / math.tan(theta1) + x, ymax]
cross_flag1 = 1
elif down_left_theta <= theta1 <= down_right_theta:
cross_point1 = [(ymin - y) / math.tan(theta1) + x, ymin]
cross_flag1 = 3
else:
cross_point1 = [xmin, math.tan(theta1) * (xmin - x) + y]
cross_flag1 = 2
if down_right_theta < theta2 < up_right_theta:
cross_point2 = [xmax, math.tan(theta2) * (xmax - x) + y]
cross_flag2 = 0
elif up_right_theta <= theta2 <= up_left_theta:
cross_point2 = [(ymax - y) / math.tan(theta2) + x, ymax]
cross_flag2 = 1
elif down_left_theta <= theta2 <= down_right_theta:
cross_point2 = [(ymin - y) / math.tan(theta2) + x, ymin]
cross_flag2 = 3
else:
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 = eval(input("输入bbox:"))
[xmin, ymin, xmax, ymax] = bbox
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()