我想找到一种算法,可以找到一个盒子可以围绕图像左上角旋转的角度范围。比如下图中,我可以计算出alpha_1和alpha_2,这就是我想要的角度范围。
但是根据盒子左上角的位置有很多情况,例如下图中,我需要计算不同的角度。
所以我的目的是找到一种算法来解决这个问题。最糟糕的方法是使用大量 if-else 来计算范围,但我想要一种更有效的方法来做到这一点。
编辑:感谢@MBo的想法,这是我解决这个问题的伪代码:
box1 = Polygon(*box1_pts)
# Three circles of box2's width, height and diagonal.
box2_wc = Circle(c=top_left_pt, r=box2_w)
box2_hc = Circle(c=top_left_pt, r=box2_h)
box2_dc = Circle(c=top_left_pt, r=box2_d)
# Angle between box2's diagonal and x-axis.
angle_diag = angle(Line(top_left_pt, top_left_pt+box2_size)
# Find three sectors that box2's width, height and diagonal can rotate within box1.
angle_range_w = find_sector(
points=box1.intersection(box2_wc),
center=top_left_pt,
).angle_range
angle_range_h = find_sector(
points=box1.intersection(box2_hc),
center=top_left_pt,
).angle_range
angle_range_d = find_sector(
points=box1.intersection(box2_dc),
center=top_left_pt,
).angle_range
angle_range_h += 90
angle_range_d += angle_diag
angle_range = intersect_angle_range(angle_range_w, angle_range_h, angle_range_d)
还有另一个相关问题,我想找到红色框可以包含蓝色框的自由旋转范围。红框左上角也固定了
我目前的想法是计算红色框的四个边与蓝色框的四个角相交的角度(如果适用),然后计算与上面相同的相交角度范围。我想知道是否有一种像上面那样有效的方法。
您可以使用 arctan(反正切)函数来计算两点之间的角度。通过获取每个点的坐标值并形成直角三角形,您可以根据点的位置来确定角度是窄还是宽。如果角度较宽,则计算会将其视为较窄的角度,并相应地计算角度。
def calculate_right_triangle(point1, point2):
# Calculate triangle sides
side1 = abs(point2[0] - point1[0])
side2 = abs(point2[1] - point1[1])
hypotenuse = math.sqrt(side1**2 + side2**2)
# Calculate the angles
if point2[1] > point1[1]:
first_angle_degrees = math.degrees(math.atan(side1 / side2))
elif point2[1] < point1[1]:
first_angle_degrees = 180 - math.degrees(math.atan(side1 / side2))
else:
# Handle the case where the points are on the same horizontal line (avoid division by zero)
first_angle_degrees = 0
print(f"First angle: {first_angle_degrees} degrees")
return first_angle_degrees
您有三个自由顶点。每个顶点都有一组自由旋转的有效范围和排除范围(无法旋转)
设小矩形边为
a
和b
,相对于大矩形左下角的轴位置为cx, cy
,大矩形大小为height, width
,起始(零)角度对应于朝下的a
边,侧面b
指向右侧(顺便说一句,最好在问题中描述这样的设置)。
四个外侧可能会给出一些排除侧面的角度间隔
a
:
if a>cy: #with bottom side
intervals += 0..acos(cy/a)
intervals += 2*pi-acos(cy/a)..2*pi
if a>width-cx: #with right side
intervals += pi/2-acos((width-cx)/a)..pi/2+acos((width-cx)/a)
similar for upper and left borders
对角线(
diag_len=sqrt(a*a+b*b)
)和边b
做同样的事情,只需通过对角线和a
之间的角度以及边pi/2
的
b
进行校正
毕竟连接所有排除范围(如使用布尔运算 OR),并反转结果 - 现在它是自由旋转范围的集合。