Я только что проверил этот код, и он работает нормально.Он проходит все альтернативы для углов и возвращает те, которые ближе всего к 0.
public class Matrix3
{
double a11,a13,a13,a21,a22,a23,a31,a32,a33;
public void GetEulerZXZDegree(out double a, out double b, out double c)
{
GetEulerZXZ(out a, out b, out c);
a*=180/Math.PI;
b*=180/Math.PI;
c*=180/Math.PI;
}
public void GetEulerZXZ(out double a, out double b, out double c)
{
// Options
double[] a_list=new double[] { Math.Atan2(-a13, a23), Math.Atan2(a13, -a23) };
double[] c_list=new double[] { Math.Atan2(a31, a32), Math.Atan2(-a31, -a32) };
double[] b_list=new double[] { Math.PI/2-Math.Asin(a33), -Math.PI/2+Math.Asin(a33) };
int min_a_index=FindMinAbsIndex(a_list);
int min_b_index=FindMinAbsIndex(b_list);
int min_c_index=FindMinAbsIndex(c_list);
a=a_list[min_a_index];
b=b_list[min_b_index];
c=c_list[min_c_index];
}
public void GetEulerZYXDegree(out double a, out double b, out double c)
{
GetEulerZYX(out a, out b, out c);
a*=180/Math.PI;
b*=180/Math.PI;
c*=180/Math.PI;
}
public void GetEulerZYX(out double a, out double b, out double c)
{
// Options
double[] a_list=new double[] { Math.Atan2(a21, a11), Math.Atan2(-a21, -a11) };
double[] c_list=new double[] { Math.Atan2(a32, a33), Math.Atan2(-a32, -a33) };
double[] b_list=new double[] { -Math.Asin(a31), Math.Asin(a31)-Math.PI };
int min_a_index=FindMinAbsIndex(a_list);
int min_b_index=FindMinAbsIndex(b_list);
int min_c_index=FindMinAbsIndex(c_list);
a=a_list[min_a_index];
b=b_list[min_b_index];
c=c_list[min_c_index];
}
// This returns the index of the smallest number
public static int FindMinAbsIndex(double[] list)
{
if(list.Length==0) return -1;
double x=Math.Abs(list[0]);
int index=0;
for(int i=1; i<list.Length; i++)
{
if(Math.Abs(list[i])<x)
{
index=i;
x=Math.Abs(list[i]);
}
}
return index;
}
}
Вот модульный тест:
/// <summary>
///A test for GetEulerZXZDegree
///</summary>
[TestMethod()]
public void GetEulerZXZDegreeTest()
{
// Make matrix from three rotations
// RZ(75)*RX(22)*RZ(-12)
Matrix3 target =
Rotations.RotateZDegrees( 75)*
Rotations.RotateXDegrees( 22)*
Rotations.RotateZDegrees(-12);
//Matrix3 target=new Matrix3(
// 0.439367031912771, -0.822208517146682, 0.361842183278486,
// 0.894924870582839, 0.435556129311581, -0.0969553207969503,
// -0.0778850902285301, 0.366420540568700, 0.927183854566759);
double a;
double aExpected=75;
double b;
double bExpected=22;
double c;
double cExpected=-12;
target.GetEulerZXZDegree(out a, out b, out c);
Assert.AreEqual(aExpected, a, 1e-8);
Assert.AreEqual(bExpected, b, 1e-8);
Assert.AreEqual(cExpected, c, 1e-8);
}