Developer Documentation
Loading...
Searching...
No Matches
TopologyKernel.hh
1#pragma once
2/*===========================================================================*\
3 * *
4 * OpenVolumeMesh *
5 * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
6 * www.openvolumemesh.org *
7 * *
8 *---------------------------------------------------------------------------*
9 * This file is part of OpenVolumeMesh. *
10 * *
11 * OpenVolumeMesh is free software: you can redistribute it and/or modify *
12 * it under the terms of the GNU Lesser General Public License as *
13 * published by the Free Software Foundation, either version 3 of *
14 * the License, or (at your option) any later version with the *
15 * following exceptions: *
16 * *
17 * If other files instantiate templates or use macros *
18 * or inline functions from this file, or you compile this file and *
19 * link it with other files to produce an executable, this file does *
20 * not by itself cause the resulting executable to be covered by the *
21 * GNU Lesser General Public License. This exception does not however *
22 * invalidate any other reasons why the executable file might be *
23 * covered by the GNU Lesser General Public License. *
24 * *
25 * OpenVolumeMesh is distributed in the hope that it will be useful, *
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
28 * GNU Lesser General Public License for more details. *
29 * *
30 * You should have received a copy of the GNU LesserGeneral Public *
31 * License along with OpenVolumeMesh. If not, *
32 * see <http://www.gnu.org/licenses/>. *
33 * *
34\*===========================================================================*/
35
36
37#include <cassert>
38#include <set>
39#include <vector>
40#include <array>
41
42#include <OpenVolumeMesh/Core/HandleIndexing.hh>
43#include <OpenVolumeMesh/Core/BaseEntities.hh>
44#include <OpenVolumeMesh/Core/Handles.hh>
45#include <OpenVolumeMesh/Core/ResourceManager.hh>
46#include <OpenVolumeMesh/Core/Iterators.hh>
47#include <OpenVolumeMesh/Config/Export.hh>
48
49namespace OpenVolumeMesh {
50
51// provide begin() and end() for the iterator pairs provided in TopologyKernel,
52// so we can use range-for, e.g. for(const auto &vh: mesh.vertices()) works.
53template<class I>
54typename std::enable_if<is_ovm_iterator<I>::value, I>::type
55begin(const std::pair<I, I>& iterpair)
56{
57 return iterpair.first;
58}
59
60template<class I>
61typename std::enable_if<is_ovm_iterator<I>::value, I>::type
62end(const std::pair<I, I>& iterpair)
63{
64 return iterpair.second;
65}
66
67
68
69class OVM_EXPORT TopologyKernel : public ResourceManager {
70public:
71
72 TopologyKernel() = default;
73 ~TopologyKernel() override = default;
74
75 TopologyKernel(TopologyKernel const& other) = default;
76 TopologyKernel(TopologyKernel &&other) = delete;
77
78 TopologyKernel& operator=(TopologyKernel const& other) = default;
79 TopologyKernel& operator=(TopologyKernel && other) = delete;
80
81 /*
82 * Defines and constants
83 */
84
85 static const VertexHandle InvalidVertexHandle;
86 static const EdgeHandle InvalidEdgeHandle;
87 static const FaceHandle InvalidFaceHandle;
88 static const CellHandle InvalidCellHandle;
89 static const HalfEdgeHandle InvalidHalfEdgeHandle;
90 static const HalfFaceHandle InvalidHalfFaceHandle;
91
95
96 // Add StatusAttrib to list of friend classes
97 // since it provides a garbage collection
98 // that needs access to some protected methods
99 friend class StatusAttrib;
100
101 //=====================================================================
102 // Iterators
103 //=====================================================================
104
105 friend class VertexOHalfEdgeIter;
106 friend class VertexVertexIter;
107 friend class HalfEdgeHalfFaceIter;
108 friend class VertexFaceIter;
109 friend class VertexCellIter;
110 friend class HalfEdgeCellIter;
111 friend class CellVertexIter;
112 friend class CellCellIter;
113 friend class HalfFaceVertexIter;
114 friend class BoundaryHalfFaceHalfFaceIter;
115 friend class VertexIter;
116 friend class EdgeIter;
117 friend class HalfEdgeIter;
118 friend class FaceIter;
119 friend class HalfFaceIter;
120 friend class CellIter;
121
122 /*
123 * Circulators
124 */
125
126protected:
127
128 template <class Circulator>
129 static Circulator make_end_circulator(const Circulator& _circ)
130 {
131 Circulator end = _circ;
132 if (end.valid()) {
133 end.lap(_circ.max_laps());
134 end.valid(false);
135 }
136 return end;
137 }
138
139public:
140
141 VertexVertexIter vv_iter(VertexHandle _h, int _max_laps = 1) const {
142 return VertexVertexIter(_h, this, _max_laps);
143 }
144
145 std::pair<VertexVertexIter, VertexVertexIter> vertex_vertices(VertexHandle _h, int _max_laps = 1) const {
146 VertexVertexIter begin = vv_iter(_h, _max_laps);
147 return std::make_pair(begin, make_end_circulator(begin));
148 }
149
150 VertexOHalfEdgeIter voh_iter(VertexHandle _h, int _max_laps = 1) const {
151 return VertexOHalfEdgeIter(_h, this, _max_laps);
152 }
153
154 std::pair<VertexOHalfEdgeIter, VertexOHalfEdgeIter> outgoing_halfedges(VertexHandle _h, int _max_laps = 1) const {
155 VertexOHalfEdgeIter begin = voh_iter(_h, _max_laps);
156 return std::make_pair(begin, make_end_circulator(begin));
157 }
158
159 VertexIHalfEdgeIter vih_iter(VertexHandle _h, int _max_laps = 1) const {
160 return VertexIHalfEdgeIter(_h, this, _max_laps);
161 }
162
163 std::pair<VertexIHalfEdgeIter, VertexIHalfEdgeIter> incoming_halfedges(VertexHandle _h, int _max_laps = 1) const {
164 VertexIHalfEdgeIter begin = vih_iter(_h, _max_laps);
165 return std::make_pair(begin, make_end_circulator(begin));
166 }
167
168 VertexEdgeIter ve_iter(VertexHandle _h, int _max_laps = 1) const {
169 return VertexEdgeIter(_h, this, _max_laps);
170 }
171
172 std::pair<VertexEdgeIter, VertexEdgeIter> vertex_edges(VertexHandle _h, int _max_laps = 1) const {
173 VertexEdgeIter begin = ve_iter(_h, _max_laps);
174 return std::make_pair(begin, make_end_circulator(begin));
175 }
176
177 VertexHalfFaceIter vhf_iter(VertexHandle _h, int _max_laps = 1) const {
178 return VertexHalfFaceIter(_h, this, _max_laps);
179 }
180
181 std::pair<VertexHalfFaceIter, VertexHalfFaceIter> vertex_halffaces(VertexHandle _h, int _max_laps = 1) const {
182 VertexHalfFaceIter begin = vhf_iter(_h, _max_laps);
183 return std::make_pair(begin, make_end_circulator(begin));
184 }
185
186 VertexFaceIter vf_iter(VertexHandle _h, int _max_laps = 1) const {
187 return VertexFaceIter(_h, this, _max_laps);
188 }
189
190 std::pair<VertexFaceIter, VertexFaceIter> vertex_faces(VertexHandle _h, int _max_laps = 1) const {
191 VertexFaceIter begin = vf_iter(_h, _max_laps);
192 return std::make_pair(begin, make_end_circulator(begin));
193 }
194
195 VertexCellIter vc_iter(VertexHandle _h, int _max_laps = 1) const {
196 return VertexCellIter(_h, this, _max_laps);
197 }
198
199 std::pair<VertexCellIter, VertexCellIter> vertex_cells(VertexHandle _h, int _max_laps = 1) const {
200 VertexCellIter begin = vc_iter(_h, _max_laps);
201 return std::make_pair(begin, make_end_circulator(begin));
202 }
203
204 HalfEdgeHalfFaceIter hehf_iter(HalfEdgeHandle _h, int _max_laps = 1) const {
205 return HalfEdgeHalfFaceIter(_h, this, _max_laps);
206 }
207
208 std::pair<HalfEdgeHalfFaceIter, HalfEdgeHalfFaceIter> halfedge_halffaces(HalfEdgeHandle _h, int _max_laps = 1) const {
209 HalfEdgeHalfFaceIter begin = hehf_iter(_h, _max_laps);
210 return std::make_pair(begin, make_end_circulator(begin));
211 }
212
213 HalfEdgeFaceIter hef_iter(HalfEdgeHandle _h, int _max_laps = 1) const {
214 return HalfEdgeFaceIter(_h, this, _max_laps);
215 }
216
217 std::pair<HalfEdgeFaceIter, HalfEdgeFaceIter> halfedge_faces(HalfEdgeHandle _h, int _max_laps = 1) const {
218 HalfEdgeFaceIter begin = hef_iter(_h, _max_laps);
219 return std::make_pair(begin, make_end_circulator(begin));
220 }
221
222 HalfEdgeCellIter hec_iter(HalfEdgeHandle _h, int _max_laps = 1) const {
223 return HalfEdgeCellIter(_h, this, _max_laps);
224 }
225
226 std::pair<HalfEdgeCellIter, HalfEdgeCellIter> halfedge_cells(HalfEdgeHandle _h, int _max_laps = 1) const {
227 HalfEdgeCellIter begin = hec_iter(_h, _max_laps);
228 return std::make_pair(begin, make_end_circulator(begin));
229 }
230
231 EdgeHalfFaceIter ehf_iter(EdgeHandle _h, int _max_laps = 1) const {
232 return EdgeHalfFaceIter(_h, this, _max_laps);
233 }
234
235 std::pair<EdgeHalfFaceIter, EdgeHalfFaceIter> edge_halffaces(EdgeHandle _h, int _max_laps = 1) const {
236 EdgeHalfFaceIter begin = ehf_iter(_h, _max_laps);
237 return std::make_pair(begin, make_end_circulator(begin));
238 }
239
240 EdgeFaceIter ef_iter(EdgeHandle _h, int _max_laps = 1) const {
241 return EdgeFaceIter(_h, this, _max_laps);
242 }
243
244 std::pair<EdgeFaceIter, EdgeFaceIter> edge_faces(EdgeHandle _h, int _max_laps = 1) const {
245 EdgeFaceIter begin = ef_iter(_h, _max_laps);
246 return std::make_pair(begin, make_end_circulator(begin));
247 }
248
249 EdgeCellIter ec_iter(EdgeHandle _h, int _max_laps = 1) const {
250 return EdgeCellIter(_h, this, _max_laps);
251 }
252
253 std::pair<EdgeCellIter, EdgeCellIter> edge_cells(EdgeHandle _h, int _max_laps = 1) const {
254 EdgeCellIter begin = ec_iter(_h, _max_laps);
255 return std::make_pair(begin, make_end_circulator(begin));
256 }
257
258 HalfFaceHalfEdgeIter hfhe_iter(HalfFaceHandle _h, int _max_laps = 1) const {
259 return HalfFaceHalfEdgeIter(_h, this, _max_laps);
260 }
261
262 std::pair<HalfFaceHalfEdgeIter, HalfFaceHalfEdgeIter> halfface_halfedges(HalfFaceHandle _h, int _max_laps = 1) const {
263 HalfFaceHalfEdgeIter begin = hfhe_iter(_h, _max_laps);
264 return std::make_pair(begin, make_end_circulator(begin));
265 }
266
267 HalfFaceEdgeIter hfe_iter(HalfFaceHandle _h, int _max_laps = 1) const {
268 return HalfFaceEdgeIter(_h, this, _max_laps);
269 }
270
271 std::pair<HalfFaceEdgeIter, HalfFaceEdgeIter> halfface_edges(HalfFaceHandle _h, int _max_laps = 1) const {
272 HalfFaceEdgeIter begin = hfe_iter(_h, _max_laps);
273 return std::make_pair(begin, make_end_circulator(begin));
274 }
275
276 FaceVertexIter fv_iter(FaceHandle _h, int _max_laps = 1) const {
277 return FaceVertexIter(_h, this, _max_laps);
278 }
279
280 std::pair<FaceVertexIter, FaceVertexIter> face_vertices(FaceHandle _h, int _max_laps = 1) const {
281 FaceVertexIter begin = fv_iter(_h, _max_laps);
282 return std::make_pair(begin, make_end_circulator(begin));
283 }
284
285 FaceHalfEdgeIter fhe_iter(FaceHandle _h, int _max_laps = 1) const {
286 return FaceHalfEdgeIter(_h, this, _max_laps);
287 }
288
289 std::pair<FaceHalfEdgeIter, FaceHalfEdgeIter> face_halfedges(FaceHandle _h, int _max_laps = 1) const {
290 FaceHalfEdgeIter begin = fhe_iter(_h, _max_laps);
291 return std::make_pair(begin, make_end_circulator(begin));
292 }
293
294 FaceEdgeIter fe_iter(FaceHandle _h, int _max_laps = 1) const {
295 return FaceEdgeIter(_h, this, _max_laps);
296 }
297
298 std::pair<FaceEdgeIter, FaceEdgeIter> face_edges(FaceHandle _h, int _max_laps = 1) const {
299 FaceEdgeIter begin = fe_iter(_h, _max_laps);
300 return std::make_pair(begin, make_end_circulator(begin));
301 }
302
303 CellVertexIter cv_iter(CellHandle _h, int _max_laps = 1) const {
304 return CellVertexIter(_h, this, _max_laps);
305 }
306
307 std::pair<CellVertexIter, CellVertexIter> cell_vertices(CellHandle _h, int _max_laps = 1) const {
308 CellVertexIter begin = cv_iter(_h, _max_laps);
309 return std::make_pair(begin, make_end_circulator(begin));
310 }
311
312 CellHalfEdgeIter che_iter(CellHandle _h, int _max_laps = 1) const {
313 return CellHalfEdgeIter(_h, this, _max_laps);
314 }
315
316 std::pair<CellHalfEdgeIter, CellHalfEdgeIter> cell_halfedges(CellHandle _h, int _max_laps = 1) const {
317 CellHalfEdgeIter begin = che_iter(_h, _max_laps);
318 return std::make_pair(begin, make_end_circulator(begin));
319 }
320
321 CellEdgeIter ce_iter(CellHandle _h, int _max_laps = 1) const {
322 return CellEdgeIter(_h, this, _max_laps);
323 }
324
325 std::pair<CellEdgeIter, CellEdgeIter> cell_edges(CellHandle _h, int _max_laps = 1) const {
326 CellEdgeIter begin = ce_iter(_h, _max_laps);
327 return std::make_pair(begin, make_end_circulator(begin));
328 }
329
330 CellHalfFaceIter chf_iter(CellHandle _h, int _max_laps = 1) const {
331 return CellHalfFaceIter(_h, this, _max_laps);
332 }
333
334 std::pair<CellHalfFaceIter, CellHalfFaceIter> cell_halffaces(CellHandle _h, int _max_laps = 1) const {
335 CellHalfFaceIter begin = chf_iter(_h, _max_laps);
336 return std::make_pair(begin, make_end_circulator(begin));
337 }
338
339 CellFaceIter cf_iter(CellHandle _h, int _max_laps = 1) const {
340 return CellFaceIter(_h, this, _max_laps);
341 }
342
343 std::pair<CellFaceIter, CellFaceIter> cell_faces(CellHandle _h, int _max_laps = 1) const {
344 CellFaceIter begin = cf_iter(_h, _max_laps);
345 return std::make_pair(begin, make_end_circulator(begin));
346 }
347
348 CellCellIter cc_iter(CellHandle _h, int _max_laps = 1) const {
349 return CellCellIter(_h, this, _max_laps);
350 }
351
352 std::pair<CellCellIter, CellCellIter> cell_cells(CellHandle _h, int _max_laps = 1) const {
353 CellCellIter begin = cc_iter(_h, _max_laps);
354 return std::make_pair(begin, make_end_circulator(begin));
355 }
356
357 HalfFaceVertexIter hfv_iter(HalfFaceHandle _h, int _max_laps = 1) const {
358 return HalfFaceVertexIter(_h, this, _max_laps);
359 }
360
361 std::pair<HalfFaceVertexIter, HalfFaceVertexIter> halfface_vertices(HalfFaceHandle _h, int _max_laps = 1) const {
362 HalfFaceVertexIter begin = hfv_iter(_h, _max_laps);
363 return std::make_pair(begin, make_end_circulator(begin));
364 }
365
366 BoundaryHalfFaceHalfFaceIter bhfhf_iter(HalfFaceHandle _ref_h, int _max_laps = 1) const {
367 return BoundaryHalfFaceHalfFaceIter(_ref_h, this, _max_laps);
368 }
369
370 std::pair<BoundaryHalfFaceHalfFaceIter, BoundaryHalfFaceHalfFaceIter> boundary_halfface_halffaces(HalfFaceHandle _h, int _max_laps = 1) const {
371 BoundaryHalfFaceHalfFaceIter begin = bhfhf_iter(_h, _max_laps);
372 return std::make_pair(begin, make_end_circulator(begin));
373 }
374
375 /*
376 * Iterators
377 */
378
379 BoundaryVertexIter bv_iter() const {
380 return BoundaryVertexIter(this);
381 }
382
383 BoundaryHalfEdgeIter bhe_iter() const {
384 return BoundaryHalfEdgeIter(this);
385 }
386
387 BoundaryEdgeIter be_iter() const {
388 return BoundaryEdgeIter(this);
389 }
390
391 BoundaryHalfFaceIter bhf_iter() const {
392 return BoundaryHalfFaceIter(this);
393 }
394
395 BoundaryFaceIter bf_iter() const {
396 return BoundaryFaceIter(this);
397 }
398
399 BoundaryCellIter bc_iter() const {
400 return BoundaryCellIter(this);
401 }
402
403 VertexIter v_iter() const {
404 return VertexIter(this);
405 }
406
407 VertexIter vertices_begin() const {
408 return VertexIter(this, VertexHandle(0));
409 }
410
411 VertexIter vertices_end() const {
412 return VertexIter(this, VertexHandle((int)n_vertices()));
413 }
414
415 std::pair<VertexIter, VertexIter> vertices() const {
416 return std::make_pair(vertices_begin(), vertices_end());
417 }
418
419 EdgeIter e_iter() const {
420 return EdgeIter(this);
421 }
422
423 EdgeIter edges_begin() const {
424 return EdgeIter(this, EdgeHandle(0));
425 }
426
427 EdgeIter edges_end() const {
428 return EdgeIter(this, EdgeHandle((int)edges_.size()));
429 }
430
431 std::pair<EdgeIter, EdgeIter> edges() const {
432 return std::make_pair(edges_begin(), edges_end());
433 }
434
435 HalfEdgeIter he_iter() const {
436 return HalfEdgeIter(this);
437 }
438
439 HalfEdgeIter halfedges_begin() const {
440 return HalfEdgeIter(this, HalfEdgeHandle(0));
441 }
442
443 HalfEdgeIter halfedges_end() const {
444 return HalfEdgeIter(this, HalfEdgeHandle((int)edges_.size() * 2));
445 }
446
447 std::pair<HalfEdgeIter, HalfEdgeIter> halfedges() const {
448 return std::make_pair(halfedges_begin(), halfedges_end());
449 }
450
451 FaceIter f_iter() const {
452 return FaceIter(this);
453 }
454
455 FaceIter faces_begin() const {
456 return FaceIter(this, FaceHandle(0));
457 }
458
459 FaceIter faces_end() const {
460 return FaceIter(this, FaceHandle((int)faces_.size()));
461 }
462
463 std::pair<FaceIter, FaceIter> faces() const {
464 return std::make_pair(faces_begin(), faces_end());
465 }
466
467 HalfFaceIter hf_iter() const {
468 return HalfFaceIter(this);
469 }
470
471 HalfFaceIter halffaces_begin() const {
472 return HalfFaceIter(this, HalfFaceHandle(0));
473 }
474
475 HalfFaceIter halffaces_end() const {
476 return HalfFaceIter(this, HalfFaceHandle((int)faces_.size() * 2));
477 }
478
479 std::pair<HalfFaceIter, HalfFaceIter> halffaces() const {
480 return std::make_pair(halffaces_begin(), halffaces_end());
481 }
482
483 CellIter c_iter() const {
484 return CellIter(this);
485 }
486
487 CellIter cells_begin() const {
488 return CellIter(this, CellHandle(0));
489 }
490
491 CellIter cells_end() const {
492 return CellIter(this, CellHandle((int)cells_.size()));
493 }
494
495 std::pair<CellIter, CellIter> cells() const {
496 return std::make_pair(cells_begin(), cells_end());
497 }
498
499 /*
500 * Convenience functions
501 */
502
503 std::array<VertexHandle, 2> halfedge_vertices(HalfEdgeHandle _h) const {
504 return {from_vertex_handle(_h), to_vertex_handle(_h)};
505 }
506
507 std::array<VertexHandle, 2> edge_vertices(EdgeHandle _h) const {
508 return halfedge_vertices(halfedge_handle(_h, 0));
509 }
510
511 std::array<HalfEdgeHandle, 2> edge_halfedges(EdgeHandle _h) const {
512 return {
513 halfedge_handle(_h, 0),
514 halfedge_handle(_h, 1)};
515 }
516
517 std::array<HalfFaceHandle,2> face_halffaces(FaceHandle _h) const {
518 return {
519 halfface_handle(_h, 0),
520 halfface_handle(_h, 1)};
521 }
522
523 std::array<CellHandle, 2> face_cells(FaceHandle _h) const {
524 return {
525 incident_cell(halfface_handle(_h, 0)),
526 incident_cell(halfface_handle(_h, 1))};
527 }
528
529 /*
530 * Virtual functions with implementation
531 */
532
534 size_t n_vertices() const override { return n_vertices_; }
536 size_t n_edges() const override { return edges_.size(); }
538 size_t n_halfedges() const override { return edges_.size() * 2u; }
540 size_t n_faces() const override { return faces_.size(); }
542 size_t n_halffaces() const override { return faces_.size() * 2u; }
544 size_t n_cells() const override { return cells_.size(); }
545
547 size_t n_logical_vertices() const { return n_vertices_ - n_deleted_vertices_; }
549 size_t n_logical_edges() const { return edges_.size() - n_deleted_edges_; }
551 size_t n_logical_halfedges() const { return n_logical_edges() * 2u; }
553 size_t n_logical_faces() const { return faces_.size() - n_deleted_faces_; }
555 size_t n_logical_halffaces() const { return n_logical_faces() * 2u; }
557 size_t n_logical_cells() const { return cells_.size() - n_deleted_cells_; }
558
559 int genus() const {
560
561 int g = (1 - (int)(n_logical_vertices() -
562 n_logical_edges() +
563 n_logical_faces() -
564 n_logical_cells()));
565
566 if(g % 2 == 0) return (g / 2);
567
568 // An error occured
569 // The mesh might not be manifold
570 return -1;
571 }
572
573private:
574
575 // Cache total vertex number
576 size_t n_vertices_ = 0u;
577
578public:
579 void add_n_vertices(size_t n);
580 void reserve_vertices(size_t n);
581 void reserve_edges(size_t n);
582 void reserve_faces(size_t n);
583 void reserve_cells(size_t n);
584
586 virtual VertexHandle add_vertex();
587
588 //=======================================================================
589
591 virtual EdgeHandle add_edge(VertexHandle _fromVertex, VertexHandle _toHandle, bool _allowDuplicates = false);
592
600 virtual FaceHandle add_face(std::vector<HalfEdgeHandle> _halfedges, bool _topologyCheck = false);
601
603 virtual FaceHandle add_face(const std::vector<VertexHandle>& _vertices);
604
612 virtual CellHandle add_cell(std::vector<HalfFaceHandle> _halffaces, bool _topologyCheck = false);
613
615 void set_edge(EdgeHandle _eh, VertexHandle _fromVertex, VertexHandle _toVertex);
616
618 void set_face(FaceHandle _fh, const std::vector<HalfEdgeHandle>& _hes);
619
621 void set_cell(CellHandle _ch, const std::vector<HalfFaceHandle>& _hfs);
622
624 void reorder_incident_halffaces(EdgeHandle _eh);
625
626 /*
627 * Non-virtual functions
628 */
629
631 const Edge& edge(EdgeHandle _edgeHandle) const;
632
634 const Face& face(FaceHandle _faceHandle) const;
635
637 const Cell& cell(CellHandle _cellHandle) const;
638
640 Edge& edge(EdgeHandle _edgeHandle);
641
643 Face& face(FaceHandle _faceHandle);
644
646 Cell& cell(CellHandle _cellHandle);
647
649 Edge halfedge(HalfEdgeHandle _halfEdgeHandle) const;
650
652 Face halfface(HalfFaceHandle _halfFaceHandle) const;
653
655 Edge opposite_halfedge(HalfEdgeHandle _halfEdgeHandle) const;
656
658 Face opposite_halfface(HalfFaceHandle _halfFaceHandle) const;
659
661 HalfEdgeHandle find_halfedge(VertexHandle _vh1, VertexHandle _vh2) const;
662 [[deprecated("please use find_halfedge instead")]]
663 HalfEdgeHandle halfedge (VertexHandle _vh1, VertexHandle _vh2) const; // deprecated, use the one above instead!!!
664
666 HalfEdgeHandle find_halfedge_in_cell(VertexHandle _vh1, VertexHandle _vh2, CellHandle _ch) const;
667
671 HalfFaceHandle find_halfface(const std::vector<VertexHandle>& _vs) const;
672 [[deprecated("please use find_halfface instead")]]
673 HalfFaceHandle halfface (const std::vector<VertexHandle>& _vs) const; // deprecated, use the one above instead!!!
674
678 HalfFaceHandle find_halfface_in_cell(const std::vector<VertexHandle>& _vs, CellHandle _ch) const;
679
683 HalfFaceHandle find_halfface_extensive(const std::vector<VertexHandle>& _vs) const;
684 [[deprecated("please use find_halfface_extensive instead")]]
685 HalfFaceHandle halfface_extensive (const std::vector<VertexHandle>& _vs) const; // deprecated, use the one above instead!!!
686
690 HalfFaceHandle find_halfface(const std::vector<HalfEdgeHandle>& _hes) const;
691 [[deprecated("please use find_halfface instead")]]
692 HalfFaceHandle halfface (const std::vector<HalfEdgeHandle>& _hes) const; // deprecated, use the one above instead!!!
693
695 HalfEdgeHandle next_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const;
696
698 HalfEdgeHandle prev_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const;
699
702 return halfedge(_h).from_vertex();
703 }
704
707 return halfedge(_h).to_vertex();
708 }
709
711 inline size_t valence(VertexHandle _vh) const {
712 assert(is_valid(_vh));
713 assert(has_vertex_bottom_up_incidences());
714
715 return outgoing_hes_per_vertex_[_vh].size();
716 }
717
719 inline size_t valence(EdgeHandle _eh) const {
720 assert(is_valid(_eh));
721 assert(has_edge_bottom_up_incidences());
722
723 return incident_hfs_per_he_[halfedge_handle(_eh, 0)].size();
724 }
725
727 inline size_t valence(FaceHandle _fh) const {
728 assert(is_valid(_fh));
729
730 return face(_fh).halfedges().size();
731 }
732
734 inline size_t valence(CellHandle _ch) const {
735 assert(is_valid(_ch));
736
737 return cell(_ch).halffaces().size();
738 }
739
741 std::vector<VertexHandle> get_halfface_vertices(HalfFaceHandle hfh) const;
743 std::vector<VertexHandle> get_halfface_vertices(HalfFaceHandle hfh, VertexHandle vh) const;
745 std::vector<VertexHandle> get_halfface_vertices(HalfFaceHandle hfh, HalfEdgeHandle heh) const;
746
748 bool is_incident( FaceHandle _fh, EdgeHandle _eh) const;
749
750 //=====================================================================
751 // Delete entities
752 //=====================================================================
753
754public:
755
756 virtual VertexIter delete_vertex(VertexHandle _h);
757
758 virtual EdgeIter delete_edge(EdgeHandle _h);
759
760 virtual FaceIter delete_face(FaceHandle _h);
761
762 virtual CellIter delete_cell(CellHandle _h);
763
764 virtual void collect_garbage();
765
766
767 virtual bool is_deleted(VertexHandle _h) const { return vertex_deleted_[_h]; }
768 virtual bool is_deleted(EdgeHandle _h) const { return edge_deleted_[_h]; }
769 virtual bool is_deleted(HalfEdgeHandle _h) const { return edge_deleted_[_h.edge_handle()]; }
770 virtual bool is_deleted(FaceHandle _h) const { return face_deleted_[_h]; }
771 virtual bool is_deleted(HalfFaceHandle _h) const { return face_deleted_[_h.face_handle()]; }
772 virtual bool is_deleted(CellHandle _h) const { return cell_deleted_[_h]; }
773
774private:
775
776 template <class ContainerT>
777 void get_incident_edges(const ContainerT& _vs, std::set<EdgeHandle>& _es) const;
778
779 template <class ContainerT>
780 void get_incident_faces(const ContainerT& _es, std::set<FaceHandle>& _fs) const;
781
782 template <class ContainerT>
783 void get_incident_cells(const ContainerT& _fs, std::set<CellHandle>& _cs) const;
784
785 VertexIter delete_vertex_core(VertexHandle _h);
786
787 EdgeIter delete_edge_core(EdgeHandle _h);
788
789 FaceIter delete_face_core(FaceHandle _h);
790
791 CellIter delete_cell_core(CellHandle _h);
792
793public:
794
796 virtual void swap_cell_indices(CellHandle _h1, CellHandle _h2);
797
799 virtual void swap_face_indices(FaceHandle _h1, FaceHandle _h2);
800
802 virtual void swap_edge_indices(EdgeHandle _h1, EdgeHandle _h2);
803
805 virtual void swap_vertex_indices(VertexHandle _h1, VertexHandle _h2);
806
807protected:
808
810 public:
811 explicit EdgeCorrector(const std::vector<int>& _newIndices) :
812 newIndices_(_newIndices) {}
813
814 void operator()(Edge& _edge) {
815 _edge.set_from_vertex(VertexHandle(newIndices_[_edge.from_vertex().uidx()]));
816 _edge.set_to_vertex(VertexHandle(newIndices_[_edge.to_vertex().uidx()]));
817 }
818 private:
819 const std::vector<int>& newIndices_;
820 };
821
823 public:
824 explicit FaceCorrector(const std::vector<int>& _newIndices) :
825 newIndices_(_newIndices) {}
826
827 void operator()(Face& _face) {
828 std::vector<HalfEdgeHandle> hes = _face.halfedges();
829 for(std::vector<HalfEdgeHandle>::iterator he_it = hes.begin(),
830 he_end = hes.end(); he_it != he_end; ++he_it) {
831
832 EdgeHandle eh = edge_handle(*he_it);
833 unsigned char opp = he_it->idx() == halfedge_handle(eh, 1).idx();
834 *he_it = halfedge_handle(EdgeHandle(newIndices_[eh.uidx()]), opp);
835 }
836 _face.set_halfedges(hes);
837 }
838 private:
839 const std::vector<int>& newIndices_;
840 };
841
843 public:
844 explicit CellCorrector(const std::vector<int>& _newIndices) :
845 newIndices_(_newIndices) {}
846
847 void operator()(Cell& _cell) {
848 std::vector<HalfFaceHandle> hfs = _cell.halffaces();
849 for(std::vector<HalfFaceHandle>::iterator hf_it = hfs.begin(),
850 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
851
852 FaceHandle fh = face_handle(*hf_it);
853 unsigned char opp = hf_it->idx() == halfface_handle(fh, 1).idx();
854 *hf_it = halfface_handle(FaceHandle(newIndices_[fh.uidx()]), opp);
855 }
856 _cell.set_halffaces(hfs);
857 }
858 private:
859 const std::vector<int>& newIndices_;
860 };
861
862public:
863
865 virtual void clear(bool _clearProps = true) {
866
867 edges_.clear();
868 faces_.clear();
869 cells_.clear();
870 vertex_deleted_.clear();
871 edge_deleted_.clear();
872 face_deleted_.clear();
873 cell_deleted_.clear();
874 n_deleted_vertices_ = 0;
875 n_deleted_edges_ = 0;
876 n_deleted_faces_ = 0;
877 n_deleted_cells_ = 0;
878 outgoing_hes_per_vertex_.clear();
879 incident_hfs_per_he_.clear();
880 incident_cell_per_hf_.clear();
881 n_vertices_ = 0;
882
883 if(_clearProps) {
884 clear_all_props();
885 } else {
886 // Resize props
887 resize_vprops(0u);
888 resize_eprops(0u);
889 resize_fprops(0u);
890 resize_cprops(0u);
891 }
892 }
893
894 //=====================================================================
895 // Bottom-up Incidences
896 //=====================================================================
897
898public:
899
900 void enable_bottom_up_incidences(bool _enable = true)
901 {
902 enable_vertex_bottom_up_incidences(_enable);
903 enable_edge_bottom_up_incidences(_enable);
904 enable_face_bottom_up_incidences(_enable);
905 }
906
907 void enable_vertex_bottom_up_incidences(bool _enable = true) {
908
909 if(_enable && !v_bottom_up_) {
910 // Vertex bottom-up incidences have to be
911 // recomputed for the whole mesh
912 compute_vertex_bottom_up_incidences();
913 }
914
915 if(!_enable) {
916 outgoing_hes_per_vertex_.clear();
917 }
918
919 v_bottom_up_ = _enable;
920 }
921
922 void enable_edge_bottom_up_incidences(bool _enable = true) {
923
924 if(_enable && !e_bottom_up_) {
925 // Edge bottom-up incidences have to be
926 // recomputed for the whole mesh
927 compute_edge_bottom_up_incidences();
928
929 if(f_bottom_up_) {
930 for (const auto &eh: edges()) {
931 reorder_incident_halffaces(eh);
932 }
933 }
934 }
935
936 if(!_enable) {
937 incident_hfs_per_he_.clear();
938 }
939
940 e_bottom_up_ = _enable;
941 }
942
943 void enable_face_bottom_up_incidences(bool _enable = true) {
944
945 bool updateOrder = false;
946 if(_enable && !f_bottom_up_) {
947 // Face bottom-up incidences have to be
948 // recomputed for the whole mesh
949 compute_face_bottom_up_incidences();
950
951 updateOrder = true;
952 }
953
954 if(!_enable) {
955 incident_cell_per_hf_.clear();
956 }
957
958 f_bottom_up_ = _enable;
959
960 if(updateOrder) {
961 if(e_bottom_up_) {
962 for (const auto &eh: edges()) {
963 reorder_incident_halffaces(eh);
964 }
965 }
966 }
967 }
968
969 bool has_full_bottom_up_incidences() const {
970 return (has_vertex_bottom_up_incidences() &&
971 has_edge_bottom_up_incidences() &&
972 has_face_bottom_up_incidences());
973 }
974
975 bool has_vertex_bottom_up_incidences() const { return v_bottom_up_; }
976
977 bool has_edge_bottom_up_incidences() const { return e_bottom_up_; }
978
979 bool has_face_bottom_up_incidences() const { return f_bottom_up_; }
980
981
982 void enable_deferred_deletion(bool _enable = true);
983 bool deferred_deletion_enabled() const { return deferred_deletion_; }
984
985
986 void enable_fast_deletion(bool _enable = true) { fast_deletion_ = _enable; }
987 bool fast_deletion_enabled() const { return fast_deletion_; }
988
989
990protected:
991
992 void compute_vertex_bottom_up_incidences();
993
994 void compute_edge_bottom_up_incidences();
995
996 void compute_face_bottom_up_incidences();
997
998 // Outgoing halfedges per vertex
999 VertexVector<std::vector<HalfEdgeHandle> > outgoing_hes_per_vertex_;
1000
1001 // Incident halffaces per (directed) halfedge
1002 HalfEdgeVector<std::vector<HalfFaceHandle> > incident_hfs_per_he_;
1003
1004 // Incident cell (at most one) per halfface
1005 HalfFaceVector<CellHandle> incident_cell_per_hf_;
1006
1007private:
1008 bool v_bottom_up_ = true;
1009
1010 bool e_bottom_up_ = true;
1011
1012 bool f_bottom_up_ = true;
1013
1014 bool deferred_deletion_ = true;
1015
1016 bool fast_deletion_ = true;
1017
1018 //=====================================================================
1019 // Connectivity
1020 //=====================================================================
1021
1022public:
1023
1032
1033 // TODO: We might also want a "common halfedge" API that may assume he \in hf once the deprecated function is eliminated for good
1034 HalfFaceHandle adjacent_halfface_in_cell(HalfFaceHandle _halfFaceHandle, HalfEdgeHandle _halfEdgeHandle) const;
1035
1037 CellHandle incident_cell(HalfFaceHandle _halfFaceHandle) const;
1038
1039 bool is_boundary(HalfFaceHandle _halfFaceHandle) const
1040 {
1041 assert(is_valid(_halfFaceHandle));
1042 assert(has_face_bottom_up_incidences());
1043 return incident_cell_per_hf_[_halfFaceHandle] == InvalidCellHandle;
1044 }
1045
1046 bool is_boundary(FaceHandle _faceHandle) const {
1047 assert(is_valid(_faceHandle));
1048 assert(has_face_bottom_up_incidences());
1049 return is_boundary(halfface_handle(_faceHandle, 0)) ||
1050 is_boundary(halfface_handle(_faceHandle, 1));
1051 }
1052
1053 bool is_boundary(EdgeHandle _edgeHandle) const {
1054 assert(is_valid(_edgeHandle));
1055 assert(has_edge_bottom_up_incidences());
1056
1057 for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(halfedge_handle(_edgeHandle, 0));
1058 hehf_it.valid(); ++hehf_it) {
1059 if(is_boundary(face_handle(*hehf_it))) {
1060 return true;
1061 }
1062 }
1063 return false;
1064 }
1065
1066 bool is_boundary(HalfEdgeHandle _halfedgeHandle) const {
1067 assert(is_valid(_halfedgeHandle));
1068 assert(has_edge_bottom_up_incidences());
1069
1070 for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(_halfedgeHandle);
1071 hehf_it.valid(); ++hehf_it) {
1072 if(is_boundary(face_handle(*hehf_it))) {
1073 return true;
1074 }
1075 }
1076 return false;
1077 }
1078
1079 bool is_boundary(VertexHandle _vertexHandle) const {
1080 assert(is_valid(_vertexHandle));
1081 assert(has_vertex_bottom_up_incidences());
1082
1083 for(VertexOHalfEdgeIter voh_it = voh_iter(_vertexHandle); voh_it.valid(); ++voh_it) {
1084 if(is_boundary(*voh_it)) return true;
1085 }
1086 return false;
1087 }
1088
1089 bool is_boundary(CellHandle _cellHandle) const {
1090 assert(is_valid(_cellHandle));
1091
1092 for(CellFaceIter cf_it = cf_iter(_cellHandle); cf_it.valid(); ++cf_it) {
1093 if(is_boundary(*cf_it)) return true;
1094 }
1095 return false;
1096 }
1097
1098 size_t n_vertices_in_cell(CellHandle _ch) const {
1099 assert(is_valid(_ch));
1100
1101 std::set<VertexHandle> vhs;
1102 for(const auto hfh: cell_halffaces(_ch)) {
1103 for(const auto heh: halfface_halfedges(hfh)) {
1104 vhs.insert(to_vertex_handle(heh));
1105 }
1106 }
1107 return vhs.size();
1108 }
1109
1110 //=========================================================================
1111
1112 /*
1113 * Non-virtual functions
1114 */
1115
1116 Edge opposite_halfedge(const Edge& _edge) const {
1117 return Edge(_edge.to_vertex(), _edge.from_vertex());
1118 }
1119
1120 Face opposite_halfface(const Face& _face) const {
1121 std::vector<HalfEdgeHandle> opp_halfedges;
1122 opp_halfedges.resize(_face.halfedges().size());
1123 std::transform(_face.halfedges().rbegin(),
1124 _face.halfedges().rend(),
1125 opp_halfedges.begin(),
1126 opposite_halfedge_handle);
1127 return Face(opp_halfedges);
1128 }
1129
1130 /*
1131 * Static functions
1132 */
1133
1135 static inline HalfEdgeHandle halfedge_handle(EdgeHandle _h, const unsigned char _subIdx) {
1136 // Is handle in range?
1137 assert(_h.is_valid());
1138 assert(_subIdx < 2);
1139 // if(_h.idx() < 0 || _subIdx > 1) return InvalidHalfEdgeHandle;
1140 return HalfEdgeHandle((2 * _h.idx()) + (_subIdx ? 1 : 0));
1141 }
1142
1144 static inline HalfFaceHandle halfface_handle(FaceHandle _h, const unsigned char _subIdx) {
1145 // Is handle in range?
1146 assert(_h.is_valid());
1147 assert(_subIdx < 2);
1148 // if(_h.idx() < 0 || _subIdx > 1) return InvalidHalfFaceHandle;
1149 return HalfFaceHandle((2 * _h.idx()) + (_subIdx ? 1 : 0));
1150 }
1151
1154 assert(_h.is_valid());
1155 return EdgeHandle(_h.idx() / 2);
1156 }
1157
1158 static inline FaceHandle face_handle(HalfFaceHandle _h) {
1159 assert(_h.is_valid());
1160 return FaceHandle(_h.idx() / 2);
1161 }
1162
1163 static inline HalfEdgeHandle opposite_halfedge_handle(HalfEdgeHandle _h) {
1164 assert(_h.is_valid());
1165 return HalfEdgeHandle(_h.idx() ^ 1);
1166 }
1167
1168 static inline HalfFaceHandle opposite_halfface_handle(HalfFaceHandle _h) {
1169 assert(_h.is_valid());
1170 return HalfFaceHandle(_h.idx() ^ 1);
1171 }
1172
1173 bool inline needs_garbage_collection() const {
1174 return n_deleted_vertices_ > 0 || n_deleted_edges_ > 0 || n_deleted_faces_ > 0 || n_deleted_cells_ > 0;
1175 }
1176
1178 template<typename Handle>
1179 bool is_valid(Handle _h) const {
1180 static_assert(is_handle_v<Handle>);
1181 return _h.is_valid() && _h.uidx() < n<typename Handle::EntityTag>();
1182 }
1183
1184private:
1185
1186 // top-down incidences:
1187 EdgeVector<Edge> edges_;
1188 FaceVector<Face> faces_;
1189 CellVector<Cell> cells_;
1190
1191 // deferred deletion:
1192 VertexVector<bool> vertex_deleted_;
1193 EdgeVector<bool> edge_deleted_;
1194 FaceVector<bool> face_deleted_;
1195 CellVector<bool> cell_deleted_;
1196
1197 // number of elements deleted, but not yet garbage collected
1198 size_t n_deleted_vertices_ = 0;
1199 size_t n_deleted_edges_ = 0;
1200 size_t n_deleted_faces_ = 0;
1201 size_t n_deleted_cells_ = 0;
1202};
1203
1204}
1205
MeshT::HalfedgeHandle opposite_halfedge(MeshT &_mesh, typename MeshT::HalfedgeHandle _he)
size_t valence(VertexHandle _vh) const
Get valence of vertex (number of incident edges)
size_t n_logical_halfedges() const
Get number of undeleted halfedges in mesh.
size_t n_halfedges() const override
Get number of halfedges in mesh.
bool is_valid(Handle _h) const
test is_valid and perform index range check
size_t valence(EdgeHandle _eh) const
Get valence of edge (number of incident faces)
static HalfEdgeHandle halfedge_handle(EdgeHandle _h, const unsigned char _subIdx)
Conversion function.
size_t n_logical_halffaces() const
Get number of undeleted halffaces in mesh.
static EdgeHandle edge_handle(HalfEdgeHandle _h)
Handle conversion.
size_t n_vertices() const override
Get number of vertices in mesh.
static HalfFaceHandle halfface_handle(FaceHandle _h, const unsigned char _subIdx)
Conversion function.
size_t n_faces() const override
Get number of faces in mesh.
size_t n_cells() const override
Get number of cells in mesh.
size_t n_logical_edges() const
Get number of undeleted edges in mesh.
size_t valence(CellHandle _ch) const
Get valence of cell (number of incident faces)
virtual void clear(bool _clearProps=true)
Clear whole mesh.
size_t n_edges() const override
Get number of edges in mesh.
VertexHandle from_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge starts from.
size_t n_logical_vertices() const
Get number of undeleted vertices in mesh.
size_t n_logical_faces() const
Get number of undeleted faces in mesh.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.
size_t n_logical_cells() const
Get number of undeleted cells in mesh.
size_t valence(FaceHandle _fh) const
Get valence of face (number of incident edges)
size_t n_halffaces() const override
Get number of halffaces in mesh.
unsigned int uidx() const
return unsigned idx - handle must be valid
Definition Handles.hh:85