RSMesh 1.0.0
一个曲面重构的系统,输入为点云,输出为obj,stl等主流格式的网格文件,使用的方法为径向基函数插值,采取了并行优化、Intel-MKL等优化措施,支持百万级别的点云
载入中...
搜索中...
未找到
rbf_solver.h
1//
2// Created by RainSure on 2024/2/4.
3//
4
5#ifndef RSMESH_RBF_SOLVER_H
6#define RSMESH_RBF_SOLVER_H
7
8#include <iomanip>
9#include <iostream>
10#include <memory>
11#include <stdexcept>
12#include "Eigen/Core"
13#include "common/macros.h"
14#include "common/orthonormalize.h"
15#include "geometry/bbox3d.h"
16#include "geometry/point3d.h"
17#include "interpolation/rbf_operator.h"
18#include "interpolation/rbf_residual_evaluator.h"
19#include "krylov/fgmres.h"
20#include "model.h"
21#include "polynomial/monomial_basis.h"
22#include "preconditioner/ras_preconditioner.h"
23#include "types.h"
24
25namespace rsmesh::interpolation {
26 class rbf_solver {
28
29 public:
30 rbf_solver(const model& model, const geometry::points3d& points)
31 : model_(model), n_poly_basis_(model.poly_basis_size()), n_points_(points.rows()) {
32 op_ = std::make_unique<rbf_operator<>>(model, points);
33 res_eval_ = std::make_unique<rbf_residual_evaluator>(model, points);
34
35 set_points(points);
36 }
37
38 rbf_solver(const model& model, int tree_height, const geometry::bbox3d& bbox) :
39 model_(model), n_poly_basis_(model.poly_basis_size()) {
40 op_ = std::make_unique<rbf_operator<>>(model, tree_height, bbox);
41 res_eval_ = std::make_unique<rbf_residual_evaluator>(model, tree_height, bbox);
42 }
43
44 void set_points(const geometry::points3d& points) {
45 n_points_ = points.rows();
46
47 op_->set_points(points);
48 res_eval_->set_points(points);
49
50 pc_ = std::make_unique<Preconditioner>(model_, points);
51 if (n_poly_basis_ > 0) {
52 polynomial::monomial_basis poly(model_.poly_dimension(), model_.poly_degree());
53 p_ = poly.evaluate(points).transpose();
54 common::orthonormalize_cols(p_);
55 }
56 }
57 template <class Derived>
58 valuesd solve(const Eigen::MatrixBase<Derived>& values, double absolute_tolerance,
59 int max_iter) const {
60 RSMESH_ASSERT(values.rows() == n_points_);
61
62 return solve_impl(values, absolute_tolerance, max_iter);
63 }
64
65 template <class Derived, class Derived2>
66 valuesd solve(const Eigen::MatrixBase<Derived>& values, double absolute_tolerance,
67 int max_iter, const Eigen::MatrixBase<Derived2>& initial_solution) const {
68 RSMESH_ASSERT(values.rows() == n_points_);
69 RSMESH_ASSERT(initial_solution.rows() == n_points_ + n_poly_basis_);
70
71 valuesd ini_sol = initial_solution;
72
73 if (n_poly_basis_ > 0) {
74 // Orthogonalize weights against P.
75 auto n_cols = p_.cols();
76 for (index_t i = 0; i < n_cols; i++) {
77 ini_sol.head(n_points_) -= p_.col(i).dot(ini_sol.head(n_points_)) * p_.col(i);
78 }
79 }
80
81 return solve_impl(values, absolute_tolerance, max_iter, &ini_sol);
82 }
83
84 private:
85 template <class Derived, class Derived2 = valuesd>
86 valuesd solve_impl(const Eigen::MatrixBase<Derived>& values, double absolute_tolerance,
87 int max_iter,
88 const Eigen::MatrixBase<Derived2> *initial_solution = nullptr) const {
89 // The solver does not work when all values are zero
90 if(values.isZero()) {
91 return valuesd::Zero(n_points_ + n_poly_basis_);
92 }
93
94 valuesd rhs(n_points_ + n_poly_basis_);
95 rhs.head(n_points_) = values;
96 rhs.tail(n_poly_basis_) = valuesd::Zero(n_poly_basis_);
97
98 krylov::fgmres solver(*op_, rhs, max_iter);
99 if(initial_solution != nullptr) {
100 solver.set_initial_solution(*initial_solution);
101 }
102 solver.set_right_preconditioner(*pc_);
103 solver.setup();
104
105 std::cout << std::setw(4) << "iter" << std::setw(16) << "rel_res" << std::endl
106 << std::setw(4) << solver.iteration_count() << std::setw(16) << std::scientific
107 << solver.relative_residual() << std::defaultfloat << std::endl;
108 valuesd solution;
109 while(true) {
110 solver.iterate_process();
111 solution = solver.solution_vector();
112 std::cout << std::setw(4) << solver.iteration_count() << std::setw(16) << std::scientific
113 << solver.relative_residual() << std::defaultfloat << std::endl;
114
115 auto convergence = res_eval_->converged(values, solution, absolute_tolerance);
116 if (convergence.first) {
117 std::cout << "Achieved absolute residual: " << convergence.second << std::endl;
118 break;
119 }
120 if(solver.iteration_count() == solver.max_iterations()) {
121 throw std::runtime_error("Reached the maximum number of iterations.");
122 }
123 }
124 return solution;
125 }
126 const model& model_;
127 const index_t n_poly_basis_;
128
129 index_t n_points_{};
130 std::unique_ptr<rbf_operator<>> op_;
131 std::unique_ptr<Preconditioner> pc_;
132 std::unique_ptr<rbf_residual_evaluator> res_eval_;
133 Eigen::MatrixXd p_;
134 };
135}
136
137
138#endif //RSMESH_RBF_SOLVER_H
描述了一个插值模型
Definition model.h:21
vectors3d points3d
3维点的集合
Definition point3d.h:48
该命名空间下主要定义了插值相关的类和函数