C++ 增广矩阵的行归约-三维样条计算

C++ 增广矩阵的行归约-三维样条计算,c++,math,matrix,eigen,spline,C++,Math,Matrix,Eigen,Spline,我正在尝试通过松弛三次样条来实现插值,这可以在本文第5章(第9页)中找到: 到目前为止,我有以下几点: auto GetControlPoints = [](const std::vector<Vector3d>& S) { int n = S.size(); float var = n - 1.0f; MatrixXd M(n - 1, n - 1); VectorXd C[3] = { VectorXd(n - 1),

我正在尝试通过松弛三次样条来实现插值,这可以在本文第5章(第9页)中找到:

到目前为止,我有以下几点:

auto GetControlPoints = [](const std::vector<Vector3d>& S) {
    int n = S.size();
    float var = n - 1.0f;
    MatrixXd M(n - 1, n - 1);
    VectorXd C[3] = {
        VectorXd(n - 1),
        VectorXd(n - 1),
        VectorXd(n - 1)
    };

    for (int i = 0; i < n - 1; ++i) {
        auto r = RowVectorXd(n - 1);

        for (int j = 0; j < n - 1; ++j) {
            if (j == i)
                r[j] = var;
            else if (j == i - 1 || j == i + 1)
                r[j] = 1.f;
            else
                r[j] = 0.f;
        }

        M.row(i) = r;

        if (i == 0) {
            for (int j = 0; j < 3; ++j) {
                C[j] << (n + 1) * S[1][j] - S[0][j];
            }
        }
        else if (i == n - 1) {
            for (int j = 0; j < 3; ++j) {
                C[j] << (n + 1) * S[n - 1][j] - S[n][j];
            }
        }
        else {
            for (int j = 0; j < 3; ++j) {
                C[j] << (n + 1) * S[i][j];
            }
        }
    }

    MatrixXd augMC[3] = {
        MatrixXd(n - 1, n),
        MatrixXd(n - 1, n),
        MatrixXd(n - 1, n)
    };

    for (int i = 0; i < 3; ++i) {
        augMC[i].block(0, 0, n - 1, n - 1) = M;
        augMC[i].block(n - 1, n - 1, n - 1, 1) = C[i].transpose();
    }
};
auto-GetControlPoints=[](const std::vector&S){
int n=S.size();
浮动var=n-1.0f;
矩阵M(n-1,n-1);
向量xd C[3]={
矢量xd(n-1),
矢量xd(n-1),
向量xd(n-1)
};
对于(int i=0;iM*B=C
,您应该对其分解
M
(因为它是对称的,所以您可以使用
LLt
LDLt
分解),然后使用分解的
solve
方法

要设置
M
,还应使用
对角线法(未测试):

矩阵M(n-1,n-1);
M.setZero();
M.对角线().设定常数(n-1.0);
M.对角线();
M.对角线();
LLT lltOfM(M);
对于(inti=0;i<3;++i){B[i]=lltOfM.solve(C[i]);}
对于大型
n
而言,这是次优的,因为它没有利用
M
的三对角结构。您可以为此尝试稀疏模块,但实际上应该有一个直接算法(尽管Eigen没有明确的三对角矩阵类型)


对于
C
您可能还可以使用
MatrixX3d
(我真的不明白如何填充
C
向量——我认为您当前的代码应该在运行时断言,除非
n==2
,或者您禁用了断言)。

您可以使用
PartialPivLU
的内置变量()--但是看起来您实际上想要解决系统
M*B=C
,您应该对其进行分解
M
(因为它是对称的,所以您可以使用LLt或LDLt分解)然后使用分解的
solve
方法。设置
M
会简单得多,使用分解不会得到一致的结果:LLT lltOfM(M);for(int i=0;i<3;++i){B[i]=lltOfM.solve(C[i])}for(int i=0;iMatrixXd M(n - 1, n - 1); M.setZero(); M.diagonal().setConstant(n - 1.0); M.diagonal<1>().setOnes(); M.diagonal<-1>().setOnes(); LLT<MatrixXd> lltOfM(M); for (int i = 0; i < 3; ++i) { B[i] = lltOfM.solve(C[i]); }