示例#1
0
void EigenSolver(const Matrix3x3& mtx, float* eigenValues, Vector3* eigenVecs)
{
	double roots[3] = {0.0};
	ComputeRoots(mtx, roots);
	eigenValues[0] = static_cast<float>(roots[0]);
	eigenValues[1] = static_cast<float>(roots[1]);
	eigenValues[2] = static_cast<float>(roots[2]);

	Matrix3x3 m0 = mtx - (Matrix3x3::IDENTITY * eigenValues[0]);
	int m0rank = ::ComputeRank(m0);
	if (m0rank == 0)
	{
		eigenVecs[0] = Vector3(1.0f, 0.0f, 0.0f);
		eigenVecs[1] = Vector3(0.0f, 1.0f, 0.0f);
		eigenVecs[2] = Vector3(0.0f, 0.0f, 1.0f);
		return;
	}
	else if (m0rank == 1)
	{
		GetComplement2(m0.GetRow(0), eigenVecs[0], eigenVecs[1]);
		eigenVecs[2] = eigenVecs[0].Cross(eigenVecs[1]);
		return;
	}

	// m0rank == 2
	eigenVecs[0] = GetComplement1(m0.GetRow(0), m0.GetRow(1));

	Matrix3x3 diag(
		eigenValues[1], 0.0f, 0.0f,
		0.0f, eigenValues[1], 0.0f,
		0.0f, 0.0f, eigenValues[1]);

	Matrix3x3 m1 = mtx - diag;//(Matrix3x3::IDENTITY * eigenValues[1]);
	int m1rank = ComputeRank(m1);
	if (m1rank == 1)
	{
		GetComplement2(eigenVecs[0], eigenVecs[1], eigenVecs[2]);
		return;
	}

	// m1rank == 2
	GetComplement2(eigenVecs[0], eigenVecs[1], eigenVecs[2]);
	//eigenVecs[1] = GetComplement1(m1.GetRow(0), m1.GetRow(1));

	//eigenVecs[2] = eigenVecs[0].Cross(eigenVecs[1]);
}
NoniterativeEigen3x3<Real>::NoniterativeEigen3x3 (const Matrix3<Real>& A)
{
	// Scale the matrix so its entries are in [-1,1].  The scaling is applied
	// only when at least one matrix entry has magnitude larger than 1.
	Matrix3<Real> AScaled = A;
	Real* scaledEntry = (Real*)AScaled;
	Real maxValue = Math<Real>::FAbs(scaledEntry[0]);
	Real absValue = Math<Real>::FAbs(scaledEntry[1]);
	if (absValue > maxValue)
	{
		maxValue = absValue;
	}
	absValue = Math<Real>::FAbs(scaledEntry[2]);
	if (absValue > maxValue)
	{
		maxValue = absValue;
	}
	absValue = Math<Real>::FAbs(scaledEntry[4]);
	if (absValue > maxValue)
	{
		maxValue = absValue;
	}
	absValue = Math<Real>::FAbs(scaledEntry[5]);
	if (absValue > maxValue)
	{
		maxValue = absValue;
	}
	absValue = Math<Real>::FAbs(scaledEntry[8]);
	if (absValue > maxValue)
	{
		maxValue = absValue;
	}

	int i;
	if (maxValue > (Real)1)
	{
		Real invMaxValue = ((Real)1)/maxValue;
		for (i = 0; i < 9; ++i)
		{
			scaledEntry[i] *= invMaxValue;
		}
	}

	// Compute the eigenvalues using double-precision arithmetic.
	double root[3];
	ComputeRoots(AScaled,root);
	mEigenvalue[0] = (Real)root[0];
	mEigenvalue[1] = (Real)root[1];
	mEigenvalue[2] = (Real)root[2];

	Real maxEntry[3];
	Vector3<Real> maxRow[3];
	for (i = 0; i < 3; ++i)
	{
		Matrix3<Real> M = AScaled;
		M[0][0] -= mEigenvalue[i];
		M[1][1] -= mEigenvalue[i];
		M[2][2] -= mEigenvalue[i];
		if (!PositiveRank(M, maxEntry[i], maxRow[i]))
		{
			// Rescale back to the original size.
			if (maxValue > (Real)1)
			{
				for (int j = 0; j < 3; ++j)
				{
					mEigenvalue[j] *= maxValue;
				}
			}

			mEigenvector[0] = Vector3<Real>::UNIT_X;
			mEigenvector[1] = Vector3<Real>::UNIT_Y;
			mEigenvector[2] = Vector3<Real>::UNIT_Z;
			return;
		}
	}

	Real totalMax = maxEntry[0];
	i = 0;
	if (maxEntry[1] > totalMax)
	{
		totalMax = maxEntry[1];
		i = 1;
	}
	if (maxEntry[2] > totalMax)
	{
		i = 2;
	}

	if (i == 0)
	{
		maxRow[0].Normalize();
		ComputeVectors(AScaled, maxRow[0], 1, 2, 0);
	}
	else if (i == 1)
	{
		maxRow[1].Normalize();
		ComputeVectors(AScaled, maxRow[1], 2, 0, 1);
	}
	else
	{
		maxRow[2].Normalize();
		ComputeVectors(AScaled, maxRow[2], 0, 1, 2);
	}

	// Rescale back to the original size.
	if (maxValue > (Real)1)
	{
		for (i = 0; i < 3; ++i)
		{
			mEigenvalue[i] *= maxValue;
		}
	}
}