RSMesh 1.0.0
一个曲面重构的系统,输入为点云,输出为obj,stl等主流格式的网格文件,使用的方法为径向基函数插值,采取了并行优化、Intel-MKL等优化措施,支持百万级别的点云
载入中...
搜索中...
未找到
interpolant.h
1//
2// Created by RainSure on 2024/2/22.
3//
4
5#ifndef RSMESH_INTERPOLANT_H
6#define RSMESH_INTERPOLANT_H
7
8#include <algorithm>
9#include <memory>
10#include <stdexcept>
11#include <string>
12#include <tuple>
13#include <utility>
14#include <vector>
15#include "geometry/bbox3d.h"
16#include "geometry/point3d.h"
17#include "interpolation/rbf_evaluator.h"
18#include "interpolation/rbf_fitter.h"
19#include "interpolation/rbf_incremental_fitter.h"
20#include "interpolation/rbf_inequality_fitter.h"
21#include "model.h"
22#include "types.h"
23
24namespace rsmesh {
26 public:
27 explicit interpolant(model model) : model_(std::move(model)) {}
28
29 [[nodiscard]] const geometry::points3d& centers() const {
30 if (!fitted_) {
31 throw std::runtime_error(kNotFittedErrorMessage);
32 }
33
34 return centers_;
35 }
36
37 valuesd evaluate(const geometry::points3d& points) {
38 if (!fitted_) {
39 throw std::runtime_error(kNotFittedErrorMessage);
40 }
41
42 set_evaluation_bbox_impl(geometry::bbox3d::from_points(points));
43 return evaluate_impl(points);
44 }
45
46 valuesd evaluate_impl(const geometry::points3d& points) const {
47 if (!fitted_) {
48 throw std::runtime_error(kNotFittedErrorMessage);
49 }
50
51 return evaluator_->evaluate(points);
52 }
53
54 void fit(const geometry::points3d& points, const valuesd& values,
55 double absolute_tolerance, int max_iter = 32) {
56 auto min_n_points = std::max(index_t{1}, model_.poly_basis_size());
57 if (points.rows() < min_n_points) {
58 throw std::invalid_argument("points.rows() must be greater than or equal to " +
59 std::to_string(min_n_points) + ".");
60 }
61
62 if (values.rows() != points.rows()) {
63 throw std::invalid_argument("values.rows() must be equal to points.rows().");
64 }
65
66 if (absolute_tolerance <= 0.0) {
67 throw std::invalid_argument("absolute_tolerance must be greater than 0.0.");
68 }
69
70 clear();
71
72 interpolation::rbf_fitter fitter(model_, points);
73 weights_ = fitter.fit(values, absolute_tolerance, max_iter);
74
75 fitted_ = true;
76 centers_ = points;
77 centers_bbox_ = geometry::bbox3d::from_points(centers_);
78 }
79
80 void fit_incrementally(const geometry::points3d& points, const valuesd& values,
81 double absolute_tolerance, int max_iter = 32) {
82 auto min_n_points = std::max(index_t{1}, model_.poly_basis_size());
83 if (points.rows() < min_n_points) {
84 throw std::invalid_argument("points.rows() must be greater than or equal to " +
85 std::to_string(min_n_points) + ".");
86 }
87
88 if (values.rows() != points.rows()) {
89 throw std::invalid_argument("values.rows() must be equal to points.rows().");
90 }
91
92 if (absolute_tolerance <= 0.0) {
93 throw std::invalid_argument("absolute_tolerance must be greater than 0.0.");
94 }
95
96 clear();
97
98 interpolation::rbf_incremental_fitter fitter(model_, points);
99 std::vector<index_t> center_indices;
100 std::tie(center_indices, weights_) = fitter.fit(values, absolute_tolerance, max_iter);
101
102 fitted_ = true;
103 centers_ = points(center_indices, Eigen::all);
104 centers_bbox_ = geometry::bbox3d::from_points(centers_);
105 }
106
107 void fit_inequality(const geometry::points3d& points, const valuesd& values,
108 const valuesd& values_lb, const valuesd& values_ub,
109 double absolute_tolerance, int max_iter = 32) {
110 if (model_.nugget() > 0.0) {
111 throw std::runtime_error("Non-zero nugget is not supported.");
112 }
113
114 auto min_n_points = std::max(index_t{1}, model_.poly_basis_size());
115 if (points.rows() < min_n_points) {
116 throw std::invalid_argument("points.rows() must be greater than or equal to " +
117 std::to_string(min_n_points) + ".");
118 }
119
120 if (values.rows() != points.rows()) {
121 throw std::invalid_argument("values.rows() must be equal to points.rows().");
122 }
123
124 if (values_lb.rows() != points.rows()) {
125 throw std::invalid_argument("values_lb.rows() must be equal to points.rows().");
126 }
127
128 if (values_ub.rows() != points.rows()) {
129 throw std::invalid_argument("values_ub.rows() must be equal to points.rows().");
130 }
131
132 if (absolute_tolerance <= 0.0) {
133 throw std::invalid_argument("absolute_tolerance must be greater than 0.0.");
134 }
135
136 clear();
137
138 interpolation::rbf_inequality_fitter fitter(model_, points);
139 std::vector<index_t> center_indices;
140 std::tie(center_indices, weights_) =
141 fitter.fit(values, values_lb, values_ub, absolute_tolerance, max_iter);
142
143 fitted_ = true;
144 centers_ = points(center_indices, Eigen::all);
145 centers_bbox_ = geometry::bbox3d::from_points(centers_);
146 }
147
148 void set_evaluation_bbox_impl(const geometry::bbox3d& bbox) {
149 if (!fitted_) {
150 throw std::runtime_error(kNotFittedErrorMessage);
151 }
152
153 auto union_bbox = bbox.convex_hull(centers_bbox_);
154
155 evaluator_ = std::make_unique<interpolation::rbf_evaluator<>>(model_, centers_, union_bbox);
156 evaluator_->set_weights(weights_);
157 }
158
159 const valuesd& weights() const {
160 if (!fitted_) {
161 throw std::runtime_error(kNotFittedErrorMessage);
162 }
163
164 return weights_;
165 }
166
167 private:
168 void clear() {
169 fitted_ = false;
170 centers_ = geometry::points3d();
171 centers_bbox_ = geometry::bbox3d();
172 weights_ = valuesd();
173 }
174
175 static constexpr const char* kNotFittedErrorMessage = "The interpolant is not fitted yet.";
176
177 const model model_;
178
179 bool fitted_{};
180 geometry::points3d centers_;
181 geometry::bbox3d centers_bbox_;
182 valuesd weights_;
183
184 std::unique_ptr<interpolation::rbf_evaluator<>> evaluator_;
185 };
186} // namespace rsmesh
187
188#endif //RSMESH_INTERPOLANT_H
bbox3d convex_hull(const bbox3d &other) const
Definition bbox3d.cpp:60
描述了一个插值模型
Definition model.h:21
vectors3d points3d
3维点的集合
Definition point3d.h:48
本系统的主命名空间,包含了common, examples, fmm, geometry, numeric, point_cloud等子命名空间