RSMesh 1.0.0
一个曲面重构的系统,输入为点云,输出为obj,stl等主流格式的网格文件,使用的方法为径向基函数插值,采取了并行优化、Intel-MKL等优化措施,支持百万级别的点云
载入中...
搜索中...
未找到
domain_divider.cpp
1//
2// Created by RainSure on 2024/2/18.
3//
4
5#include "preconditioner/domain_divider.h"
6#include "Eigen/Core"
7#include "common/zip_sort.h"
8#include <algorithm>
9#include <iterator>
10#include <numeric>
11#include <random>
12
13namespace rsmesh::preconditioner {
14 struct mixed_point {
15 index_t index{};
16 bool inner{};
17 bool grad{};
18 };
19
20 domain_divider::domain_divider(const geometry::points3d& points,
21 const geometry::points3d& grad_points,
22 const std::vector<index_t>& point_indices,
23 const std::vector<index_t>& grad_point_indices,
24 const std::vector<index_t>& poly_point_indices)
25 : points_(points),
26 grad_points_(grad_points),
27 mixed_size_of_root_(static_cast<index_t>(point_indices.size() + grad_point_indices.size())),
28 poly_point_idcs_(poly_point_indices) {
29 domain root;
30
31 root.point_indices = point_indices;
32 root.grad_point_indices = grad_point_indices;
33
34 root.inner_point = std::vector<bool>(point_indices.size(), true);
35 root.inner_grad_point = std::vector<bool>(grad_point_indices.size(), true);
36
37 root.bbox_ = domain_bbox(root);
38 longest_side_length_of_root_ = root.bbox_.size().maxCoeff();
39
40 domains_.push_back(std::move(root));
41
42 divide_domains();
43 }
44
45 std::pair<std::vector<index_t>, std::vector<index_t>> domain_divider::choose_coarse_points(
46 double ratio) const {
47 std::vector<index_t> idcs(poly_point_idcs_);
48 std::vector<index_t> grad_idcs;
49
50 std::random_device rd;
51 std::mt19937 gen(rd());
52
53 auto n_poly_points = static_cast<index_t>(poly_point_idcs_.size());
54 for (const auto& d : domains_) {
55 std::vector<mixed_point> mixed_points;
56 for (index_t i = n_poly_points; i < d.size(); i++) {
57 mixed_points.emplace_back(d.point_indices.at(i), d.inner_point.at(i), false);
58 }
59 for (index_t i = 0; i < d.grad_size(); i++) {
60 mixed_points.emplace_back(d.grad_point_indices.at(i), d.inner_grad_point.at(i), true);
61 }
62
63 std::shuffle(mixed_points.begin(), mixed_points.end(), gen);
64
65 auto n_inner_pts = std::count(d.inner_point.begin(), d.inner_point.end(), true) +
66 std::count(d.inner_grad_point.begin(), d.inner_grad_point.end(), true);
67 auto n_coarse = std::max(
68 index_t{1},
69 static_cast<index_t>(round_half_to_even(ratio * static_cast<double>(n_inner_pts))));
70
71 auto count = index_t{0};
72 for (const auto& p : mixed_points) {
73 if (count == n_coarse) {
74 break;
75 }
76
77 if (p.inner) {
78 (p.grad ? grad_idcs : idcs).push_back(p.index);
79 count++;
80 }
81 }
82 }
83
84 return {std::move(idcs), std::move(grad_idcs)};
85 }
86
87 const std::list<domain>& domain_divider::domains() const { return domains_; }
88
89 std::list<domain>&& domain_divider::into_domains() { return std::move(domains_); }
90
91 void domain_divider::divide_domain(std::list<domain>::iterator it) {
92 auto& d = *it;
93
94 std::vector<mixed_point> mixed_points;
95 for (index_t i = 0; i < d.size(); i++) {
96 mixed_points.emplace_back(d.point_indices.at(i), d.inner_point.at(i), false);
97 }
98 for (index_t i = 0; i < d.grad_size(); i++) {
99 mixed_points.emplace_back(d.grad_point_indices.at(i), d.inner_grad_point.at(i), true);
100 }
101
102 auto split_axis = index_t{0};
103 auto longest_side_length = d.bbox_.size().maxCoeff(&split_axis);
104
105 // TODO(mizuno): Sort all points along each axis and cache the result as a permutation.
106 std::sort(mixed_points.begin(), mixed_points.end(),
107 [this, split_axis](const auto& a, const auto& b) {
108 return (a.grad ? grad_points_ : points_)(a.index, split_axis) <
109 (b.grad ? grad_points_ : points_)(b.index, split_axis);
110 });
111
112 auto q =
113 longest_side_length_of_root_ / longest_side_length *
114 std::sqrt(static_cast<double>(max_leaf_size) / static_cast<double>(mixed_size_of_root_)) *
115 overlap_quota;
116 q = std::min(0.5, q);
117
118 auto n_pts = d.mixed_size();
119 auto n_overlap_pts = static_cast<index_t>(round_half_to_even(q * static_cast<double>(n_pts)));
120 auto n_subdomain_pts =
121 static_cast<index_t>(std::ceil(static_cast<double>(n_pts + n_overlap_pts) / 2.0));
122 auto left_partition = n_pts - n_subdomain_pts;
123 auto right_partition = n_subdomain_pts;
124 auto mid = static_cast<index_t>(
125 round_half_to_even(static_cast<double>(left_partition + right_partition) / 2.0));
126
127 domain left;
128 domain right;
129
130 for (index_t i = 0; i < right_partition; i++) {
131 const auto& p = mixed_points.at(i);
132 auto inner = p.inner && i < mid;
133
134 if (p.grad) {
135 left.grad_point_indices.push_back(p.index);
136 left.inner_grad_point.push_back(inner);
137 } else {
138 left.point_indices.push_back(p.index);
139 left.inner_point.push_back(inner);
140 }
141 }
142
143 for (index_t i = left_partition; i < n_pts; i++) {
144 const auto& p = mixed_points.at(i);
145 auto inner = p.inner && i >= mid;
146
147 if (p.grad) {
148 right.grad_point_indices.push_back(p.index);
149 right.inner_grad_point.push_back(inner);
150 } else {
151 right.point_indices.push_back(p.index);
152 right.inner_point.push_back(inner);
153 }
154 }
155
156 left.bbox_ = domain_bbox(left);
157 right.bbox_ = domain_bbox(right);
158
159 domains_.push_back(std::move(left));
160 domains_.push_back(std::move(right));
161 }
162
163 void domain_divider::divide_domains() {
164 auto it = domains_.begin();
165
166 while (it != domains_.end()) {
167 auto& d = *it;
168 if (d.mixed_size() <= max_leaf_size) {
169 ++it;
170 continue;
171 }
172
173 divide_domain(it);
174
175 it = domains_.erase(it);
176 }
177
178 for (auto& d : domains_) {
179 d.merge_poly_points(poly_point_idcs_);
180 }
181 }
182
183 geometry::bbox3d domain_divider::domain_bbox(const domain& domain) const {
184 auto points = points_(domain.point_indices, Eigen::all);
185 auto grad_points = grad_points_(domain.grad_point_indices, Eigen::all);
186
187 return geometry::bbox3d::from_points(points).convex_hull(
188 geometry::bbox3d::from_points(grad_points));
189 }
190
191 double domain_divider::round_half_to_even(double d) {
192 return std::ceil((d - 0.5) / 2.0) + std::floor((d + 0.5) / 2.0);
193 }
194}
vectors3d points3d
3维点的集合
Definition point3d.h:48
该命名空间下主要定义了关于krylov子空间方法的预处理相关的类和函数