2016-03-19 127 views
0

我在寫一個程序,它將圍繞一個點旋轉一個矩形棱鏡。它通過3種旋轉方法處理旋轉,每種旋轉方法都管理圍繞單個軸(X,Y和Z)的旋轉。這裏的代碼Java:旋轉和3D扭曲

public void spinZ(Spin spin) { 

    if (x == 0 && y == 0) { 
     return; 
    } 
    double mag = Math.sqrt(x * x + y * y); 
    double pxr = Math.atan(y/x); 
    x = Math.cos(spin.zr + pxr) * mag; 
    y = Math.sin(spin.zr + pxr) * mag; 
} 
public void spinY(Spin spin) { 

    if (z == 0 && x == 0) { 
     return; 
    } 
    double mag = Math.sqrt(x * x + z * z); 
    double pxr = Math.atan(z/x); 
    x = Math.cos(spin.yr + pxr) * mag; 
    z = Math.sin(spin.yr + pxr) * mag; 
} 
public void spinX(Spin spin) { 

    if (z == 0 && y == 0) { 
     return; 
    } 
    double mag = Math.sqrt(y * y + z * z); 
    double pxr = Math.atan(z/y); 
    y = Math.cos(spin.xr + pxr) * mag; 
    z = Math.sin(spin.xr + pxr) * mag; 
} 

public void addSpin(Spin spin) { 

    spinY(spin); 
    spinX(spin); 
    spinZ(spin); 

} 

自旋是一個無用的類,它存儲三個雙打(這是旋轉)。這些方法基本上將旋轉轉換爲2D向量(我如何存儲點)並旋轉它們。第一條if語句確保2D矢量的大小不爲0.它們被允許,但在這種情況下,不需要執行旋轉計算。另一部分只處理trig。底部方法只是將所有東西都連接在一起,並允許我快速更改旋轉的順序(因爲順序應該並且確實影響最終旋轉)。

問題不在於個人輪換,而在於他們都聚在一起。我可以很容易地在單個軸周圍旋轉一圈,而不會扭曲矩形棱鏡。當我把它們放在一起時,就像你打電話給addSpin()一樣。

當首先調用spinY時,如果旋轉包含Y旋轉(如果旋轉的y分量爲零,並且不會發生圍繞y軸的旋轉,則不會發生扭曲),則棱鏡會失真。實際上,如果隨時調用spinY(),但最後會發生立方體的變形。

spinZ()的情況也是如此。如果最後調用spinZ(),則多維數據集不會變形。但是,spinX()可以去任何地方,而不會導致失真。

所以問題是:我是如何進行旋轉的問題?另一個問題是,雖然所有的旋轉不能僅僅沿着X和Y軸或者任何其他的不同軸(如X和Z,或者Y和Z)旋轉,那麼這三個集合可以共同旋轉嗎?爲了說明,繞X軸和Z軸或Y軸和Z軸的一組旋轉是否可以達到繞X軸和Y軸旋轉一組無法達到的旋轉?

我相信我用來顯示棱鏡的介質。這是我製作的光線跟蹤器,可以很好地處理矩形棱鏡。這是一個更基於數學的問題,但它有一個相當全面的編程組件。

這些是一些並行計算,仍然產生扭曲。

public void spinZ(Spin spin) { 

    double c = Math.cos(spin.yr); 
    double s = Math.sin(spin.yr); 
    double xp = x*c - y*s; 
    double yp = y*s + x*c; 
    x = xp; 
    y = yp; 
} 
public void spinY(Spin spin) { 

    double c = Math.cos(spin.yr); 
    double s = Math.sin(spin.yr); 
    double zp = z*c - x*s; 
    double xp = z*s + x*c; 
    x = xp; 
    z = zp; 
} 
public void spinX(Spin spin) { 

    double c = Math.cos(spin.yr); 
    double s = Math.sin(spin.yr); 
    double yp = y*c - z*s; 
    double zp = z*c + y*s; 
    y = yp; 
    z = zp; 
} 

回答

1

你的東西檢查像

x == 0 

是不必要的和危險的,因爲雙幾乎從不會有精確值0。反正切當你有一個部門能夠導致災難性的精度損失好。

他們爲什麼沒有必要?因爲以下的清潔劑進行您的旋轉(數值穩定)時尚:

double c = Math.cos(spin.yr); 
double s = Math.cos(spin.yr); 
double zp = z*c - x*s; 
double xp = z*s + x*c; 
x = xp; 
z = zp; 

當然,我的例子假定你把用右手方向Y旋轉,但是從你的示例代碼,你似乎是處理它如左手。無論如何,Rotation matrix上的維基百科文章解釋了數學。

+0

我檢查0的原因並不多,當x和z相等時,我不需要計算。這就是當你在java中將0除以0時,你會得到NaN,這會把事情搞砸。這是否會導致扭曲的右手和左手旋轉?我不這麼認爲,但我可能是錯的... –

+0

不,我會想象失真的發生是因爲你的徑向角的計算不能區分(+,+)和( - , - ),也不是(+, - )和( - ,+)座標對。 我知道你爲什麼要檢查零點,但正如我所說的,如果你使用旋轉矩陣計算而不是座標變化,你將有更穩定的計算而不需要分支條件。 –

+0

好的,我用您的計算方法代替我的方法(修改每個方法以匹配旋轉矩陣)並對其進行測試。棱鏡仍然變形。我將粘貼適應的方法以確保觸發檢查。 –