我们使用以下代码计算两条线之间的锐角。
def AcuteAngle2(line1,line2):
''':: line(x1,y1,x2,y2)'''
u = (line1[2]-line1[0], line1[3]-line1[1])
v = (line2[2]-line2[0], line2[3]-line2[1])
return arccos(abs(dot(u,v)/(norm(u)*norm(v))))
它按预期工作。例如:
>>> AcuteAngle2([0,0,1,0],[0,0,0,1])
1.5707963267948966 #in rad = 90 degree
但是我们最近发现它在某些特殊情况下会失败!
>>> AcuteAngle2([0,0,1,0],[0,0,1,0])
0.0
这是正确的,但是:
>>> AcuteAngle2([0,0,1,1],[0,0,1,1])
2.1073424255447017e-08 #failed!
这是不正确的!它应该是 0.0。
有什么想法和解决方案吗?
更新 1:
按照以下答案中的建议使用 Decimal
包可能对某些情况有所帮助。然而,我们的问题仍未解决,因为 (1) 有很多代码需要大量时间来调整每个部分以使用 Decimal
。此外,(2)性能显着下降。此外,它需要 (3) 在处理 numpy
数组时进行大量更改。因此它对我们的案例没有用。我们正在考虑某种装饰器等,而不改变任何东西,同时保持 numpy
的性能。顺便说一句,有些人可能会建议使用 gmpy 等多精度包,请注意它们需要在代码中进行大量调整,这对我们的情况没有帮助。
最佳答案
如果您关心准确性,则对锐角使用 arccos
不是一个好主意。问题在于,对于接近 0 的角度的微小变化,该角度的余弦几乎不会改变。对于 arccos
,情况正好相反 - 对于余弦角变化非常非常小的变化。
在 2D 和 3D 中,更好的方法是使用 atan2(crossproduct.length,scalarproduct)
在 2D 中,这变为 atan2( dx1*dy2-dx2*dy1 , dx1*dy1+dx2*dy2 )
。请注意,您不需要规范化向量,因此有两个改进:
arccos
没有错误放大- 没有平方根的额外误差
关于Python:计算锐角的精度失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16966325/