计算两条线之间的角度 (两种选择) 和效率

2024-04-24 14:10:23 发布

您现在位置:Python中文网/ 问答频道 /正文

任务:计算两条线之间的角度

输入:
浮点x1,y1(起点)
浮动x2,y2(终点)
输出:
浮动φ(线之间的角度,单位为度)

另外:
一条线平行于x轴,φ为0°≤φ<;359°

Task Picture


方案1:

import math
rad_to deg = lambda x: 180.0/math.pi * x

# start-point
x1 = float(input("x1: "))
y1 = float(input("y1: "))
# end-point
x2 = float(input("x2: "))
y2 = float(input("y2: "))

# slope of one line (parallel to the x-axis)
m1 = 0

# slope between the start-point and end-point
# special-case: division with zero
if x1 == x2:
    m2 = "Not defined!"
    if y2 > y1: # end-point over start-point
        phi = 90
    elif y2 < y1: # end-point under start-point
        phi = 270
else:
    m2 = (y2 - y2) / (x2 - x1)

# angle between two lines (smaller angle: 0° < phi < 90°)
angle = rad_to_deg(math.atan(abs((m1 - m2) / (1 + m1 * m2))))

if x1 < x2 and y1 < y2: # 1. quadrant
    phi =  sw
elif x1 > x2 and y1 < y2: # 2. quadrant
    phi = 180 - sw
elif x1 > x2 and y1 > y2: # 3. quadrant
    phi = 180 + sw
elif x1 < x2 and y1 > y2: # 4. quadrant
    phi = 360 - sw
elif y1 == y2 and x1 > x2: # end-point left from start-point
    phi = 180
elif y1 == y2 and x1 < x2 : # end-point right from start-point
    phi = 0
elif x1 == x2 and y1 == y2:
    phi = "Error, start-point is end-point"

print("angle phi: " + str(phi))

或者应该是try/except的特例?你知道吗

try:
    m2 = (y2 - y2) / (x2 - x1)
except ZeroDivisionError: # x1 == x2
    m2 = "Not defined!"
    if y2 > y1: # end-point over start-point
        phi = 90
    elif y2 < y1: # end-point under start-point
        phi = 270

选项2:使用矢量

for math import sqrt, acos, pi
rad_to_deg = lambda x: 180.0/pi * x

x1 = float(input("x1: "))
y1 = float(input("y1: "))
x2 = float(input("x1: "))
y2 = float(input("x2: "))

# vectors
u = [1, 0] # start-point and (a point right from the start-point)
v = [x2 - x1, y2 - y1]

# calculation
u_scalar_v = u[0] * v[0] + u[1] * v[1]
u_amount = sqrt(u[0] * u[0] + u[1] * u[1])
v_amount = sqrt(v[0] * v[0] + v[1] * v[1])

# scalar product
phi = round(rad_to_deg(acos(u_scalar_v / (u_amount * v_amount))), 5)

if y2 >= y1:
    pass
else:
    phi = 360 - phi

print(phi)

方案3: 把起点,终点和一个点从s开始,看作一个三角形,然后计算余弦定理


最有效的计算方法是什么?如何确定?你知道吗


Tags: andtoinputiffloatstartendpoint
1条回答
网友
1楼 · 发布于 2024-04-24 14:10:23

Find the Angle between three points from 2D using python提供了一个简单的解决方案。你知道吗

import math

def getAngle(a, b, c):
    ang = math.degrees(math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0]))
    return ang + 360 if ang < 0 else ang

# starting-point
x1 = float(input("x1: "))
y1 = float(input("y1: "))

# middle-point (intersection point)
x2 = float(input("x2: "))
y2 = float(input("y2: "))

# ending point of horizontal line
x3 = x2 + 1  # i.e. horizontal offset from mid-point (x2, y2)
y3 = y2

a = (x1, y1)
b = (x2, y2)
c = (x3, y3)
angle = getAngle(a, b, c)

示例

a = (5, 0)
b = (0, 0)
c = (0, 5)
print(getAngle(a, b, c)) # result 90.0

例2随机点测试

from random import randrange, sample
radius = 10
points = []
for i1 in range(10):
    for i2 in range(10):
        points.append((randrange(-radius, radius+1), randrange(-radius, radius+1)))

x1y1  = sample(points[:50], 10)
x2y2 = sample(points[50:], 10)
x3y3 = [(x+1, y) for x, y in x2y2]

for i in range(len(x1y1)):
    a, b, c = x1y1[i], x2y2[i], x3y3[i]
    angle = getAngle(a, b, c)
    print(i, ": ", a, b, c, '=> ', angle)

结果

0 :  (10, -6) (8, -10) (9, -10) =>  296.565051177078
1 :  (0, -9) (-4, -3) (-3, -3) =>  56.309932474020215
2 :  (-6, 10) (5, 9) (6, 9) =>  185.1944289077348
3 :  (0, 1) (-2, 1) (-1, 1) =>  0.0
4 :  (2, -1) (-3, 7) (-2, 7) =>  57.9946167919165
5 :  (2, -3) (-10, -8) (-9, -8) =>  337.3801350519596
6 :  (2, -6) (-10, 5) (-9, 5) =>  42.510447078000844
7 :  (7, 8) (7, 3) (8, 3) =>  270.0
8 :  (2, -2) (-4, 4) (-3, 4) =>  45.0
9 :  (1, -2) (-2, 7) (-1, 7) =>  71.56505117707799

相关问题 更多 >