11
11
12
12
#include < algorithm>
13
13
#include < array>
14
+ #include < boost/unordered/concurrent_flat_map.hpp>
15
+ #include < boost/unordered/concurrent_flat_set.hpp>
14
16
#include < boost/variant/get.hpp>
17
+ #include < functional>
15
18
#include < iterator>
16
- #include < unordered_map>
17
- #include < unordered_set>
18
19
#include < utility>
19
20
#include < vector>
20
21
@@ -27,6 +28,17 @@ class Find_defects {
27
28
using Triangle_soup = Triangle_soup<K, FaceData>;
28
29
using Leaf = typename Triangle_soup::Leaf;
29
30
31
+ struct Halfedge_hash {
32
+ std::size_t operator ()(const Halfedge& he) const noexcept {
33
+ std::size_t seed{};
34
+ boost::hash_combine (seed, he[0 ].idx ());
35
+ boost::hash_combine (seed, he[1 ].idx ());
36
+ return seed;
37
+ }
38
+ };
39
+
40
+ using Halfedge_count = boost::unordered_flat_map<Halfedge, std::size_t , Halfedge_hash>;
41
+
30
42
public:
31
43
explicit Find_defects (const Triangle_soup& m)
32
44
: m_{merge_duplicate_vertices (m)},
@@ -153,7 +165,8 @@ class Find_defects {
153
165
continue ;
154
166
}
155
167
156
- std::unordered_map<Vertex_index, std::size_t > local_vis;
168
+ boost::unordered_flat_map<Vertex_index, std::size_t , std::hash<kigumi::Vertex_index>>
169
+ local_vis;
157
170
for (auto v_fi : v_fis) {
158
171
local_vis.emplace (next_vertex (v_fi, vi), local_vis.size ());
159
172
local_vis.emplace (prev_vertex (v_fi, vi), local_vis.size ());
@@ -180,73 +193,58 @@ class Find_defects {
180
193
181
194
static Halfedge opposite (const Halfedge& he) { return {he[1 ], he[0 ]}; }
182
195
183
- static std::unordered_multiset<Halfedge> collect_halfedges (const Triangle_soup& m) {
184
- std::unordered_multiset<Halfedge> hes;
196
+ static Halfedge_count collect_halfedges (const Triangle_soup& m) {
197
+ Halfedge_count hes;
185
198
for (auto fi : m.faces ()) {
186
199
const auto & f = m.face (fi);
187
200
if (f[0 ] == f[1 ] || f[1 ] == f[2 ] || f[2 ] == f[0 ]) {
188
201
continue ;
189
202
}
190
203
for (std::size_t i = 0 ; i < 3 ; ++i) {
191
204
auto he = Halfedge{f.at (i), f.at ((i + 1 ) % 3 )};
192
- hes. insert (he) ;
205
+ ++ hes[he] ;
193
206
}
194
207
}
195
208
return hes;
196
209
}
197
210
198
- static std::vector<Edge> boundary_edges (const std::unordered_multiset<Halfedge> & hes) {
211
+ static std::vector<Edge> boundary_edges (const Halfedge_count & hes) {
199
212
std::vector<Edge> edges;
200
213
201
- Halfedge last_he;
202
- for (const auto & he : hes) {
203
- if (he == last_he) {
204
- continue ;
205
- }
206
- last_he = he;
207
-
208
- if (hes.count (he) == 1 && !hes.contains (opposite (he))) {
214
+ for (const auto & [he, count] : hes) {
215
+ if (count == 1 && !hes.contains (opposite (he))) {
209
216
edges.push_back (to_edge (he));
210
217
}
211
218
}
212
219
213
220
return edges;
214
221
}
215
222
216
- static std::vector<Edge> inconsistent_edges (const std::unordered_multiset<Halfedge> & hes) {
223
+ static std::vector<Edge> inconsistent_edges (const Halfedge_count & hes) {
217
224
std::vector<Edge> edges;
218
225
219
- Halfedge last_he;
220
- for (const auto & he : hes) {
221
- if (he == last_he) {
222
- continue ;
223
- }
224
- last_he = he;
225
-
226
- if (hes.count (he) == 2 && !hes.contains (opposite (he))) {
226
+ for (const auto & [he, count] : hes) {
227
+ if (count == 2 && !hes.contains (opposite (he))) {
227
228
edges.push_back (to_edge (he));
228
229
}
229
230
}
230
231
231
232
return edges;
232
233
}
233
234
234
- static std::vector<Edge> non_manifold_edges (const std::unordered_multiset<Halfedge> & hes) {
235
+ static std::vector<Edge> non_manifold_edges (const Halfedge_count & hes) {
235
236
std::vector<Edge> edges;
236
237
237
- Halfedge last_he;
238
- for (const auto & he : hes) {
239
- if (he == last_he) {
240
- continue ;
241
- }
242
- last_he = he;
238
+ for (const auto & [he, count] : hes) {
239
+ auto opp_it = hes.find (opposite (he));
240
+ auto opp_count = opp_it == hes.end () ? 0 : opp_it->second ;
243
241
244
- if (he[0 ] > he[1 ] && hes. contains ( opposite (he)) ) {
242
+ if (he[0 ] > he[1 ] && opp_count > 0 ) {
245
243
// Prevent double counting.
246
244
continue ;
247
245
}
248
246
249
- if (hes. count (he) + hes. count ( opposite (he)) > 2 ) {
247
+ if (count + opp_count > 2 ) {
250
248
edges.push_back (to_edge (he));
251
249
}
252
250
}
@@ -298,7 +296,7 @@ class Find_defects {
298
296
const std::vector<Face_index>& non_trivial_degenerate_faces) {
299
297
std::vector<Face_index> fis;
300
298
301
- std::unordered_set <Face_index> degenerate_faces;
299
+ boost::unordered_flat_set<Face_index, std::hash <Face_index> > degenerate_faces;
302
300
degenerate_faces.reserve (trivial_degenerate_faces.size () + non_trivial_degenerate_faces.size ());
303
301
degenerate_faces.insert (trivial_degenerate_faces.begin (), trivial_degenerate_faces.end ());
304
302
degenerate_faces.insert (non_trivial_degenerate_faces.begin (),
@@ -378,7 +376,7 @@ class Find_defects {
378
376
Triangle_soup m_;
379
377
std::vector<Vertex_index> isolated_vertices_;
380
378
std::vector<Vertex_index> non_manifold_vertices_;
381
- std::unordered_multiset<Halfedge> halfedges_;
379
+ Halfedge_count halfedges_;
382
380
std::vector<Edge> boundary_edges_;
383
381
std::vector<Edge> inconsistent_edges_;
384
382
std::vector<Edge> non_manifold_edges_;
0 commit comments