2011-07-17 76 views
5

我試圖計算兩個角度之間的最小差異。兩個角度之間的最小差異?

這是我當前的代碼(的東西,我在網上找到一個微小的變化):

float a1 = MathHelper.ToDegrees(Rot); 
float a2 = MathHelper.ToDegrees(m_fTargetRot); 

float dif = (float)(Math.Abs(a1 - a2); 

if (dif > 180) 
    dif = 360 - dif; 

dif = MathHelper.ToRadians(dif); 

它正常工作,除了在案件在一個圓圈的邊緣。例如,如果當前角度是355,目標角度是5,則它計算差值爲-350而不是10,因爲365度等於5度。

關於我能做些什麼的任何想法?

+0

這看起來是正確的。你也不需要轉換爲度數然後回到弧度 - 你可以用弧度來計算 –

+4

答案中沒有對'MathHelper.WrapAngle'的熱愛:( –

+0

偉大的呼叫,@安德魯我沒有任何知識就來到這裏MathHelper,但WrapAngle似乎是寫作解決方案,希望你已經發布了一個解決方案,但是因爲你沒有,我會更新我的答案 – Prestaul

回答

7

你基本上已經擁有了它。只取DIF模量360檢查,看看是否大於180的前面:

float a1 = MathHelper.ToDegrees(Rot); 
float a2 = MathHelper.ToDegrees(m_fTargetRot); 

float dif = (float)Math.Abs(a1 - a2) % 360; 

if (dif > 180) 
    dif = 360 - dif; 

dif = MathHelper.ToRadians(dif); 

編輯: @Andrew羅素在評論你的問題做出了很大的點和下面的解決方案採取MathHelper.WrapAngle方法的優點正如他所建議的那樣:

diff = Math.Abs(MathHelper.WrapAngle(a2 - a1)); 
+0

我怎麼知道是增加還是減少差異? – tweetypi

+0

對不起,我不太確定你在問什麼......代碼應該是完整的,並且總會返回一個正值0和180(含)0 – Prestaul

+2

請注意,'MathHelper.WrapAngle'工作在弧度,所以如果你使用它,不要做度轉換(反正它永遠不是必需的:2π弧度= 360度。別忘了我們的朋友'MathHelper.TwoPi'!) –

1

您可以正常化的結果是0 < = THETA < 360:

while(theta < 0) { theta += 360; } 

如果你想保持弧度的答案(推薦):

const Double TwoPi = 2 * Math.Pi; 
while(theta < 0) { theta += TwoPi; } 
3

您將擴大檢查超出界限角度:

if (dif < 0) dif = dif + 360; 
if (dif > 180) dif = 360 - dif; 
+1

爲什麼downvote?如果你不排除你認爲是錯誤的,它可以 – Guffa

1

我從來不喜歡用case語句處理zero-wrapping。相反,我用的是點積的定義來計算兩個角度之間的(無符號)角度:

vec(a) . vec(b) = ||a|| ||b|| cos(theta)

我們只是要做一個和b單位向量,所以||a|| == ||b|| == 1

由於vec(x) = [cos(x),sin(x)],我們得到:

unsigned_angle_theta(a,b) = acos(cos(a)cos(b) + sin(a)sin(b)) 

(弧度注:各個角度)