2017-04-19 104 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