RSMesh 1.0.0
一个曲面重构的系统,输入为点云,输出为obj,stl等主流格式的网格文件,使用的方法为径向基函数插值,采取了并行优化、Intel-MKL等优化措施,支持百万级别的点云
载入中...
搜索中...
未找到
fine_grid.cpp
1//
2// Created by RainSure on 2024/2/18.
3//
4
5#include "preconditioner/fine_grid.h"
6#include "common/macros.h"
7#include "preconditioner/mat_a.h"
8#include <utility>
9
10namespace rsmesh::preconditioner {
11 fine_grid::fine_grid(const model& model, domain&& domain)
12 : model_(model),
13 point_idcs_(std::move(domain.point_indices)),
14 grad_point_idcs_(std::move(domain.grad_point_indices)),
15 inner_point_(std::move(domain.inner_point)),
16 inner_grad_point_(std::move(domain.inner_grad_point)),
17 dim_(model.poly_dimension()),
18 l_(model.poly_basis_size()),
19 mu_(static_cast<index_t>(point_idcs_.size())),
20 sigma_(static_cast<index_t>(grad_point_idcs_.size())),
21 m_(mu_ + dim_ * sigma_) {
22 RSMESH_ASSERT(mu_ > l_);
23 }
24
25 void fine_grid::clear() {
26 me_ = Eigen::MatrixXd();
27 ldlt_of_qtaq_ = Eigen::LDLT<Eigen::MatrixXd>();
28 }
29
30 void fine_grid::setup(const geometry::points3d& points_full,
31 const Eigen::MatrixXd& lagrange_pt_full) {
32 setup(points_full, geometry::points3d(0, 3), lagrange_pt_full);
33 }
34
35 void fine_grid::setup(const geometry::points3d& points_full,
36 const geometry::points3d& grad_points_full,
37 const Eigen::MatrixXd& lagrange_pt_full) {
38 auto points = points_full(point_idcs_, Eigen::all);
39 auto grad_points = grad_points_full(grad_point_idcs_, Eigen::all);
40
41 // Compute A.
42 auto a = mat_a(model_, points, grad_points);
43
44 if (l_ > 0) {
45 std::vector<index_t> flat_indices(point_idcs_);
46 flat_indices.reserve(mu_ + dim_ * sigma_);
47 for (auto i : grad_point_idcs_) {
48 for (index_t j = 0; j < dim_; j++) {
49 flat_indices.push_back(mu_ + dim_ * i + j);
50 }
51 }
52
53 // Compute -E.
54 auto lagrange_pt = lagrange_pt_full(Eigen::all, flat_indices);
55 me_ = -lagrange_pt.rightCols(m_ - l_);
56
57 // Compute decomposition of Q^T A Q.
58 ldlt_of_qtaq_ = (me_.transpose() * a.topLeftCorner(l_, l_) * me_ +
59 me_.transpose() * a.topRightCorner(l_, m_ - l_) +
60 a.bottomLeftCorner(m_ - l_, l_) * me_ + a.bottomRightCorner(m_ - l_, m_ - l_))
61 .ldlt();
62 } else {
63 ldlt_of_qtaq_ = a.ldlt();
64 }
65
66 mu_full_ = points_full.rows();
67 sigma_full_ = grad_points_full.rows();
68 }
69
70 void fine_grid::set_solution_to(valuesd& weights_full) const {
71 for (index_t i = 0; i < mu_; i++) {
72 if (inner_point_.at(i)) {
73 weights_full(point_idcs_.at(i)) = lambda_(i);
74 }
75 }
76
77 for (index_t i = 0; i < sigma_; i++) {
78 if (inner_grad_point_.at(i)) {
79 weights_full.segment(mu_full_ + dim_ * grad_point_idcs_.at(i), dim_) =
80 lambda_.segment(mu_ + dim_ * i, dim_);
81 }
82 }
83 }
84
85 void fine_grid::solve(const valuesd& values_full) {
86 valuesd values(m_);
87 values.head(mu_) = values_full(point_idcs_);
88 values.tail(dim_ * sigma_).reshaped<Eigen::RowMajor>(sigma_, dim_) =
89 values_full.tail(dim_ * sigma_full_)
90 .reshaped<Eigen::RowMajor>(sigma_full_, dim_)(grad_point_idcs_, Eigen::all);
91
92 if (l_ > 0) {
93 // Compute Q^T d.
94 valuesd qtd = me_.transpose() * values.head(l_) + values.tail(m_ - l_);
95
96 // Solve Q^T A Q gamma = Q^T d for gamma.
97 valuesd gamma = ldlt_of_qtaq_.solve(qtd);
98
99 // Compute lambda = Q gamma.
100 lambda_ = valuesd(m_);
101 lambda_.head(l_) = me_ * gamma;
102 lambda_.tail(m_ - l_) = gamma;
103 } else {
104 lambda_ = ldlt_of_qtaq_.solve(values);
105 }
106 }
107}
该命名空间下主要定义了关于krylov子空间方法的预处理相关的类和函数