我可以澄清下面这个 Python 代码吗?

Could I get a clarification to this Python code below?

我是 Python 的初学者,我正在尝试计算下图的角度 (-26.6 和 18.4),使用 Python代码。

我找到了下面的代码,我正在尝试很好地理解它。它怎么能在这里工作?有什么需要说明的吗?

Python代码:

def computeDegree(a,b,c):
    babc = (a[0]-b[0])*(c[0]-b[0])+(a[1]-b[1])*(c[1]-b[1])

    norm_ba = math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
    norm_bc = math.sqrt((c[0]-b[0])**2 + (c[1]-b[1])**2)
    norm_babc = norm_ba * norm_bc

    radian = math.acos(babc/norm_babc)
    degree = math.degrees(radian)
    return round(degree, 1)

def funcAngle(p, s, sn):
    a = (s[0]-p[0], s[1]-p[1])
    b = (sn[0]-p[0], sn[1]-p[1])
    c = a[0] * b[1] - a[1] * b[0]

    if p != sn:
        d = computeDegree(s, p, sn)
    else:
        d = 0

    if c > 0:
        result = d
    elif c < 0:
        result = -d
    elif c == 0:
        result = 0
    return result

p = (1,4)
s = (2,2)
listSn= ((1,2),(2,3),(3,2),(2,1))

for sn in listSn:
    func(p,s,sn)

结果

我希望得到图片中的角度,例如-26.6、18.4 ...

本质上,这是使用点积的定义来求解角度。您可以在 this link(也是我找到这些图片的地方)阅读更多内容。

要求解角度,您首先需要将 3 个输入点转换为两个向量。

# Vector from b to a
# BA = (a[0] - b[0], a[1] - b[1])
BA = a - b

# Vector from b to c
# BC = (a[0] - c[0], a[1] - c[1])
BC = c - b

使用这两个向量,您可以通过首先使用第二个公式求出点积的值来求出它们之间的角度。

# babc = (a[0]-b[0])*(c[0]-b[0])+(a[1]-b[1])*(c[1]-b[1])
dot_product = BA[0] * BC[0] + BA[1] * BC[1]

然后回到第一个定义,你可以除以两个输入向量的长度,结果值应该是向量之间夹角的余弦值。使用数组符号可能很难阅读,但它只是使用毕达哥拉斯定理。

# Length/magnitude of vector BA
# norm_ba = math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
length_ba = math.sqrt(BA[0]**2 + BA[1]**2)

# Length/magnitude of vector BC
# norm_bc = math.sqrt((c[0]-b[0])**2 + (c[1]-b[1])**2)
length_bc = math.sqrt(BC[0]**2 + BC[1]**2)

# Then using acos (essentially inverse of cosine), you can get the angle
# radian = math.acos(babc/norm_babc)
angle = Math.acos(dot_product / (length_ba * length_bc))

大多数其他内容只是为了捕获程序可能意外尝试除以零的情况。希望这有助于解释为什么它看起来像这样。

编辑:我回答这个问题是因为我很无聊并且没有看到解释该代码背后的数学有什么害处,但是以后尽量避免问像 'how does this code work' 将来。

让我们从 funcAngle 开始,因为它稍后会调用 computeDegree。

它做的第一件事是将 a 定义为一个包含两项的元组。很多这段代码似乎使用了两个项目元组,其中两个部分由 v[0]v[1] 或类似的引用。这些几乎可以肯定是某种二维向量。

我将针对向量和 vₓ 和 vᵧ 编写这些,因为它们可能是两个组件。 [不要太仔细看第二个下标,它完全是 y 而不是 gamma...]

asp的向量差:即

a = (s[0]-p[0], s[1]-p[1])

是aₓ=sₓ-pₓ和aᵧ=sᵧ-pᵧ;或者只是 =- 在向量中。

b = (sn[0]-p[0], sn[1]-p[1])

再次; =-

c = a[0] * b[1] - a[1] * b[0]

c=aₓbᵧ-aᵧbₓ; c 是和的叉积(只是一个数字)

if p != sn:
    d = computeDegree(s, p, sn)
else:
    d = 0

我会反过来看:如果 和 相同,那么我们已经知道它们之间的角度为零(并且算法可能严重失败)所以不要计算它。否则,计算角度(我们稍后再看)。

if c > 0:
    result = d
elif c < 0:
    result = -d
elif c == 0:
    result = 0

如果 c 指向法线方向(通过左手定则?右手定则?不记得了)没关系:如果不是,显然我们需要取反角度。

return result

将我们刚刚算出的数字传递给其他代码。

您可以通过添加如下内容来调用此代码:

print (funcangle((1,0),(0,1),(2,2))

最后 运行 它。 (还没有真正测试过这些数字)


所以这个函数计算a和b得到c;如果它指向错误的方向,所有这些都只是为了否定角度。 None 这些变量实际上传递给了 computeDegree。

所以,computeDegree():

def computeDegree(a,b,c):

首先要注意的是之前的变量已经重命名。 funcAngle 通过了 s、p 和 sn,但现在它们被称为 a、b 和 c。请注意,它们传递的顺序与传递给 funcAngle 的顺序不同,这是令人讨厌且令人困惑的。

babc = (a[0]-b[0])*(c[0]-b[0])+(a[1]-b[1])*(c[1]-b[1])

babc = (aₓ-bₓ)(cₓ-bₓ)+(aᵧ-bᵧ)(cᵧ-bᵧ)

如果'和'分别是-和-,这就是

a'ₓc'ₓ+a'ᵧc'ᵧ,或者'和'的点积。

norm_ba = math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)
norm_bc = math.sqrt((c[0]-b[0])**2 + (c[1]-b[1])**2)

norm_ba = √[(aₓ-bₓ)² + (aᵧ-bᵧ)²](和 norm_bc 同样)。

这看起来像是 '(和 ' 分别)的斜边的长度

norm_babc = norm_ba * norm_bc

然后我们将它们相乘

radian = math.acos(babc/norm_babc)

我们使用反余弦(反余弦,cos^-1)函数,将那些相乘的斜边的长度作为斜边,将那个点积作为相邻的长度...

degree = math.degrees(radian)
return round(degree, 1)

但这是以弧度为单位,因此我们将其转换为度数并将其四舍五入以获得良好的格式。


好的,所以现在是数学,而不是 Python,但仍然不是很容易理解。

(旁注:这就是为什么描述性变量名称和文档是每个人的朋友!)