2017-04-19 102 views
1

我正在寻找一种方法来计算视为两个向量三个点之间的角度(见下文):与结果范围0两个3D向量之间的角度 - 360

using System.Windows.Media.Media3D; 

public static float AngleBetweenThreePoints(Point3D[] points) 
{ 
    var v1 = points[1] - points[0]; 
    var v2 = points[2] - points[1]; 

    var cross = Vector3D.CrossProduct(v1, v2); 
    var dot = Vector3D.DotProduct(v1, v2); 

    var angle = Math.PI - Math.Atan2(cross.Length, dot); 
    return (float) angle; 
} 

如果你把这个以下几点:

var points = new[] 
{ 
    new Point3D(90, 100, 300), 
    new Point3D(100, 200, 300), 
    new Point3D(100, 300, 300) 
}; 

或以下:

var points = new[] 
{ 
    new Point3D(110, 100, 300), 
    new Point3D(100, 200, 300), 
    new Point3D(100, 300, 300) 
}; 

你得到相同的结果。我可以看到函数中的交叉乘积在第一种情况下返回(0,0,10000),而在第二种情况下,(0,0,-10000),但是这些信息在cross.Length中丢失了,它永远不会返回-ve结果。

我在找的是一个结果范围0 - 360不限于0 - 180.我该如何做到这一点?

+0

将不会从Math.PI这是180度减去。你的结果是0到360,所以当你从180减去你得到的结果从+180到-180。 – jdweng

+2

在3D空间中,两个矢量之间的角度仅在0到180度之间定义。在什么情况下你想要180度和360度之间的答案?这很容易在2D空间中定义为有向或有符号的角度,但这不会延伸到3D空间。 –

回答

1

你在找?

θ_radian=反余弦((P⋅Q)/(|P||Q|)),与矢量P和Q

θ_radian=θ_degree*π/ 180

EDIT 0-360范围

angle = angle * 360/(2*Math.PI); 
if (angle < 0) angle = angle + 360; 
+0

这是我的第一个解决方案,但它有相同的问题。它有一个0-180角度的限制。 – imekon

+0

那么弧度角在[-π;π]区间内,而π弧度角是180度,所以是的,这就是你的极限0-180。但我向你展示了一个从弧度转换为度数的公式。 –

+0

arccos的结果范围为0到PI(而不是PI * 2)。因此,我提到的限制180. – imekon

0

答案是提供一种参考UP矢量:

public static float AngleBetweenThreePoints(Point3D[] points, Vector3D up) 
{ 
    var v1 = points[1] - points[0]; 
    var v2 = points[2] - points[1]; 

    var cross = Vector3D.CrossProduct(v1, v2); 
    var dot = Vector3D.DotProduct(v1, v2); 

    var angle = Math.Atan2(cross.Length, dot); 

    var test = Vector3D.DotProduct(up, cross); 
    if (test < 0.0) angle = -angle; 
    return (float) angle; 
} 

这从这里走过:https://stackoverflow.com/a/5190354/181622