C++ 增广矩阵的行归约-三维样条计算
我正在尝试通过松弛三次样条来实现插值,这可以在本文第5章(第9页)中找到: 到目前为止,我有以下几点: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),
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]); }