在 C# 中给定 3x3 矩阵的特征值查找特征向量的算法

Algorithm for finding Eigenvectors given Eigenvalues of a 3x3 matrix in C#

我正在尝试使用 PCA 为我的网格找到最佳的 OOBB 碰撞箱。为此,我需要特征向量,但我有点不知道如何在不使用庞大库的情况下计算它们。

我实现了一种算法,可以计算给定 3x3 矩阵的三个特征值。此代码最初来自 Wikipedia:

private Vector3 CalculateEigenvalues(ref Matrix3 A)
{
    Vector3 val = new Vector3(0, 0, 0);

    float p1 = A.M12 * A.M12 + A.M13 * A.M13 + A.M23 * A.M23;
    if (p1 == 0)
    {
        val.X = A.M11;
        val.Y = A.M22;
        val.Z = A.M33;
    }
    else
    {
        float q = A.Trace / 3f;
        float p2 = (float)(Math.Pow(A.M11 - q, 2) + Math.Pow(A.M22 - q, 2) + Math.Pow(A.M33 - q, 2)) + 2 * p1;
        float p = (float)Math.Sqrt(p2 / 6);
        Matrix4 I = Matrix4.Identity;
        Matrix4.Mult(ref I, q, out Matrix4 tmp);
        Matrix4 tmp2 = Matrix4.Subtract(new Matrix4(A), tmp);
        Matrix4 B = Matrix4.Mult(tmp2, 1 / p);
        float r = new Matrix3(B).Determinant / 2;

        float phi = 0;
        if (r <= -1)
            phi = (float)Math.PI / 3;
        else if (r >= 1)
            phi = 0;
        else
            phi = (float)Math.Acos(r) / 3;
        val.X = q + 2 * p * (float)Math.Cos(phi);
        val.Z = q + 2 * p * (float)Math.Cos(phi + (2 * Math.PI / 3));
        val.Y = 3 * q - val.X - val.Z;
    }
    return val;
}

但是,维基百科文章中没有计算三个特征值的特征向量的代码。我试图理解这个主题,但我的数学技能非常有限。我必须 google 每个教程中的每个第二个字。

所以我的问题是:

如果我有 3x3 矩阵和三个特征值,有没有什么简单的方法可以在不使用外部库的情况下计算相应的特征向量?

对于所有特征值具有相同 algebraic and geometric 重数(旋转矩阵就是这种情况)的情况,绝对简单的实现是这样的:

// Observe that the function doesn't use rZ,
// it is expected that it will become zero vector in triangular form
static Vector3 EigenVector(Vector3 rX, Vector3 rY, Vector3 rZ, float lambda)
{
    // Move RHS to LHS
    rX.X -= lambda;
    rY.Y -= lambda;
    // Transform to upper triangle
    rY -= rX * (rY.X / rX.X);
    // Backsubstitute
    var res = new Vector3(1f);
    res.Y = -rY.Z / rY.Y;
    res.X = -(rX.Y * res.Y + rX.Z * res.Z) / rX.X;
    return res;
}

// Case of eigenvalue with algebraic multiplicity two
static (Vector3, Vector3) EigenVector2(Vector3 rX, Vector3 rY, Vector3 rZ, float lambda)
{
    // Move RHS to LHS
    rX.X -= lambda;
    float x2 = rX.Y / rX.X;
    float x3 = rX.Z / rX.X;
    return (new Vector3(x2, 1, 0), new Vector3(x3, 0, 1));
}

static void Main(string[] args)
{
    var rX = new Vector3(1, -3, 3);
    var rY = new Vector3(3, -5, 3);
    var rZ = new Vector3(6, -6, 4);
    var e = EigenVector(rX, rY, rZ, 4);
    var e2 = EigenVector2(rX, rY, rZ, 2);

    System.Diagnostics.Debug.WriteLine(e.ToString());
    System.Diagnostics.Debug.WriteLine(e2.Item1.ToString());
    System.Diagnostics.Debug.WriteLine(e2.Item2.ToString());
}

<0,5  0,5  1>
<3  1  0>
<-3  0  1>

在现实生活中,需要进行大量的错误检查。输入数据取自 this paper.