RSMesh 1.0.0
一个曲面重构的系统,输入为点云,输出为obj,stl等主流格式的网格文件,使用的方法为径向基函数插值,采取了并行优化、Intel-MKL等优化措施,支持百万级别的点云
载入中...
搜索中...
未找到
rmt_node.h
1//
2// Created by RainSure on 2024/2/23.
3//
4
5#ifndef RSMESH_RMT_NODE_H
6#define RSMESH_RMT_NODE_H
7
8#include <array>
9#include <cmath>
10#include <memory>
11#include <unordered_map>
12#include <utility>
13#include <vector>
14#include <optional>
15#include "geometry/point3d.h"
16#include "isosurface/bit.h"
17#include "isosurface/isosurface_types.h"
18#include "common/macros.h"
19
20namespace rsmesh::isosurface {
21
22 // Encodes 0 or 1 on 14 outgoing halfedges for each node.
23 using edge_bitset = std::uint16_t;
24
25 static constexpr edge_bitset EdgeSetMask = 0x3fff;
26
27// Edge index per node: 0 - 13
28 using edge_index = int;
29
30// Adjacent edges (4 or 6) of each edge.
31 inline const std::array<edge_bitset, 14> NeighborMasks{0x321a, 0x2015, 0x24b2, 0x0251, 0x006f,
32 0x00d4, 0x03b8, 0x0d64, 0x0ac0, 0x1949,
33 0x2884, 0x3780, 0x2a01, 0x1c07};
34
35 enum binary_sign { Pos = 0, Neg = 1 };
36
37 class rmt_node {
38 geometry::point3d position_;
39 std::optional<double> value_;
40
41 // The corresponding bit is set if an edge crosses the isosurface
42 // at a point nearer than the midpoint.
43 // Such intersections are called "near intersections".
44 edge_bitset intersections_{};
45
46 // The corresponding bit is set if an edge crosses the isosurface.
47 edge_bitset all_intersections_{};
48
49 std::unique_ptr<std::vector<vertex_index>> vis_;
50
51 std::unique_ptr<std::array<rmt_node*, 14>> neighbors_;
52
53 static std::vector<edge_bitset> connected_components(edge_bitset edge_set) {
54 std::vector<edge_bitset> components;
55 while (edge_set != 0) {
56 edge_bitset component{};
57 edge_bitset queue = 1 << bit_peek(edge_set);
58 while (queue != 0) {
59 auto e = bit_pop(&queue);
60 component |= 1 << e;
61 edge_set ^= 1 << e;
62 queue |= NeighborMasks.at(e) & edge_set;
63 }
64 components.push_back(component);
65 }
66 return components;
67 }
68
69 public:
70 explicit rmt_node(const geometry::point3d& position) : position_(position) {}
71
72 void cluster(std::vector<geometry::point3d>& vertices,
73 std::unordered_map<vertex_index, vertex_index>& cluster_map) const {
74 auto surfaces = connected_components(intersections_);
75 for (auto surface : surfaces) {
76 auto holes = connected_components(surface ^ EdgeSetMask);
77 if (holes.size() != 1) {
78 // holes.size() == 0 -> closed surface
79 // holes.size() >= 2 -> holes in the surface
80 continue;
81 }
82
83 auto n = bit_count(surface);
84 auto new_vi = static_cast<vertex_index>(vertices.size());
85
86 geometry::point3d clustered = geometry::point3d::Zero();
87 while (surface != 0) {
88 auto edge_idx = bit_pop(&surface);
89 auto vi = vertex_on_edge(edge_idx);
90 clustered += vertices.at(vi);
91 cluster_map.emplace(vi, new_vi);
92 }
93 clustered /= static_cast<double>(n);
94
95 vertices.push_back(clustered);
96 }
97 }
98
99 bool has_intersection(edge_index edge_idx) const {
100 edge_bitset edge_bit = 1 << edge_idx;
101 return (intersections_ & edge_bit) != 0;
102 }
103
104 bool has_neighbor(edge_index edge) const { return neighbors_->at(edge) != nullptr; }
105
106 void insert_vertex(vertex_index vi, edge_index edge_idx) {
107 RSMESH_ASSERT(!has_intersection(edge_idx));
108
109 if (!vis_) {
110 vis_ = std::make_unique<std::vector<vertex_index>>();
111 }
112
113 edge_bitset edge_bit = 1 << edge_idx;
114 edge_bitset edge_count_mask = edge_bit - 1;
115
116 intersections_ |= edge_bit;
117
118 auto it = vis_->begin() + bit_count(static_cast<edge_bitset>(intersections_ & edge_count_mask));
119 vis_->insert(it, vi);
120
121 RSMESH_ASSERT(vertex_on_edge(edge_idx) == vi);
122 }
123
124 bool is_free() const { return all_intersections_ == 0; }
125
126 rmt_node& neighbor(edge_index edge) {
127 RSMESH_ASSERT(has_neighbor(edge));
128 return *neighbors_->at(edge);
129 }
130
131 const rmt_node& neighbor(edge_index edge) const {
132 RSMESH_ASSERT(has_neighbor(edge));
133 return *neighbors_->at(edge);
134 }
135
136 const geometry::point3d& position() const { return position_; }
137
138 void set_intersection(edge_index edge_idx) {
139 edge_bitset edge_bit = 1 << edge_idx;
140
141 all_intersections_ |= edge_bit;
142 }
143
144 void set_neighbors(std::unique_ptr<std::array<rmt_node*, 14>> neighbors) {
145 neighbors_.swap(neighbors);
146 }
147
148 void set_value(double value) {
149 RSMESH_ASSERT(!value_.has_value());
150 value_ = value;
151 }
152
153 double value() const {
154 RSMESH_ASSERT(value_.has_value());
155 return *value_;
156 }
157
158 binary_sign value_sign() const { return value() < 0 ? Neg : Pos; }
159
160 vertex_index vertex_on_edge(edge_index edge_idx) const {
161 RSMESH_ASSERT(has_intersection(edge_idx));
162
163 edge_bitset edge_bit = 1 << edge_idx;
164 edge_bitset edge_count_mask = edge_bit - 1;
165 return vis_->at(bit_count(static_cast<edge_bitset>(intersections_ & edge_count_mask)));
166 }
167 };
168}
169
170#endif //RSMESH_RMT_NODE_H
vector3d point3d
3维点
Definition point3d.h:39
该命名空间下主要定义了等值面提取相关的类和函数