📄 wmlmatrix3.inl
字号:
template <class Real>
void Matrix3<Real>::FromEulerAnglesZXY (Real fYAngle, Real fPAngle,
Real fRAngle)
{
Real fCos, fSin;
fCos = Math<Real>::Cos(fYAngle);
fSin = Math<Real>::Sin(fYAngle);
Matrix3 kZMat(
fCos,-fSin,(Real)0.0,
fSin,fCos,(Real)0.0,
(Real)0.0,(Real)0.0,(Real)1.0);
fCos = Math<Real>::Cos(fPAngle);
fSin = Math<Real>::Sin(fPAngle);
Matrix3 kXMat(
(Real)1.0,(Real)0.0,(Real)0.0,
(Real)0.0,fCos,-fSin,
(Real)0.0,fSin,fCos);
fCos = Math<Real>::Cos(fRAngle);
fSin = Math<Real>::Sin(fRAngle);
Matrix3 kYMat(
fCos,(Real)0.0,fSin,
(Real)0.0,(Real)1.0,(Real)0.0,
-fSin,(Real)0.0,fCos);
*this = kZMat*(kXMat*kYMat);
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::FromEulerAnglesZYX (Real fYAngle, Real fPAngle,
Real fRAngle)
{
Real fCos, fSin;
fCos = Math<Real>::Cos(fYAngle);
fSin = Math<Real>::Sin(fYAngle);
Matrix3 kZMat(
fCos,-fSin,(Real)0.0,
fSin,fCos,(Real)0.0,
(Real)0.0,(Real)0.0,(Real)1.0);
fCos = Math<Real>::Cos(fPAngle);
fSin = Math<Real>::Sin(fPAngle);
Matrix3 kYMat(
fCos,(Real)0.0,fSin,
(Real)0.0,(Real)1.0,(Real)0.0,
-fSin,(Real)0.0,fCos);
fCos = Math<Real>::Cos(fRAngle);
fSin = Math<Real>::Sin(fRAngle);
Matrix3 kXMat(
(Real)1.0,(Real)0.0,(Real)0.0,
(Real)0.0,fCos,-fSin,
(Real)0.0,fSin,fCos);
*this = kZMat*(kYMat*kXMat);
}
//----------------------------------------------------------------------------
template <class Real>
Matrix3<Real> Matrix3<Real>::Slerp (Real fT, const Matrix3& rkR0,
const Matrix3& rkR1)
{
Vector3<Real> kAxis;
Real fAngle;
Matrix3 kProd = rkR0.TransposeTimes(rkR1);
kProd.ToAxisAngle(kAxis,fAngle);
return rkR0*Matrix3<Real>(kAxis,fT*fAngle);
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::Tridiagonalize (Real afDiag[3], Real afSubDiag[3])
{
// Householder reduction T = Q^t M Q
// Input:
// mat, symmetric 3x3 matrix M
// Output:
// mat, orthogonal matrix Q (a reflection)
// diag, diagonal entries of T
// subd, subdiagonal entries of T (T is symmetric)
Real fA = m_afEntry[0];
Real fB = m_afEntry[1];
Real fC = m_afEntry[2];
Real fD = m_afEntry[4];
Real fE = m_afEntry[5];
Real fF = m_afEntry[8];
afDiag[0] = fA;
afSubDiag[2] = (Real)0.0;
if ( Math<Real>::FAbs(fC) >= Math<Real>::EPSILON )
{
Real fLength = Math<Real>::Sqrt(fB*fB+fC*fC);
Real fInvLength = ((Real)1.0)/fLength;
fB *= fInvLength;
fC *= fInvLength;
Real fQ = ((Real)2.0)*fB*fE+fC*(fF-fD);
afDiag[1] = fD+fC*fQ;
afDiag[2] = fF-fC*fQ;
afSubDiag[0] = fLength;
afSubDiag[1] = fE-fB*fQ;
m_afEntry[0] = (Real)1.0;
m_afEntry[1] = (Real)0.0;
m_afEntry[2] = (Real)0.0;
m_afEntry[3] = (Real)0.0;
m_afEntry[4] = fB;
m_afEntry[5] = fC;
m_afEntry[6] = (Real)0.0;
m_afEntry[7] = fC;
m_afEntry[8] = -fB;
}
else
{
afDiag[1] = fD;
afDiag[2] = fF;
afSubDiag[0] = fB;
afSubDiag[1] = fE;
m_afEntry[0] = (Real)1.0;
m_afEntry[1] = (Real)0.0;
m_afEntry[2] = (Real)0.0;
m_afEntry[3] = (Real)0.0;
m_afEntry[4] = (Real)1.0;
m_afEntry[5] = (Real)0.0;
m_afEntry[6] = (Real)0.0;
m_afEntry[7] = (Real)0.0;
m_afEntry[8] = -(Real)1.0;
}
}
//----------------------------------------------------------------------------
template <class Real>
bool Matrix3<Real>::QLAlgorithm (Real afDiag[3], Real afSubDiag[3])
{
// QL iteration with implicit shifting to reduce matrix from tridiagonal
// to diagonal
for (int i0 = 0; i0 < 3; i0++)
{
const int iMaxIter = 32;
int iIter;
for (iIter = 0; iIter < iMaxIter; iIter++)
{
int i1;
for (i1 = i0; i1 <= 1; i1++)
{
Real fSum = Math<Real>::FAbs(afDiag[i1]) +
Math<Real>::FAbs(afDiag[i1+1]);
if ( Math<Real>::FAbs(afSubDiag[i1]) + fSum == fSum )
break;
}
if ( i1 == i0 )
break;
Real fTmp0 = (afDiag[i0+1] - afDiag[i0]) /
(((Real)2.0)*afSubDiag[i0]);
Real fTmp1 = Math<Real>::Sqrt(fTmp0*fTmp0+(Real)1.0);
if ( fTmp0 < (Real)0.0 )
fTmp0 = afDiag[i1]-afDiag[i0]+afSubDiag[i0]/(fTmp0-fTmp1);
else
fTmp0 = afDiag[i1]-afDiag[i0]+afSubDiag[i0]/(fTmp0+fTmp1);
Real fSin = (Real)1.0;
Real fCos = (Real)1.0;
Real fTmp2 = (Real)0.0;
for (int i2 = i1-1; i2 >= i0; i2--)
{
Real fTmp3 = fSin*afSubDiag[i2];
Real fTmp4 = fCos*afSubDiag[i2];
if ( Math<Real>::FAbs(fTmp3) >= Math<Real>::FAbs(fTmp0) )
{
fCos = fTmp0/fTmp3;
fTmp1 = Math<Real>::Sqrt(fCos*fCos+(Real)1.0);
afSubDiag[i2+1] = fTmp3*fTmp1;
fSin = ((Real)1.0)/fTmp1;
fCos *= fSin;
}
else
{
fSin = fTmp3/fTmp0;
fTmp1 = Math<Real>::Sqrt(fSin*fSin+(Real)1.0);
afSubDiag[i2+1] = fTmp0*fTmp1;
fCos = ((Real)1.0)/fTmp1;
fSin *= fCos;
}
fTmp0 = afDiag[i2+1]-fTmp2;
fTmp1 = (afDiag[i2]-fTmp0)*fSin+((Real)2.0)*fTmp4*fCos;
fTmp2 = fSin*fTmp1;
afDiag[i2+1] = fTmp0+fTmp2;
fTmp0 = fCos*fTmp1-fTmp4;
for (int iRow = 0; iRow < 3; iRow++)
{
fTmp3 = m_afEntry[I(iRow,i2+1)];
m_afEntry[I(iRow,i2+1)] = fSin*m_afEntry[I(iRow,i2)] +
fCos*fTmp3;
m_afEntry[I(iRow,i2)] = fCos*m_afEntry[I(iRow,i2)] -
fSin*fTmp3;
}
}
afDiag[i0] -= fTmp2;
afSubDiag[i0] = fTmp0;
afSubDiag[i1] = (Real)0.0;
}
if ( iIter == iMaxIter )
{
// should not get here under normal circumstances
assert( false );
return false;
}
}
return true;
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::EigenDecomposition (Matrix3& rkRot, Matrix3& rkDiag)
const
{
// Factor M = R*D*R^T. The columns of R are the eigenvectors. The
// diagonal entries of D are the corresponding eigenvalues.
Real afDiag[3], afSubDiag[3];
rkRot = *this;
rkRot.Tridiagonalize(afDiag,afSubDiag);
rkRot.QLAlgorithm(afDiag,afSubDiag);
// The Householder transformation is a reflection. Make the eigenvectors
// a right--handed system by changing sign on the last column.
rkRot[2][0] = -rkRot[2][0];
rkRot[2][1] = -rkRot[2][1];
rkRot[2][2] = -rkRot[2][2];
// (insertion) sort eigenvalues in increasing order, d0 <= d1 <= d2
int i;
Real fSave;
if ( afDiag[1] < afDiag[0] )
{
// swap d0 and d1
fSave = afDiag[0];
afDiag[0] = afDiag[1];
afDiag[1] = fSave;
// swap V0 and V1
for (i = 0; i < 3; i++)
{
fSave = rkRot[i][0];
rkRot[i][0] = rkRot[i][1];
rkRot[i][1] = fSave;
}
}
if ( afDiag[2] < afDiag[1] )
{
// swap d1 and d2
fSave = afDiag[1];
afDiag[1] = afDiag[2];
afDiag[2] = fSave;
// swap V1 and V2
for (i = 0; i < 3; i++)
{
fSave = rkRot[i][1];
rkRot[i][1] = rkRot[i][2];
rkRot[i][2] = fSave;
}
}
if ( afDiag[1] < afDiag[0] )
{
// swap d0 and d1
fSave = afDiag[0];
afDiag[0] = afDiag[1];
afDiag[1] = fSave;
// swap V0 and V1
for (i = 0; i < 3; i++)
{
fSave = rkRot[i][0];
rkRot[i][0] = rkRot[i][1];
rkRot[i][1] = fSave;
}
}
rkDiag.MakeDiagonal(afDiag[0],afDiag[1],afDiag[2]);
}
//----------------------------------------------------------------------------
template <class Real>
void Matrix3<Real>::Bidiagonalize (Matrix3& rkA, Matrix3& rkL, Matrix3& rkR)
{
Real afV[3], afW[3];
Real fLength, fSign, fT1, fInvT1, fT2;
bool bIdentity;
// map first column to (*,0,0)
fLength = Math<Real>::Sqrt(rkA[0][0]*rkA[0][0] + rkA[1][0]*rkA[1][0] +
rkA[2][0]*rkA[2][0]);
if ( fLength > (Real)0.0 )
{
fSign = (rkA[0][0] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
fT1 = rkA[0][0] + fSign*fLength;
fInvT1 = ((Real)1.0)/fT1;
afV[1] = rkA[1][0]*fInvT1;
afV[2] = rkA[2][0]*fInvT1;
fT2 = -((Real)2.0)/(((Real)1.0)+afV[1]*afV[1]+afV[2]*afV[2]);
afW[0] = fT2*(rkA[0][0]+rkA[1][0]*afV[1]+rkA[2][0]*afV[2]);
afW[1] = fT2*(rkA[0][1]+rkA[1][1]*afV[1]+rkA[2][1]*afV[2]);
afW[2] = fT2*(rkA[0][2]+rkA[1][2]*afV[1]+rkA[2][2]*afV[2]);
rkA[0][0] += afW[0];
rkA[0][1] += afW[1];
rkA[0][2] += afW[2];
rkA[1][1] += afV[1]*afW[1];
rkA[1][2] += afV[1]*afW[2];
rkA[2][1] += afV[2]*afW[1];
rkA[2][2] += afV[2]*afW[2];
rkL[0][0] = ((Real)1.0)+fT2;
rkL[0][1] = fT2*afV[1];
rkL[1][0] = rkL[0][1];
rkL[0][2] = fT2*afV[2];
rkL[2][0] = rkL[0][2];
rkL[1][1] = ((Real)1.0)+fT2*afV[1]*afV[1];
rkL[1][2] = fT2*afV[1]*afV[2];
rkL[2][1] = rkL[1][2];
rkL[2][2] = ((Real)1.0)+fT2*afV[2]*afV[2];
bIdentity = false;
}
else
{
rkL = Matrix3::IDENTITY;
bIdentity = true;
}
// map first row to (*,*,0)
fLength = Math<Real>::Sqrt(rkA[0][1]*rkA[0][1]+rkA[0][2]*rkA[0][2]);
if ( fLength > (Real)0.0 )
{
fSign = (rkA[0][1] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
fT1 = rkA[0][1] + fSign*fLength;
afV[2] = rkA[0][2]/fT1;
fT2 = -((Real)2.0)/(((Real)1.0)+afV[2]*afV[2]);
afW[0] = fT2*(rkA[0][1]+rkA[0][2]*afV[2]);
afW[1] = fT2*(rkA[1][1]+rkA[1][2]*afV[2]);
afW[2] = fT2*(rkA[2][1]+rkA[2][2]*afV[2]);
rkA[0][1] += afW[0];
rkA[1][1] += afW[1];
rkA[1][2] += afW[1]*afV[2];
rkA[2][1] += afW[2];
rkA[2][2] += afW[2]*afV[2];
rkR[0][0] = (Real)1.0;
rkR[0][1] = (Real)0.0;
rkR[1][0] = (Real)0.0;
rkR[0][2] = (Real)0.0;
rkR[2][0] = (Real)0.0;
rkR[1][1] = ((Real)1.0)+fT2;
rkR[1][2] = fT2*afV[2];
rkR[2][1] = rkR[1][2];
rkR[2][2] = ((Real)1.0)+fT2*afV[2]*afV[2];
}
else
{
rkR = Matrix3::IDENTITY;
}
// map second column to (*,*,0)
fLength = Math<Real>::Sqrt(rkA[1][1]*rkA[1][1]+rkA[2][1]*rkA[2][1]);
if ( fLength > (Real)0.0 )
{
fSign = (rkA[1][1] > (Real)0.0 ? (Real)1.0 : -(Real)1.0);
fT1 = rkA[1][1] + fSign*fLength;
afV[2] = rkA[2][1]/fT1;
fT2 = -((Real)2.0)/(((Real)1.0)+afV[2]*afV[2]);
afW[1] = fT2*(rkA[1][1]+rkA[2][1]*afV[2]);
afW[2] = fT2*(rkA[1][2]+rkA[2][2]*afV[2]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -