2012-07-19 71 views
1

我是用於地鐵應用程序的winrt的實驗kinect。 我正試圖在肘部取得角度。使用3個給定的3d點計算角度

通常我會做以下

Vector3D handLeftVector = new Vector3D(HandLeftX, HandLeftY, HandLeftZ); 
handLeftVector.Normalize(); 

Vector3D ElbowLeftEVector = new Vector3D(ElbowLeftX, ElbowLeftY, ElbowLeftZ); 
ElbowLeftEVector.Normalize(); 

Vector3D ShoulderLeftVector = new Vector3D(ShoulderLeftX, ShoulderLeftY, ShoulderLeftZ); 
ShoulderLeftVector.Normalize(); 

Vector3D leftElbowV1 = ShoulderLeftVector - ElbowLeftEVector; 
Vector3D leftElbowV2 = handLeftVector - ElbowLeftEVector; 
double leftElbowAngle = Vector3D.AngleBetween(leftElbowV1, leftElbowV2); 

然而Vector3D對象是不是在WinRT中使用。

我決定複製Vector3D方法如下。但結果似乎並不如預期。我在任何地方犯了錯誤嗎?

double leftElbowV1X = ShoulderLeftX - ElbowLeftX; 
double leftElbowV1Y = ShoulderLeftY - ElbowLeftY; 
double leftElbowV1Z = ShoulderLeftZ - ElbowLeftZ; 

double leftElbowV2X = handLeftX - ElbowLeftX; 
double leftElbowV2Y = handLeftY - ElbowLeftY; 
double leftElbowV2Z = handLeftZ - ElbowLeftZ; 

double product = leftElbowV1X * leftElbowV2X + leftElbowV1Y * leftElbowV2Y + leftElbowV1Z * leftElbowV2Z; 

double magnitudeA = Math.Sqrt(Math.Pow(leftElbowV1X, 2) + Math.Pow(leftElbowV1Y, 2) + Math.Pow(leftElbowV1Z, 2)); 
double magnitudeB = Math.Sqrt(Math.Pow(leftElbowV2X, 2) + Math.Pow(leftElbowV2Y, 2) + Math.Pow(leftElbowV2Z, 2)); 
magnitudeA = Math.Abs(magnitudeA); 
magnitudeB = Math.Abs(magnitudeB); 

double cosDelta = product/(magnitudeA * magnitudeB); 
double angle = Math.Acos(cosDelta) *180.0/Math.P; 

是否需要規範化它?

我已經設法解決它,但我想如果有一個更有效的方法。

+1

如果您使用ILSpy(http://wiki.sharpdevelop.net/ILSpy.ashx)來反編譯'Vector3D'代碼,您應該能夠獲得正確的代碼。 – 2012-07-19 15:11:44

+0

感謝ILSpy,它幫助我確認我的dotproduct是正確的,但是我仍然不確定我的代碼的哪一部分是錯誤的。 – LZH 2012-07-19 16:26:35

+0

請注意,我忘記將rad轉換爲deg – LZH 2012-07-20 03:02:33

回答

0

不知道這是否有助於但是這是一些老的角碼我用,返回度:

float AngleBetween(Vector3 from, Vector3 dest) { 
    float len = from.magnitude * dest.magnitude; 
    if(len < Mathf.Epsilon) len = Mathf.Epsilon; 

    float f = Vector3.Dot(from,dest)/len; 
    if(f>1.0f)f=1.0f; 
    else if (f < -1.0f) f = -1.0f; 

    return Mathf.Acos(f) * 180.0f/(float)Math.PI; 
} 

這顯然使用API​​特定的語法,但我認爲該方法是明確的。