Developer Documentation
Loading...
Searching...
No Matches
TopologyKernel.cc
1/*===========================================================================*\
2 * *
3 * OpenVolumeMesh *
4 * Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
5 * www.openvolumemesh.org *
6 * *
7 *---------------------------------------------------------------------------*
8 * This file is part of OpenVolumeMesh. *
9 * *
10 * OpenVolumeMesh is free software: you can redistribute it and/or modify *
11 * it under the terms of the GNU Lesser General Public License as *
12 * published by the Free Software Foundation, either version 3 of *
13 * the License, or (at your option) any later version with the *
14 * following exceptions: *
15 * *
16 * If other files instantiate templates or use macros *
17 * or inline functions from this file, or you compile this file and *
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#ifndef NDEBUG
37#include <iostream>
38#endif
39
40#include <OpenVolumeMesh/Core/TopologyKernel.hh>
41#include <OpenVolumeMesh/Core/detail/swap_bool.hh>
42
43namespace OpenVolumeMesh {
44
45
46// Initialize constants
47const VertexHandle TopologyKernel::InvalidVertexHandle = VertexHandle(-1);
48const EdgeHandle TopologyKernel::InvalidEdgeHandle = EdgeHandle(-1);
49const HalfEdgeHandle TopologyKernel::InvalidHalfEdgeHandle = HalfEdgeHandle(-1);
50const FaceHandle TopologyKernel::InvalidFaceHandle = FaceHandle(-1);
51const HalfFaceHandle TopologyKernel::InvalidHalfFaceHandle = HalfFaceHandle(-1);
52const CellHandle TopologyKernel::InvalidCellHandle = CellHandle(-1);
53
54//========================================================================================
55
56void TopologyKernel::reserve_vertices(size_t n)
57{
58 ResourceManager::reserve_vprops(n);
59 vertex_deleted_.reserve(n);
60}
61
62void TopologyKernel::reserve_edges(size_t n)
63{
64 ResourceManager::reserve_eprops(n);
65 edges_.reserve(n);
66 edge_deleted_.reserve(n);
67}
68
69void TopologyKernel::reserve_faces(size_t n)
70{
71 ResourceManager::reserve_fprops(n);
72 faces_.reserve(n);
73 face_deleted_.reserve(n);
74}
75
76void TopologyKernel::reserve_cells(size_t n)
77{
78 ResourceManager::reserve_cprops(n);
79 cells_.reserve(n);
80 cell_deleted_.reserve(n);
81}
82
83void TopologyKernel::add_n_vertices(size_t n)
84{
85 resize_vprops(n_vertices_ + n);
86 n_vertices_ += n;
87 vertex_deleted_.resize(n_vertices_, false);
88 if(has_vertex_bottom_up_incidences()) {
89 outgoing_hes_per_vertex_.resize(n_vertices_);
90 }
91}
92
94
95 ++n_vertices_;
96 vertex_deleted_.push_back(false);
97
98 // Create item for vertex bottom-up incidences
99 if(has_vertex_bottom_up_incidences()) {
100 outgoing_hes_per_vertex_.resize(n_vertices_);
101 }
102
103 // Resize vertex props
104 resize_vprops(n_vertices_);
105
106 // Return 0-indexed handle
107 return VertexHandle((int)(n_vertices_ - 1));
108}
109
110//========================================================================================
111
114 VertexHandle _toVertex,
115 bool _allowDuplicates) {
116
117 // If the conditions are not fulfilled, assert will fail (instead
118 // of returning an invalid handle)
119 assert(_fromVertex.is_valid() && (size_t)_fromVertex.idx() < n_vertices() && !is_deleted(_fromVertex));
120 assert(_toVertex.is_valid() && (size_t)_toVertex.idx() < n_vertices() && !is_deleted(_toVertex));
121
122 // Test if edge does not exist, yet
123 if(!_allowDuplicates) {
124 if(has_vertex_bottom_up_incidences()) {
125
126 assert((size_t)_fromVertex.idx() < outgoing_hes_per_vertex_.size());
127 std::vector<HalfEdgeHandle>& ohes = outgoing_hes_per_vertex_[_fromVertex];
128 for(std::vector<HalfEdgeHandle>::const_iterator he_it = ohes.begin(),
129 he_end = ohes.end(); he_it != he_end; ++he_it) {
130 if(halfedge(*he_it).to_vertex() == _toVertex) {
131 return edge_handle(*he_it);
132 }
133 }
134 } else {
135 for(int i = 0; i < (int)edges_.size(); ++i) {
136 if(edge(EdgeHandle(i)).from_vertex() == _fromVertex && edge(EdgeHandle(i)).to_vertex() == _toVertex) {
137 return EdgeHandle(i);
138 } else if(edge(EdgeHandle(i)).from_vertex() == _toVertex && edge(EdgeHandle(i)).to_vertex() == _fromVertex) {
139 return EdgeHandle(i);
140 }
141 }
142 }
143 }
144
145 // Store edge
146 edges_.emplace_back(_fromVertex, _toVertex);
147 edge_deleted_.push_back(false);
148
150
151 EdgeHandle eh((int)edges_.size()-1);
152
153 // Update vertex bottom-up incidences
154 if(has_vertex_bottom_up_incidences()) {
155 assert((size_t)_fromVertex.idx() < outgoing_hes_per_vertex_.size());
156 assert((size_t)_toVertex.idx() < outgoing_hes_per_vertex_.size());
157
158 outgoing_hes_per_vertex_[_fromVertex].push_back(halfedge_handle(eh, 0));
159 outgoing_hes_per_vertex_[_toVertex].push_back(halfedge_handle(eh, 1));
160 }
161
162 // Create item for edge bottom-up incidences
163 if(has_edge_bottom_up_incidences()) {
164 incident_hfs_per_he_.resize(n_halfedges());
165 }
166
167 // Get handle of recently created edge
168 return eh;
169}
170
171//========================================================================================
172
174FaceHandle TopologyKernel::add_face(std::vector<HalfEdgeHandle> _halfedges, bool _topologyCheck) {
175
176#ifndef NDEBUG
177 // Assert that halfedges are valid
178 for(std::vector<HalfEdgeHandle>::const_iterator it = _halfedges.begin(),
179 end = _halfedges.end(); it != end; ++it)
180 assert(it->is_valid() && (size_t)it->idx() < edges_.size() * 2u && !is_deleted(*it));
181#endif
182
183 // Perform topology check
184 if(_topologyCheck) {
185 for (size_t i = 0; i + 1< _halfedges.size(); ++i) {
186 if (to_vertex_handle(_halfedges[i]) != from_vertex_handle(_halfedges[i+1])) {
187 return InvalidFaceHandle;
188 }
189 }
190 if (to_vertex_handle(_halfedges.back()) != from_vertex_handle(_halfedges.front())) {
191 return InvalidFaceHandle;
192 }
193 // The halfedges are now guaranteed to be connected
194 }
195
196 // Create face
197 faces_.emplace_back(std::move(_halfedges));
198 face_deleted_.push_back(false);
199
200 // Get added face's handle
201 FaceHandle fh((int)faces_.size() - 1);
202
203 // Resize props
205
206 // Update edge bottom-up incidences
207 if(has_edge_bottom_up_incidences()) {
208
209 for (const auto heh: face_halfedges(fh)) {
210 auto opp = opposite_halfedge_handle(heh);
211
212 assert((size_t)heh.idx() < incident_hfs_per_he_.size());
213 assert((size_t)opp.idx() < incident_hfs_per_he_.size());
214
215 incident_hfs_per_he_[heh].push_back(halfface_handle(fh, 0));
216 incident_hfs_per_he_[opp].push_back(halfface_handle(fh, 1));
217 }
218 }
219
220 // Create item for face bottom-up incidences
221 if(has_face_bottom_up_incidences()) {
222 incident_cell_per_hf_.resize(n_halffaces(), InvalidCellHandle);
223 }
224
225 // Return handle of recently created face
226 return fh;
227}
228
229//========================================================================================
230
231// TODO: add iterator-based interface + range adapter
232
235FaceHandle TopologyKernel::add_face(const std::vector<VertexHandle>& _vertices) {
236
237#ifndef NDEBUG
238 // Assert that all vertices have valid indices
239 for(std::vector<VertexHandle>::const_iterator it = _vertices.begin(),
240 end = _vertices.end(); it != end; ++it)
241 assert(it->is_valid() && (size_t)it->idx() < n_vertices() && !is_deleted(*it));
242#endif
243
244 // Add edge for each pair of vertices
245 std::vector<HalfEdgeHandle> halfedges;
246 std::vector<VertexHandle>::const_iterator it = _vertices.begin();
247 std::vector<VertexHandle>::const_iterator end = _vertices.end();
248 for(; (it+1) != end; ++it) {
249 EdgeHandle e_idx = add_edge(*it, *(it+1));
250
251 // Swap halfedge if edge already existed and
252 // has been initially defined in reverse orientation
253 char swap = edge(e_idx).to_vertex() == *it;
254
255 halfedges.push_back(halfedge_handle(e_idx, swap));
256 }
257 EdgeHandle e_idx = add_edge(*it, *_vertices.begin());
258 char swap = edge(e_idx).to_vertex() == *it;
259 halfedges.push_back(halfedge_handle(e_idx, swap));
260
261 // Add face
262#ifndef NDEBUG
263 return add_face(halfedges, true);
264#else
265 return add_face(halfedges, false);
266#endif
267}
268
269//========================================================================================
270
272
273 /* Put halffaces in clockwise order via the
274 * same cell property which now exists.
275 * Note, this only works for manifold configurations though.
276 * Proceed as follows: Pick one starting halfface. Assuming
277 * that all halfface normals point into the incident cell,
278 * we find the adjacent halfface within the incident cell
279 * along the considered halfedge. We set the found halfface
280 * to be the one to be processed next. If we reach an outside
281 * region, we try to go back from the starting halfface in reverse
282 * order. If the complex is properly connected (the pairwise
283 * intersection of two adjacent 3-dimensional cells is always
284 * a 2-dimensional entity, namely a facet), such an ordering
285 * always exists and will be found. If not, a correct order
286 * can not be given and, as a result, the related iterators
287 * will address the related entities in an arbitrary fashion.
288 */
289
290 HalfEdgeHandle heh = halfedge_handle(_eh, 0);
291 assert((size_t)heh.idx() < incident_hfs_per_he_.size());
292 auto &incident_hfs = incident_hfs_per_he_[heh];
293
294 const size_t n_hfs = incident_hfs.size();
295
296 if(n_hfs < 2)
297 return;
298
299 std::vector<HalfFaceHandle> new_halffaces;
300 new_halffaces.reserve(n_hfs);
301
302 // Start with one incident halfface and go into the first direction
303 auto start_hf = incident_hfs.front();
304 auto cur_hf = start_hf;
305 auto cur_heh = heh;
306
307 do {
308 new_halffaces.push_back(cur_hf);
309 if (new_halffaces.size() > incident_hfs.size()) {
310 //std::cerr << "reorder_incident_halffaces(" << _eh.idx() << "): weird topology, aborting." << std::endl;
311 return;
312 };
313
314 if (incident_cell(cur_hf) == InvalidCellHandle
315 || is_deleted(incident_cell(cur_hf)))
316 break;
317
318 cur_hf = adjacent_halfface_in_cell(cur_hf, cur_heh);
319 if(cur_hf == InvalidHalfFaceHandle) {
320 return;
321 }
322 cur_hf = opposite_halfface_handle(cur_hf);
323
324 } while (cur_hf != start_hf);
325
326 // First direction has terminated
327 // If new_halffaces has the same size as old (unordered)
328 // vector of incident halffaces, we are done here
329 // If not, try the other way round
330 // (this must be a boundary edge)
331 if(new_halffaces.size() != incident_hfs.size()) {
332
333 cur_hf = start_hf;
334 cur_heh = opposite_halfedge_handle(heh);
335
336 while(true) {
337 cur_hf = opposite_halfface_handle(cur_hf);
338
339 if (incident_cell(cur_hf) == InvalidCellHandle
340 || is_deleted(incident_cell(cur_hf))) {
341 // reached the other boundary
342 break;
343 }
344
345 cur_hf = adjacent_halfface_in_cell(cur_hf, cur_heh);
346 if (cur_hf == InvalidHalfFaceHandle) {
347 return;
348 }
349
350 // TODO PERF: just move everything we already have to the end *once* and fill backwards
351 new_halffaces.insert(new_halffaces.begin(), cur_hf);
352 if(new_halffaces.size() > incident_hfs.size()) {
353 //std::cerr << "reorder_incident_halffaces(" << _eh.idx() << ") #2: weird topology, aborting" << std::endl;
354 return;
355 }
356 }
357 }
358
359 // Everything worked just fine, set the new ordered vector
360 if(new_halffaces.size() == incident_hfs.size()) {
361 incident_hfs = std::move(new_halffaces);
362 // update incident halffaces of the opposite halfedge:
363 std::transform(incident_hfs.rbegin(), incident_hfs.rend(),
364 incident_hfs_per_he_[opposite_halfedge_handle(heh)].begin(),
365 opposite_halfface_handle);
366 }
367#if 0
368 else {
369 std::cerr << "reorder_incident_halffaces: found " << new_halffaces.size() << " of " << incident_hfs.size()
370 << " incident halffaces, likely the edge has more than one boundary! Currently not supported, not reordering." << std::endl;
371 // TODO FIXME: we should support this case.
372 }
373#endif
374
375}//========================================================================================
376
378CellHandle TopologyKernel::add_cell(std::vector<HalfFaceHandle> _halffaces, bool _topologyCheck) {
379
380#ifndef NDEBUG
381 // Assert that halffaces have valid indices
382 for(std::vector<HalfFaceHandle>::const_iterator it = _halffaces.begin(),
383 end = _halffaces.end(); it != end; ++it)
384 assert(it->is_valid() && ((size_t)it->idx() < faces_.size() * 2u) && !is_deleted(*it));
385#endif
386
387
388 if(_topologyCheck) {
389
390 /*
391 * We test the following necessary properties for a closed 2-manifold cell:
392 * - each halfedge may only be used once (this implies a halfface may only be used once)
393 * - if a halfedge is used, its opposite halfface must be used too
394 */
395
396 // collect a vector of all used halfedges
397 std::vector<HalfEdgeHandle> incidentHalfedges;
398 size_t guess_n_halfedges = _halffaces.size() * valence(face_handle(_halffaces[0]));
399 // actually, use double the guess, better to allocate a bit more than
400 // risk reallocation.
401 incidentHalfedges.reserve(2 * guess_n_halfedges);
402
403 for (const auto &hfh: _halffaces) {
404 const auto &hes = face(face_handle(hfh)).halfedges();
405 if ((hfh.idx() & 1) == 0) { // first halfface
406 std::copy(hes.begin(), hes.end(),
407 std::back_inserter(incidentHalfedges));
408 } else {
409 std::transform(hes.rbegin(),
410 hes.rend(),
411 std::back_inserter(incidentHalfedges),
412 opposite_halfedge_handle);
413 }
414 }
415 std::sort(incidentHalfedges.begin(), incidentHalfedges.end());
416 auto duplicate = std::adjacent_find(incidentHalfedges.begin(), incidentHalfedges.end());
417 if (duplicate != incidentHalfedges.end()) {
418#ifndef NDEBUG
419 std::cerr << "add_cell(): Halfedge #" << duplicate->idx() << " is contained in more than 1 halfface." << std::endl;
420#endif
421 return InvalidCellHandle;
422 }
423 size_t n_halfedges = incidentHalfedges.size();
424 auto e_end = std::unique(incidentHalfedges.begin(), incidentHalfedges.end(),
425 [](HalfEdgeHandle a, HalfEdgeHandle b) {return a.idx()/2 == b.idx()/2;});
426 auto n_edges = static_cast<size_t>(std::distance(incidentHalfedges.begin(), e_end));
427
428 if(n_halfedges != 2u * n_edges) {
429#ifndef NDEBUG
430 std::cerr << "add_cell(): The specified half-faces are not connected!" << std::endl;
431#endif
432 return InvalidCellHandle;
433 }
434 }
435
436 // Perform topology chec
437 // Create new cell
438 cells_.emplace_back(std::move(_halffaces));
439 cell_deleted_.push_back(false);
440
441 // Resize props
443
444 CellHandle ch((int)cells_.size()-1);
445
446 // Update face bottom-up incidences
447 if(has_face_bottom_up_incidences()) {
448
449 const auto &cell_halffaces = cells_[ch].halffaces();
450 std::set<EdgeHandle> cell_edges;
451 for(const auto &hfh: cell_halffaces) {
452 assert((size_t)hfh.idx() < incident_cell_per_hf_.size());
453
454#ifndef NDEBUG
455 if(_topologyCheck) {
456 if(incident_cell_per_hf_[hfh] != InvalidCellHandle) {
457 // Shouldn't this situation be dealt with before adding the
458 // cell and return InvalidCellHandle in this case?
459 // Mike: Not if the user intends to add non-manifold
460 // configurations. Although, in this case, he should be
461 // warned about it.
462 std::cerr << "add_cell(): One of the specified half-faces is already incident to another cell!" << std::endl;
463 }
464 }
465#endif
466
467 // Overwrite incident cell for current half-face
468 incident_cell_per_hf_[hfh] = ch;
469
470 // Collect all edges of cell
471 for(const auto &eh: face_edges(face_handle(hfh))) {
472 cell_edges.insert(eh);
473 }
474 }
475
476 if(has_edge_bottom_up_incidences()) {
477
478 // Try to reorder all half-faces w.r.t.
479 // their incident half-edges such that all
480 // half-faces are in cyclic order around
481 // a half-edge
482 for (const auto &eh: cell_edges) {
484 }
485 }
486 }
487
488 return ch;
489}
490
491//========================================================================================
492
494// cppcheck-suppress unusedFunction ; public interface
496
497 assert(_fromVertex.is_valid() && (size_t)_fromVertex.idx() < n_vertices() && !is_deleted(_fromVertex));
498 assert(_toVertex.is_valid() && (size_t)_toVertex.idx() < n_vertices() && !is_deleted(_toVertex));
499
500 Edge& e = edge(_eh);
501
502 // Update bottom-up entries
503 if(has_vertex_bottom_up_incidences()) {
504
505 VertexHandle fv = e.from_vertex();
506 VertexHandle tv = e.to_vertex();
507
508 const HalfEdgeHandle heh0 = halfedge_handle(_eh, 0);
509 const HalfEdgeHandle heh1 = halfedge_handle(_eh, 1);
510
511 std::vector<HalfEdgeHandle>::iterator h_end =
512 std::remove(outgoing_hes_per_vertex_[fv].begin(), outgoing_hes_per_vertex_[fv].end(), heh0);
513 outgoing_hes_per_vertex_[fv].resize(h_end - outgoing_hes_per_vertex_[fv].begin());
514
515 h_end = std::remove(outgoing_hes_per_vertex_[tv].begin(), outgoing_hes_per_vertex_[tv].end(), heh1);
516 outgoing_hes_per_vertex_[tv].resize(h_end - outgoing_hes_per_vertex_[tv].begin());
517
518 outgoing_hes_per_vertex_[_fromVertex].push_back(heh0);
519 outgoing_hes_per_vertex_[_toVertex].push_back(heh1);
520 }
521
522 e.set_from_vertex(_fromVertex);
523 e.set_to_vertex(_toVertex);
524}
525
526//========================================================================================
527
529// cppcheck-suppress unusedFunction ; public interface
530void TopologyKernel::set_face(FaceHandle _fh, const std::vector<HalfEdgeHandle>& _hes) {
531
532 Face& f = face(_fh);
533
534 if(has_edge_bottom_up_incidences()) {
535
536 const HalfFaceHandle hf0 = halfface_handle(_fh, 0);
537 const HalfFaceHandle hf1 = halfface_handle(_fh, 1);
538
539 const std::vector<HalfEdgeHandle>& hes = f.halfedges();
540
541 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
542 he_end = hes.end(); he_it != he_end; ++he_it) {
543
544 std::vector<HalfFaceHandle>::iterator h_end =
545 std::remove(incident_hfs_per_he_[*he_it].begin(),
546 incident_hfs_per_he_[*he_it].end(), hf0);
547 incident_hfs_per_he_[*he_it].resize(h_end - incident_hfs_per_he_[*he_it].begin());
548
549 h_end = std::remove(incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin(),
550 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end(), hf1);
551 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].resize(h_end - incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin());
552 }
553
554 for(std::vector<HalfEdgeHandle>::const_iterator he_it = _hes.begin(),
555 he_end = _hes.end(); he_it != he_end; ++he_it) {
556
557 incident_hfs_per_he_[*he_it].push_back(hf0);
558 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].push_back(hf1);
559 }
560
561 // TODO: Reorder incident half-faces
562 }
563
564 f.set_halfedges(_hes);
565}
566
567//========================================================================================
568
570// cppcheck-suppress unusedFunction ; public interface
571void TopologyKernel::set_cell(CellHandle _ch, const std::vector<HalfFaceHandle>& _hfs) {
572
573 Cell& c = cell(_ch);
574
575 if(has_face_bottom_up_incidences()) {
576
577 const std::vector<HalfFaceHandle>& hfs = c.halffaces();
578 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
579 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
580
581 incident_cell_per_hf_[*hf_it] = InvalidCellHandle;
582 }
583
584 for(std::vector<HalfFaceHandle>::const_iterator hf_it = _hfs.begin(),
585 hf_end = _hfs.end(); hf_it != hf_end; ++hf_it) {
586
587 incident_cell_per_hf_[*hf_it] = _ch;
588 }
589 }
590
591 c.set_halffaces(_hfs);
592}
593
594//========================================================================================
595
609
610 assert(!is_deleted(_h));
611
612 std::vector<VertexHandle> vs;
613 vs.push_back(_h);
614
615 std::set<EdgeHandle> incidentEdges_s;
616 get_incident_edges(vs, incidentEdges_s);
617
618 std::set<FaceHandle> incidentFaces_s;
619 get_incident_faces(incidentEdges_s, incidentFaces_s);
620
621 std::set<CellHandle> incidentCells_s;
622 get_incident_cells(incidentFaces_s, incidentCells_s);
623
624 // Delete cells
625 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
626 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
627 delete_cell_core(*c_it);
628 }
629
630 // Delete faces
631 for(std::set<FaceHandle>::const_reverse_iterator f_it = incidentFaces_s.rbegin(),
632 f_end = incidentFaces_s.rend(); f_it != f_end; ++f_it) {
633 delete_face_core(*f_it);
634 }
635
636 // Delete edges
637 for(std::set<EdgeHandle>::const_reverse_iterator e_it = incidentEdges_s.rbegin(),
638 e_end = incidentEdges_s.rend(); e_it != e_end; ++e_it) {
639 delete_edge_core(*e_it);
640 }
641
642 // Delete vertex
643 return delete_vertex_core(_h);
644}
645
646//========================================================================================
647
661
662 assert(!is_deleted(_h));
663
664 std::vector<EdgeHandle> es;
665 es.push_back(_h);
666
667 std::set<FaceHandle> incidentFaces_s;
668 get_incident_faces(es, incidentFaces_s);
669
670 std::set<CellHandle> incidentCells_s;
671 get_incident_cells(incidentFaces_s, incidentCells_s);
672
673 // Delete cells
674 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
675 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
676 delete_cell_core(*c_it);
677 }
678
679 // Delete faces
680 for(std::set<FaceHandle>::const_reverse_iterator f_it = incidentFaces_s.rbegin(),
681 f_end = incidentFaces_s.rend(); f_it != f_end; ++f_it) {
682 delete_face_core(*f_it);
683 }
684
685 // Delete edge
686 return delete_edge_core(_h);
687}
688
689//========================================================================================
690
704
705 assert(!is_deleted(_h));
706
707 std::vector<FaceHandle> fs;
708 fs.push_back(_h);
709
710 std::set<CellHandle> incidentCells_s;
711 get_incident_cells(fs, incidentCells_s);
712
713 // Delete cells
714 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
715 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
716 delete_cell_core(*c_it);
717 }
718
719 // Delete face
720 return delete_face_core(_h);
721}
722
723//========================================================================================
724
735
736 assert(!is_deleted(_h));
737 return delete_cell_core(_h);
738}
739
744{
745 if (!deferred_deletion_enabled() || !needs_garbage_collection())
746 return; // nothing todo
747
748 deferred_deletion_ = false;
749
750 for (int i = (int)n_cells(); i > 0; --i) {
751 auto ch = CellHandle(i - 1);
752 if (is_deleted(ch)) {
753 cell_deleted_[ch] = false;
755 }
756 }
757 n_deleted_cells_ = 0;
758
759 for (int i = (int)n_faces(); i > 0; --i) {
760 auto fh = FaceHandle(i - 1);
761 if (is_deleted(fh)) {
762 face_deleted_[fh] = false;
764 }
765 }
766 n_deleted_faces_ = 0;
767
768 for (int i = (int)n_edges(); i > 0; --i) {
769 auto eh = EdgeHandle(i - 1);
770 if (is_deleted(eh)) {
771 edge_deleted_[eh] = false;
773 }
774 }
775 n_deleted_edges_ = 0;
776
777 for (int i = (int)n_vertices(); i > 0; --i) {
778 auto vh = VertexHandle(i - 1);
779 if (is_deleted(vh)) {
780 vertex_deleted_[vh] = false;
782 }
783 }
784 n_deleted_vertices_ = 0;
785
786 deferred_deletion_ = true;
787
788}
789
790//========================================================================================
791
792template <class ContainerT>
793void TopologyKernel::get_incident_edges(const ContainerT& _vs,
794 std::set<EdgeHandle>& _es) const {
795
796 _es.clear();
797
798 if(has_vertex_bottom_up_incidences()) {
799
800 for(typename ContainerT::const_iterator v_it = _vs.begin(),
801 v_end = _vs.end(); v_it != v_end; ++v_it) {
802
803 const std::vector<HalfEdgeHandle>& inc_hes = outgoing_hes_per_vertex_[*v_it];
804
805 for(std::vector<HalfEdgeHandle>::const_iterator he_it = inc_hes.begin(),
806 he_end = inc_hes.end(); he_it != he_end; ++he_it) {
807
808 _es.insert(edge_handle(*he_it));
809 }
810 }
811 } else {
812
813 for(typename ContainerT::const_iterator v_it = _vs.begin(),
814 v_end = _vs.end(); v_it != v_end; ++v_it) {
815
816 for(EdgeIter e_it = edges_begin(), e_end = edges_end(); e_it != e_end; ++e_it) {
817
818 const Edge& e = edge(*e_it);
819
820 if(e.from_vertex() == *v_it || e.to_vertex() == *v_it) {
821 _es.insert(*e_it);
822 }
823 }
824 }
825 }
826}
827
828//========================================================================================
829
830template <class ContainerT>
831void TopologyKernel::get_incident_faces(const ContainerT& _es,
832 std::set<FaceHandle>& _fs) const {
833
834 _fs.clear();
835
836 if(has_edge_bottom_up_incidences()) {
837
838 for(typename ContainerT::const_iterator e_it = _es.begin(),
839 e_end = _es.end(); e_it != e_end; ++e_it) {
840
841 for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(halfedge_handle(*e_it, 0));
842 hehf_it.valid(); ++hehf_it) {
843
844 const FaceHandle fh = face_handle(*hehf_it);
845
846 _fs.insert(fh);
847 }
848 }
849 } else {
850
851 for(typename ContainerT::const_iterator e_it = _es.begin(),
852 e_end = _es.end(); e_it != e_end; ++e_it) {
853
854 for(FaceIter f_it = faces_begin(),
855 f_end = faces_end(); f_it != f_end; ++f_it) {
856
857 const std::vector<HalfEdgeHandle>& hes = face(*f_it).halfedges();
858
859 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
860 he_end = hes.end(); he_it != he_end; ++he_it) {
861
862 if(edge_handle(*he_it) == *e_it) {
863 _fs.insert(*f_it);
864 break;
865 }
866 }
867 }
868 }
869 }
870}
871
872//========================================================================================
873
874template <class ContainerT>
875void TopologyKernel::get_incident_cells(const ContainerT& _fs,
876 std::set<CellHandle>& _cs) const {
877
878 _cs.clear();
879
880 if(has_face_bottom_up_incidences()) {
881
882 for(typename ContainerT::const_iterator f_it = _fs.begin(),
883 f_end = _fs.end(); f_it != f_end; ++f_it) {
884
885 const HalfFaceHandle hfh0 = halfface_handle(*f_it, 0);
886 const HalfFaceHandle hfh1 = halfface_handle(*f_it, 1);
887
888 const CellHandle c0 = incident_cell(hfh0);
889 const CellHandle c1 = incident_cell(hfh1);
890
891 if(c0.is_valid()) _cs.insert(c0);
892 if(c1.is_valid()) _cs.insert(c1);
893 }
894 } else {
895
896 for(typename ContainerT::const_iterator f_it = _fs.begin(),
897 f_end = _fs.end(); f_it != f_end; ++f_it) {
898
899 for(CellIter c_it = cells_begin(), c_end = cells_end();
900 c_it != c_end; ++c_it) {
901
902 const std::vector<HalfFaceHandle>& hfs = cell(*c_it).halffaces();
903
904 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
905 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
906
907 if(face_handle(*hf_it) == *f_it) {
908 _cs.insert(*c_it);
909 break;
910 }
911 }
912 }
913 }
914 }
915}
916
917//========================================================================================
918
937
938 VertexHandle h = _h;
939 assert(h.is_valid() && (size_t)h.idx() < n_vertices());
940
941 if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last not deleted vertex
942 {
943 VertexHandle last_undeleted_vertex = VertexHandle((int)n_vertices()-1);
944 assert(!vertex_deleted_[last_undeleted_vertex]);
945 swap_vertex_indices(h, last_undeleted_vertex);
946 h = last_undeleted_vertex;
947 }
948
949 if (deferred_deletion_enabled())
950 {
951 ++n_deleted_vertices_;
952 vertex_deleted_[h] = true;
953// deleted_vertices_.push_back(h);
954
955 // Iterator to next element in vertex list
956// return (vertices_begin() + h.idx()+1);
957 return VertexIter(this, VertexHandle(h.idx()+1));
958 }
959 else
960 {
961 // 1)
962 if(has_vertex_bottom_up_incidences()) {
963
964 // Decrease all vertex handles >= _h in all edge definitions
965 for(int i = h.idx(), end = (int)n_vertices(); i < end; ++i) {
966 const std::vector<HalfEdgeHandle>& hes = outgoing_hes_per_vertex_[VertexHandle(i)];
967 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
968 he_end = hes.end(); he_it != he_end; ++he_it) {
969
970 Edge& e = edge(edge_handle(*he_it));
971 if(e.from_vertex().idx() == i) {
972 e.set_from_vertex(VertexHandle(i-1));
973 }
974 if(e.to_vertex().idx() == i) {
975 e.set_to_vertex(VertexHandle(i-1));
976 }
977 }
978 }
979
980 } else {
981
982 // Iterate over all edges
983 for(EdgeIter e_it = edges_begin(), e_end = edges_end();
984 e_it != e_end; ++e_it) {
985
986 // Decrease all vertex handles in edge definitions that are greater than _h
987 if(edge(*e_it).from_vertex() > h) {
988 edge(*e_it).set_from_vertex(VertexHandle(edge(*e_it).from_vertex().idx() - 1));
989 }
990 if(edge(*e_it).to_vertex() > h) {
991 edge(*e_it).set_to_vertex(VertexHandle(edge(*e_it).to_vertex().idx() - 1));
992 }
993 }
994 }
995
996 // 2)
997
998 if(has_vertex_bottom_up_incidences()) {
999 assert((size_t)h.idx() < outgoing_hes_per_vertex_.size());
1000 outgoing_hes_per_vertex_.erase(outgoing_hes_per_vertex_.begin() + h.idx());
1001 }
1002
1003
1004 // 3)
1005
1006 --n_vertices_;
1007 vertex_deleted_.erase(vertex_deleted_.begin() + h.idx());
1008
1009 // 4)
1010
1011 vertex_deleted(h);
1012
1013 // Iterator to next element in vertex list
1014// return (vertices_begin() + h.idx());
1015 return VertexIter(this, h);
1016
1017 }
1018}
1019
1020//========================================================================================
1021
1042
1043 EdgeHandle h = _h;
1044
1045 assert(h.is_valid() && (size_t)h.idx() < edges_.size());
1046
1047 if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last one
1048 {
1049 EdgeHandle last_edge = EdgeHandle((int)edges_.size()-1);
1050 assert(!edge_deleted_[last_edge]);
1051 swap_edge_indices(h, last_edge);
1052 h = last_edge;
1053 }
1054
1055
1056 // 1)
1057 if(has_vertex_bottom_up_incidences()) {
1058
1059 VertexHandle v0 = edge(h).from_vertex();
1060 VertexHandle v1 = edge(h).to_vertex();
1061 assert(v0.is_valid() && (size_t)v0.idx() < outgoing_hes_per_vertex_.size());
1062 assert(v1.is_valid() && (size_t)v1.idx() < outgoing_hes_per_vertex_.size());
1063
1064 outgoing_hes_per_vertex_[v0].erase(
1065 std::remove(outgoing_hes_per_vertex_[v0].begin(),
1066 outgoing_hes_per_vertex_[v0].end(),
1067 halfedge_handle(h, 0)),
1068 outgoing_hes_per_vertex_[v0].end());
1069
1070 outgoing_hes_per_vertex_[v1].erase(
1071 std::remove(outgoing_hes_per_vertex_[v1].begin(),
1072 outgoing_hes_per_vertex_[v1].end(),
1073 halfedge_handle(h, 1)),
1074 outgoing_hes_per_vertex_[v1].end());
1075 }
1076
1077 if (deferred_deletion_enabled())
1078 {
1079 ++n_deleted_edges_;
1080 edge_deleted_[h] = true;
1081// deleted_edges_.push_back(h);
1082
1083 // Return iterator to next element in list
1084// return (edges_begin() + h.idx()+1);
1085 return EdgeIter(this, EdgeHandle(h.idx()+1));
1086 }
1087 else
1088 {
1089
1090 if (!fast_deletion_enabled())
1091 {
1092 // 2)
1093 if(has_edge_bottom_up_incidences()) {
1094
1095 assert((size_t)halfedge_handle(h, 0).idx() < incident_hfs_per_he_.size());
1096
1097 // Decrease all half-edge handles > he and
1098 // delete all half-edge handles == he in face definitions
1099 // Get all faces that need updates
1100 std::set<FaceHandle> update_faces;
1101 for(std::vector<std::vector<HalfFaceHandle> >::const_iterator iit =
1102 (incident_hfs_per_he_.begin() + halfedge_handle(h, 0).idx()),
1103 iit_end = incident_hfs_per_he_.end(); iit != iit_end; ++iit) {
1104 for(std::vector<HalfFaceHandle>::const_iterator it = iit->begin(),
1105 end = iit->end(); it != end; ++it) {
1106 update_faces.insert(face_handle(*it));
1107 }
1108 }
1109 // Update respective handles
1111 for(std::set<FaceHandle>::iterator f_it = update_faces.begin(),
1112 f_end = update_faces.end(); f_it != f_end; ++f_it) {
1113
1114 std::vector<HalfEdgeHandle> hes = face(*f_it).halfedges();
1115
1116 // Delete current half-edge from face's half-edge list
1117 hes.erase(std::remove(hes.begin(), hes.end(), halfedge_handle(h, 0)), hes.end());
1118 hes.erase(std::remove(hes.begin(), hes.end(), halfedge_handle(h, 1)), hes.end());
1119
1120 for (auto &it: hes) {
1121 cor.correctValue(it);
1122 }
1123 face(*f_it).set_halfedges(hes);
1124 }
1125 } else {
1126
1127 // Iterate over all faces
1128 for(FaceIter f_it = faces_begin(), f_end = faces_end();
1129 f_it != f_end; ++f_it) {
1130
1131 // Get face's half-edges
1132 std::vector<HalfEdgeHandle> hes = face(*f_it).halfedges();
1133
1134 // Delete current half-edge from face's half-edge list
1135 hes.erase(std::remove(hes.begin(), hes.end(), halfedge_handle(h, 0)), hes.end());
1136 hes.erase(std::remove(hes.begin(), hes.end(), halfedge_handle(h, 1)), hes.end());
1137
1138 // Decrease all half-edge handles greater than _h in face
1140 for (auto &it: hes) {
1141 cor.correctValue(it);
1142 }
1143 face(*f_it).set_halfedges(hes);
1144 }
1145 }
1146 }
1147
1148 // 3)
1149
1150 if(has_edge_bottom_up_incidences()) {
1151 assert((size_t)halfedge_handle(h, 1).idx() < incident_hfs_per_he_.size());
1152
1153 incident_hfs_per_he_.erase(incident_hfs_per_he_.begin() + halfedge_handle(h, 1).idx());
1154 incident_hfs_per_he_.erase(incident_hfs_per_he_.begin() + halfedge_handle(h, 0).idx());
1155 }
1156
1157 if (!fast_deletion_enabled())
1158 {
1159 // 4)
1160 if(has_vertex_bottom_up_incidences()) {
1162 for (auto &it: outgoing_hes_per_vertex_) {
1163 cor.correctVecValue(it);
1164 }
1165 }
1166 }
1167
1168
1169 // 5)
1170 edges_.erase(edges_.begin() + h.idx());
1171 edge_deleted_.erase(edge_deleted_.begin() + h.idx());
1172
1173
1174 // 6)
1175
1176 edge_deleted(h);
1177
1178 // Return iterator to next element in list
1179// return (edges_begin() + h.idx());
1180 return EdgeIter(this, h);
1181
1182 }
1183}
1184
1185//========================================================================================
1186
1207
1208 FaceHandle h = _h;
1209
1210 assert(h.is_valid() && (size_t)h.idx() < faces_.size());
1211
1212
1213 if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last one
1214 {
1215 FaceHandle last_face = FaceHandle((int)faces_.size()-1);
1216 assert(!face_deleted_[last_face]);
1217 swap_face_indices(h, last_face);
1218 h = last_face;
1219 }
1220
1221 // 1)
1222 if(has_edge_bottom_up_incidences()) {
1223
1224 const std::vector<HalfEdgeHandle>& hes = face(h).halfedges();
1225 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
1226 he_end = hes.end(); he_it != he_end; ++he_it) {
1227
1228 assert((size_t)std::max(he_it->idx(), opposite_halfedge_handle(*he_it).idx()) < incident_hfs_per_he_.size());
1229
1230 incident_hfs_per_he_[*he_it].erase(
1231 std::remove(incident_hfs_per_he_[*he_it].begin(),
1232 incident_hfs_per_he_[*he_it].end(),
1233 halfface_handle(h, 0)), incident_hfs_per_he_[*he_it].end());
1234
1235
1236 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].erase(
1237 std::remove(incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin(),
1238 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end(),
1239 halfface_handle(h, 1)), incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end());
1240
1242 }
1243 }
1244
1245 if (deferred_deletion_enabled())
1246 {
1247 ++n_deleted_faces_;
1248 face_deleted_[h] = true;
1249// deleted_faces_.push_back(h);
1250
1251 // Return iterator to next element in list
1252// return (faces_begin() + h.idx()+1);
1253 return FaceIter(this, FaceHandle(h.idx()+1));
1254 }
1255 else
1256 {
1257
1258 if (!fast_deletion_enabled())
1259 {
1260 // 2)
1261 if(has_face_bottom_up_incidences()) {
1262
1263 // Decrease all half-face handles > _h in all cells
1264 // and delete all half-face handles == _h
1265 std::set<CellHandle> update_cells;
1266 for(std::vector<CellHandle>::const_iterator c_it = (incident_cell_per_hf_.begin() + halfface_handle(h, 0).idx()),
1267 c_end = incident_cell_per_hf_.end(); c_it != c_end; ++c_it) {
1268 if(!c_it->is_valid()) continue;
1269 update_cells.insert(*c_it);
1270 }
1271 for(std::set<CellHandle>::const_iterator c_it = update_cells.begin(),
1272 c_end = update_cells.end(); c_it != c_end; ++c_it) {
1273
1274 std::vector<HalfFaceHandle> hfs = cell(*c_it).halffaces();
1275
1276 // Delete current half-faces from cell's half-face list
1277 hfs.erase(std::remove(hfs.begin(), hfs.end(), halfface_handle(h, 0)), hfs.end());
1278 hfs.erase(std::remove(hfs.begin(), hfs.end(), halfface_handle(h, 1)), hfs.end());
1279
1281 for (auto &it: hfs) {
1282 cor.correctValue(it);
1283 }
1284 cell(*c_it).set_halffaces(hfs);
1285 }
1286
1287 } else {
1288
1289 // Iterate over all cells
1290 for(CellIter c_it = cells_begin(), c_end = cells_end(); c_it != c_end; ++c_it) {
1291
1292 std::vector<HalfFaceHandle> hfs = cell(*c_it).halffaces();
1293
1294 // Delete current half-faces from cell's half-face list
1295 hfs.erase(std::remove(hfs.begin(), hfs.end(), halfface_handle(h, 0)), hfs.end());
1296 hfs.erase(std::remove(hfs.begin(), hfs.end(), halfface_handle(h, 1)), hfs.end());
1297
1299 for (auto &it: hfs) {
1300 cor.correctValue(it);
1301 }
1302 cell(*c_it).set_halffaces(hfs);
1303 }
1304 }
1305 }
1306
1307
1308 // 3)
1309 if(has_face_bottom_up_incidences()) {
1310 assert((size_t)halfface_handle(h, 1).idx() < incident_cell_per_hf_.size());
1311
1312 incident_cell_per_hf_.erase(incident_cell_per_hf_.begin() + halfface_handle(h, 1).idx());
1313 incident_cell_per_hf_.erase(incident_cell_per_hf_.begin() + halfface_handle(h, 0).idx());
1314 }
1315
1316
1317 if (!fast_deletion_enabled())
1318 {
1319 // 4)
1320 if(has_edge_bottom_up_incidences()) {
1322 for (auto &it: incident_hfs_per_he_) {
1323 cor.correctVecValue(it);
1324 }
1325 }
1326 }
1327
1328 // 5)
1329 faces_.erase(faces_.begin() + h.idx());
1330 face_deleted_.erase(face_deleted_.begin() + h.idx());
1331
1332 // 6)
1333 face_deleted(h);
1334
1335 // Return iterator to next element in list
1336// return (faces_begin() + h.idx());
1337 return FaceIter(this, h);
1338 }
1339
1340}
1341
1342//========================================================================================
1343
1360
1361 CellHandle h = _h;
1362
1363 assert(h.is_valid() && (size_t)h.idx() < cells_.size());
1364
1365
1366 if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last not deleted cell
1367 {
1368 CellHandle last_undeleted_cell = CellHandle((int)cells_.size()-1);
1369 assert(!cell_deleted_[last_undeleted_cell]);
1370 swap_cell_indices(h, last_undeleted_cell);
1371 h = last_undeleted_cell;
1372 }
1373
1374
1375 // 1)
1376 if(has_face_bottom_up_incidences()) {
1377 const std::vector<HalfFaceHandle>& hfs = cell(h).halffaces();
1378 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
1379 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
1380 assert((size_t)hf_it->idx() < incident_cell_per_hf_.size());
1381 if (incident_cell_per_hf_[*hf_it] == h)
1382 incident_cell_per_hf_[*hf_it] = InvalidCellHandle;
1383 }
1384 std::set<EdgeHandle> edges;
1385 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
1386 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
1387 const auto& hf = halfface(*hf_it);
1388 for (const auto& heh : hf.halfedges())
1389 edges.insert(edge_handle(heh));
1390 }
1391 for (auto eh : edges)
1393 }
1394
1395 if (deferred_deletion_enabled())
1396 {
1397 ++n_deleted_cells_;
1398 cell_deleted_[h] = true;
1399// deleted_cells_.push_back(h);
1400// deleted_cells_set.insert(h);
1401
1402// return (cells_begin() + h.idx()+1);
1403 return CellIter(this, CellHandle(h.idx()+1));
1404 }
1405 else
1406 {
1407 // 2)
1408 if (!fast_deletion_enabled())
1409 {
1410 if(has_face_bottom_up_incidences()) {
1411 CHandleCorrection cor(h);
1412 for (auto &it: incident_cell_per_hf_) {
1413 cor.correctValue(it);
1414 }
1415 }
1416 }
1417
1418 // 3)
1419 cells_.erase(cells_.begin() + h.idx());
1420 cell_deleted_.erase(cell_deleted_.begin() + h.idx());
1421
1422 // 4)
1423 cell_deleted(h);
1424
1425 // return handle to original position
1426// return (cells_begin() + h.idx()+1);
1427 return CellIter(this, h);
1428 }
1429}
1430
1432{
1433 assert(_h1.idx() >= 0 && _h1.idx() < (int)cells_.size());
1434 assert(_h2.idx() >= 0 && _h2.idx() < (int)cells_.size());
1435
1436 if (_h1 == _h2)
1437 return;
1438
1439 // correct pointers to those cells
1440 for (const auto hfh: cells_[_h1].halffaces()) {
1441 if (incident_cell_per_hf_[hfh] == _h1)
1442 incident_cell_per_hf_[hfh] = _h2;
1443 }
1444 for (const auto hfh: cells_[_h2].halffaces()) {
1445 if (incident_cell_per_hf_[hfh] == _h2)
1446 incident_cell_per_hf_[hfh] = _h1;
1447 }
1448
1449 // swap vector entries
1450 std::swap(cells_[_h1], cells_[_h2]);
1451 detail::swap_bool(cell_deleted_[_h1], cell_deleted_[_h2]);
1452 swap_property_elements(_h1, _h2);
1453}
1454
1456{
1457 assert(_h1.idx() >= 0 && _h1.idx() < (int)faces_.size());
1458 assert(_h2.idx() >= 0 && _h2.idx() < (int)faces_.size());
1459
1460 if (_h1 == _h2)
1461 return;
1462
1463
1464 std::vector<unsigned int> ids;
1465 ids.push_back(_h1.idx());
1466 ids.push_back(_h2.idx());
1467
1468 unsigned int id1 = _h1.idx();
1469 unsigned int id2 = _h2.idx();
1470
1471 // correct pointers to those faces
1472
1473 // correct cells that contain a swapped faces
1474 if (has_face_bottom_up_incidences())
1475 {
1476 std::set<unsigned int> processed_cells; // to ensure ids are only swapped once (in the case that the two swapped faces belong to a common cell)
1477 for (unsigned int i = 0; i < 2; ++i) // For both swapped faces
1478 {
1479 unsigned int id = ids[i];
1480 for (unsigned int j = 0; j < 2; ++j) // for both halffaces
1481 {
1482 HalfFaceHandle hfh = HalfFaceHandle(2*id+j);
1483 CellHandle ch = incident_cell_per_hf_[hfh];
1484 if (!ch.is_valid())
1485 continue;
1486
1487
1488
1489 if (processed_cells.find(ch.idx()) == processed_cells.end())
1490 {
1491
1492 Cell& c = cells_[ch];
1493
1494 // replace old halffaces with new halffaces where the ids are swapped
1495
1496 std::vector<HalfFaceHandle> new_halffaces;
1497 for (unsigned int k = 0; k < c.halffaces().size(); ++k)
1498 if (c.halffaces()[k].idx()/2 == (int)id1) // if halfface belongs to swapped face
1499 new_halffaces.push_back(HalfFaceHandle(2 * id2 + (c.halffaces()[k].idx() % 2)));
1500 else if (c.halffaces()[k].idx()/2 == (int)id2) // if halfface belongs to swapped face
1501 new_halffaces.push_back(HalfFaceHandle(2 * id1 + (c.halffaces()[k].idx() % 2)));
1502 else
1503 new_halffaces.push_back(c.halffaces()[k]);
1504 c.set_halffaces(new_halffaces);
1505
1506 processed_cells.insert(ch.idx());
1507 }
1508 }
1509 }
1510 }
1511 else
1512 {
1513 // serach for all cells that contain a swapped face
1514 for (unsigned int i = 0; i < cells_.size(); ++i)
1515 {
1516 Cell& c = cells_[CellHandle(i)];
1517
1518 // check if c contains a swapped face
1519 bool contains_swapped_face = false;
1520 for (unsigned int k = 0; k < c.halffaces().size(); ++k)
1521 {
1522 if (c.halffaces()[k].idx()/2 == (int)id1)
1523 contains_swapped_face = true;
1524 if (c.halffaces()[k].idx()/2 == (int)id2)
1525 contains_swapped_face = true;
1526 if (contains_swapped_face)
1527 break;
1528 }
1529
1530 if (contains_swapped_face)
1531 {
1532 // replace old halffaces with new halffaces where the ids are swapped
1533 std::vector<HalfFaceHandle> new_halffaces;
1534 for (unsigned int k = 0; k < c.halffaces().size(); ++k)
1535 if (c.halffaces()[k].idx()/2 == (int)id1) // if halfface belongs to swapped face
1536 new_halffaces.push_back(HalfFaceHandle(2 * id2 + (c.halffaces()[k].idx() % 2)));
1537 else if (c.halffaces()[k].idx()/2 == (int)id2) // if halfface belongs to swapped face
1538 new_halffaces.push_back(HalfFaceHandle(2 * id1 + (c.halffaces()[k].idx() % 2)));
1539 else
1540 new_halffaces.push_back(c.halffaces()[k]);
1541 c.set_halffaces(new_halffaces);
1542 }
1543 }
1544 }
1545
1546 // correct bottom up indices
1547
1548 if (has_edge_bottom_up_incidences())
1549 {
1550 std::set<HalfEdgeHandle> processed_halfedges; // to ensure ids are only swapped once (in the case that a halfedge is incident to both swapped faces)
1551 for (unsigned int i = 0; i < 2; ++i) // For both swapped faces
1552 {
1553 unsigned int id = ids[i];
1554 for (unsigned int j = 0; j < 2; ++j) // for both halffaces
1555 {
1556 HalfFaceHandle hfh = HalfFaceHandle(2*id+j);
1557 Face hf = halfface(hfh);
1558
1559 for (unsigned int k = 0; k < hf.halfedges().size(); ++k)
1560 {
1561 HalfEdgeHandle heh = hf.halfedges()[k];
1562
1563 if (processed_halfedges.find(heh) != processed_halfedges.end())
1564 continue;
1565
1566 std::vector<HalfFaceHandle>& incident_halffaces = incident_hfs_per_he_[heh];
1567 for (unsigned int l = 0; l < incident_halffaces.size(); ++l)
1568 {
1569 HalfFaceHandle& hfh2 = incident_halffaces[l];
1570
1571 if (hfh2.idx()/2 == (int)id1) // if halfface belongs to swapped face
1572 hfh2 = HalfFaceHandle(2 * id2 + (hfh2.idx() % 2));
1573 else if (hfh2.idx()/2 == (int)id2) // if halfface belongs to swapped face
1574 hfh2 = HalfFaceHandle(2 * id1 + (hfh2.idx() % 2));
1575 }
1576
1577 processed_halfedges.insert(heh);
1578 }
1579 }
1580 }
1581 }
1582
1583 // swap vector entries
1584 std::swap(faces_[_h1], faces_[_h2]);
1585 detail::swap_bool(face_deleted_[_h1], face_deleted_[_h2]);
1586 std::swap(incident_cell_per_hf_[_h1.halfface_handle(0)], incident_cell_per_hf_[_h2.halfface_handle(0)]);
1587 std::swap(incident_cell_per_hf_[_h1.halfface_handle(1)], incident_cell_per_hf_[_h2.halfface_handle(1)]);
1588 swap_property_elements(_h1, _h2);
1589 swap_property_elements(halfface_handle(_h1, 0), halfface_handle(_h2, 0));
1590 swap_property_elements(halfface_handle(_h1, 1), halfface_handle(_h2, 1));
1591
1592}
1593
1595{
1596 assert(_h1.idx() >= 0 && _h1.idx() < (int)edges_.size());
1597 assert(_h2.idx() >= 0 && _h2.idx() < (int)edges_.size());
1598
1599 if (_h1 == _h2)
1600 return;
1601
1602 std::vector<unsigned int> ids;
1603 ids.push_back(_h1.idx());
1604 ids.push_back(_h2.idx());
1605
1606
1607 // correct pointers to those edges
1608
1609 if (has_edge_bottom_up_incidences())
1610 {
1611 std::set<unsigned int> processed_faces; // to ensure ids are only swapped once (in the case that the two swapped edges belong to a common face)
1612
1613 for (unsigned int i = 0; i < 2; ++i) // For both swapped edges
1614 {
1615 HalfEdgeHandle heh = HalfEdgeHandle(2*ids[i]);
1616
1617
1618 std::vector<HalfFaceHandle>& incident_halffaces = incident_hfs_per_he_[heh];
1619 for (unsigned int j = 0; j < incident_halffaces.size(); ++j) // for each incident halfface
1620 {
1621 HalfFaceHandle hfh = incident_halffaces[j];
1622
1623 unsigned int f_id = hfh.idx() / 2;
1624
1625 if (processed_faces.find(f_id) == processed_faces.end())
1626 {
1627
1628 Face& f = faces_[FaceHandle(f_id)];
1629
1630 // replace old incident halfedges with new incident halfedges where the ids are swapped
1631 std::vector<HalfEdgeHandle> new_halfedges;
1632 for (unsigned int k = 0; k < f.halfedges().size(); ++k)
1633 {
1634 HalfEdgeHandle heh2 = f.halfedges()[k];
1635 if (heh2.idx() / 2 == (int)ids[0])
1636 new_halfedges.push_back(HalfEdgeHandle(2*ids[1] + (heh2.idx() % 2)));
1637 else if (heh2.idx() / 2 == (int)ids[1])
1638 new_halfedges.push_back(HalfEdgeHandle(2*ids[0] + (heh2.idx() % 2)));
1639 else
1640 new_halfedges.push_back(heh2);
1641 }
1642 f.set_halfedges(new_halfedges);
1643
1644 processed_faces.insert(f_id);
1645 }
1646 }
1647 }
1648 }
1649 else
1650 {
1651 // search for all faces that contain one of the swapped edges
1652 for (unsigned int i = 0; i < faces_.size(); ++i)
1653 {
1654 Face& f = faces_[FaceHandle(i)];
1655
1656 // check if f contains a swapped edge
1657 bool contains_swapped_edge = false;
1658 for (unsigned int k = 0; k < f.halfedges().size(); ++k)
1659 {
1660 if (f.halfedges()[k].idx()/2 == (int)ids[0])
1661 contains_swapped_edge = true;
1662 if (f.halfedges()[k].idx()/2 == (int)ids[1])
1663 contains_swapped_edge = true;
1664 if (contains_swapped_edge)
1665 break;
1666 }
1667
1668 if (contains_swapped_edge)
1669 {
1670 // replace old incident halfedges with new incident halfedges where the ids are swapped
1671 std::vector<HalfEdgeHandle> new_halfedges;
1672 for (unsigned int k = 0; k < f.halfedges().size(); ++k)
1673 {
1674 HalfEdgeHandle heh2 = f.halfedges()[k];
1675 if (heh2.idx() / 2 == (int)ids[0])
1676 new_halfedges.push_back(HalfEdgeHandle(2*ids[1] + (heh2.idx() % 2)));
1677 else if (heh2.idx() / 2 == (int)ids[1])
1678 new_halfedges.push_back(HalfEdgeHandle(2*ids[0] + (heh2.idx() % 2)));
1679 else
1680 new_halfedges.push_back(heh2);
1681 }
1682 f.set_halfedges(new_halfedges);
1683 }
1684 }
1685 }
1686
1687 // correct bottom up incidences
1688
1689 if (has_vertex_bottom_up_incidences())
1690 {
1691 std::set<VertexHandle> processed_vertices;
1692 for (unsigned int i = 0; i < 2; ++i) // For both swapped edges
1693 {
1694 Edge e = edge(EdgeHandle(ids[i]));
1695 std::vector<VertexHandle> vhs;
1696 vhs.push_back(e.from_vertex());
1697 vhs.push_back(e.to_vertex());
1698
1699 for (unsigned int j = 0; j < 2; ++j) // for both incident vertices
1700 {
1701 if (processed_vertices.find(vhs[j]) != processed_vertices.end())
1702 continue;
1703
1704 std::vector<HalfEdgeHandle>& outgoing_hes = outgoing_hes_per_vertex_[vhs[j]];
1705 for (unsigned int k = 0; k < outgoing_hes.size(); ++k)
1706 {
1707 HalfEdgeHandle& heh = outgoing_hes[k];
1708 if (heh.idx() / 2 == (int)ids[0])
1709 heh = HalfEdgeHandle(2 * ids[1] + (heh.idx() % 2));
1710 else if (heh.idx() / 2 == (int)ids[1])
1711 heh = HalfEdgeHandle(2 * ids[0] + (heh.idx() % 2));
1712 }
1713 processed_vertices.insert(vhs[j]);
1714 }
1715
1716 }
1717 }
1718
1719 // swap vector entries
1720 std::swap(edges_[_h1], edges_[_h2]);
1721 detail::swap_bool(edge_deleted_[_h1], edge_deleted_[_h2]);
1722 std::swap(incident_hfs_per_he_[_h1.halfedge_handle(0)], incident_hfs_per_he_[_h2.halfedge_handle(0)]);
1723 std::swap(incident_hfs_per_he_[_h1.halfedge_handle(1)], incident_hfs_per_he_[_h2.halfedge_handle(1)]);
1724 swap_property_elements(_h1, _h2);
1725 swap_property_elements(halfedge_handle(_h1, 0), halfedge_handle(_h2, 0));
1726 swap_property_elements(halfedge_handle(_h1, 1), halfedge_handle(_h2, 1));
1727
1728}
1729
1731{
1732 assert(is_valid(_h1));
1733 assert(is_valid(_h2));
1734
1735 if (_h1 == _h2)
1736 return;
1737
1738 std::array<VH, 2> ids {_h1, _h2};
1739
1740 // correct pointers to those vertices
1741
1742 if (has_vertex_bottom_up_incidences())
1743 {
1744 std::set<EH> processed_edges; // to ensure ids are only swapped once (in the case that the two swapped vertices are connected by an edge)
1745 for (unsigned int i = 0; i < 2; ++i) // For both swapped vertices
1746 {
1747 for (const auto heh: outgoing_hes_per_vertex_[ids[i]]) {
1748 const auto eh = heh.edge_handle();
1749
1750 if (processed_edges.find(eh) == processed_edges.end())
1751 {
1752 Edge& e = edges_[eh];
1753 if (e.from_vertex() == ids[0])
1754 e.set_from_vertex(ids[1]);
1755 else if (e.from_vertex() == ids[1])
1756 e.set_from_vertex(ids[0]);
1757
1758 if (e.to_vertex() == ids[0])
1759 e.set_to_vertex(ids[1]);
1760 else if (e.to_vertex() == ids[1])
1761 e.set_to_vertex(ids[0]);
1762
1763 processed_edges.insert(eh);
1764 }
1765 }
1766 }
1767
1768 }
1769 else
1770 {
1771 // search for all edges containing a swapped vertex
1772
1773 for (auto &e: edges_)
1774 {
1775 if (e.from_vertex() == ids[0])
1776 e.set_from_vertex(ids[1]);
1777 else if (e.from_vertex() == ids[1])
1778 e.set_from_vertex(ids[0]);
1779
1780 if (e.to_vertex() == ids[0])
1781 e.set_to_vertex(ids[1]);
1782 else if (e.to_vertex() == ids[1])
1783 e.set_to_vertex(ids[0]);
1784 }
1785 }
1786
1787 // swap vector entries
1788 detail::swap_bool(vertex_deleted_[_h1], vertex_deleted_[_h2]);
1789 std::swap(outgoing_hes_per_vertex_[_h1], outgoing_hes_per_vertex_[_h2]);
1790 swap_property_elements(_h1, _h2);
1791}
1792
1793
1794void TopologyKernel::enable_deferred_deletion(bool _enable)
1795{
1796 if (deferred_deletion_ && !_enable)
1798
1799 deferred_deletion_ = _enable;
1800}
1801
1802//========================================================================================
1803
1806{
1807 assert(is_valid(_edgeHandle));
1808 return edges_[_edgeHandle];
1809}
1810
1811//========================================================================================
1812
1815{
1816 assert(is_valid(_faceHandle));
1817 return faces_[_faceHandle];
1818}
1819
1820//========================================================================================
1821
1824{
1825 assert(is_valid(_cellHandle));
1826 return cells_[_cellHandle];
1827}
1828
1829//========================================================================================
1830
1833{
1834 assert(is_valid(_edgeHandle));
1835 return edges_[_edgeHandle];
1836}
1837
1838//========================================================================================
1839
1842{
1843
1844 assert(is_valid(_faceHandle));
1845 return faces_[_faceHandle];
1846}
1847
1848//========================================================================================
1849
1852{
1853 assert(is_valid(_cellHandle));
1854 return cells_[_cellHandle];
1855}
1856
1857//========================================================================================
1858
1861{
1862 assert(is_valid(_halfEdgeHandle));
1863
1864 // In case the handle is even, just return the corresponding edge
1865 // Otherwise return the opposite halfedge via opposite()
1866 if(_halfEdgeHandle.subidx() == 0)
1867 return edges_[_halfEdgeHandle.edge_handle()];
1868 else
1869 return opposite_halfedge(edges_[_halfEdgeHandle.edge_handle()]);
1870}
1871
1872//========================================================================================
1873
1876
1877 assert(is_valid(_halfFaceHandle));
1878
1879 // In case the handle is even, just return the corresponding face
1880 // Otherwise return the opposite halfface via opposite()
1881 if(_halfFaceHandle.idx() % 2 == 0)
1882 return faces_[_halfFaceHandle.face_handle()];
1883 else
1884 return opposite_halfface(faces_[_halfFaceHandle.face_handle()]);
1885}
1886
1887//========================================================================================
1888
1891{
1892 return halfedge(_halfEdgeHandle.opposite_handle());
1893}
1894
1895//========================================================================================
1896
1899{
1900 return halfface(_halfFaceHandle.opposite_handle());
1901}
1902
1903
1904//========================================================================================
1905
1906
1908{
1909 return find_halfedge(_vh1, _vh2);
1910}
1911
1912
1913//========================================================================================
1914
1915
1917{
1918 assert(is_valid(_vh1));
1919 assert(is_valid(_vh2));
1920
1921 for(VertexOHalfEdgeIter voh_it = voh_iter(_vh1); voh_it.valid(); ++voh_it) {
1922 if(halfedge(*voh_it).to_vertex() == _vh2) {
1923 return *voh_it;
1924 }
1925 }
1926
1927 return InvalidHalfEdgeHandle;
1928}
1929
1930//========================================================================================
1931
1933{
1934 assert(is_valid(_vh1));
1935 assert(is_valid(_vh2));
1936
1937 for( auto hfh : cell(_ch).halffaces())
1938 {
1939 for(auto heh : halfface(hfh).halfedges() )
1940 {
1941 if(from_vertex_handle(heh) == _vh1 && to_vertex_handle(heh) == _vh2)
1942 return heh;
1943 if(from_vertex_handle(heh) == _vh2 && to_vertex_handle(heh) == _vh1)
1944 return opposite_halfedge_handle(heh);
1945 }
1946 }
1947
1948 return InvalidHalfEdgeHandle;
1949}
1950
1951//========================================================================================
1952
1953HalfFaceHandle TopologyKernel::halfface(const std::vector<VertexHandle>& _vs) const
1954{
1955 return find_halfface(_vs);
1956}
1957
1958//========================================================================================
1959
1960HalfFaceHandle TopologyKernel::find_halfface(const std::vector<VertexHandle>& _vs) const
1961{
1962 assert(_vs.size() > 2);
1963
1964 VertexHandle v0 = _vs[0], v1 = _vs[1], v2 = _vs[2];
1965
1966 assert(v0.is_valid() && v1.is_valid() && v2.is_valid());
1967
1968 HalfEdgeHandle he0 = find_halfedge(v0, v1);
1969 if(!he0.is_valid()) return InvalidHalfFaceHandle;
1970 HalfEdgeHandle he1 = find_halfedge(v1, v2);
1971 if(!he1.is_valid()) return InvalidHalfFaceHandle;
1972
1973 std::vector<HalfEdgeHandle> hes;
1974 hes.push_back(he0);
1975 hes.push_back(he1);
1976
1977 return find_halfface(hes);
1978}
1979
1980//========================================================================================
1981
1982HalfFaceHandle TopologyKernel::find_halfface_in_cell(const std::vector<VertexHandle>& _vs, CellHandle _ch) const
1983{
1984 assert(_vs.size() > 2);
1985
1986 VertexHandle v0 = _vs[0], v1 = _vs[1], v2 = _vs[2];
1987
1988 assert(v0.is_valid() && v1.is_valid() && v2.is_valid());
1989
1990 // check all halfedges of cell until (v0 -> v1) is found and then verify (v0 -> v1 -> v2)
1991 for( auto hfh : cell(_ch).halffaces())
1992 {
1993 for(auto heh : halfface(hfh).halfedges() )
1994 {
1995 if(from_vertex_handle(heh) == v0 && to_vertex_handle(heh) == v1)
1997 return hfh;
1998
1999 // check if opposite halfedge gives desired halfedge
2000 if(from_vertex_handle(heh) == v1 && to_vertex_handle(heh) == v0)
2001 {
2002 HalfEdgeHandle heh_opp = opposite_halfedge_handle(heh);
2003 HalfFaceHandle hfh_opp = adjacent_halfface_in_cell(hfh,heh);
2004 if(to_vertex_handle(next_halfedge_in_halfface(heh_opp,hfh_opp)) == v2)
2005 return hfh_opp;
2006 }
2007 }
2008 }
2009
2010 return InvalidHalfFaceHandle;
2011}
2012
2013
2014//========================================================================================
2015
2016
2017HalfFaceHandle TopologyKernel::halfface_extensive(const std::vector<VertexHandle>& _vs) const
2018{
2019 return find_halfface_extensive(_vs);
2020}
2021
2022//========================================================================================
2023
2024
2025HalfFaceHandle TopologyKernel::find_halfface_extensive(const std::vector<VertexHandle>& _vs) const
2026{
2027 //TODO: schöner machen
2028
2029 assert(_vs.size() > 2);
2030
2031 VertexHandle v0 = _vs[0];
2032 VertexHandle v1 = _vs[1];
2033
2034 assert(v0.is_valid() && v1.is_valid());
2035
2036 HalfEdgeHandle he0 = find_halfedge(v0, v1);
2037 if(!he0.is_valid()) return InvalidHalfFaceHandle;
2038
2039 for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(he0); hehf_it.valid(); ++hehf_it)
2040 {
2041 std::vector<HalfEdgeHandle> hes = halfface(*hehf_it).halfedges();
2042
2043 if (hes.size() != _vs.size())
2044 continue;
2045
2046 int offset = 0;
2047 for (unsigned int i = 0; i < hes.size(); ++i)
2048 if (hes[i] == he0)
2049 offset = i;
2050
2051 bool all_vertices_found = true;
2052
2053 for (unsigned int i = 0; i < hes.size(); ++i)
2054 {
2055 HalfEdgeHandle heh = hes[(i+offset)%hes.size()];
2056 if (halfedge(heh).from_vertex() != _vs[i])
2057 {
2058 all_vertices_found = false;
2059 break;
2060 }
2061 }
2062
2063 if (all_vertices_found)
2064 return *hehf_it;
2065 }
2066
2067 return InvalidHalfFaceHandle;
2068}
2069
2070//========================================================================================
2071
2072HalfFaceHandle TopologyKernel::halfface(const std::vector<HalfEdgeHandle>& _hes) const
2073{
2074 return find_halfface(_hes);
2075}
2076
2077//========================================================================================
2078
2079HalfFaceHandle TopologyKernel::find_halfface(const std::vector<HalfEdgeHandle>& _hes) const
2080{
2081
2082 assert(_hes.size() >= 2);
2083
2084 HalfEdgeHandle he0 = _hes[0], he1 = _hes[1];
2085
2086 assert(he0.is_valid() && he1.is_valid());
2087
2088 for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(he0); hehf_it.valid(); ++hehf_it) {
2089
2090 std::vector<HalfEdgeHandle> hes = halfface(*hehf_it).halfedges();
2091 if(std::find(hes.begin(), hes.end(), he1) != hes.end()) {
2092 return *hehf_it;
2093 }
2094 }
2095
2096 return InvalidHalfFaceHandle;
2097}
2098
2099//========================================================================================
2100
2102
2103 assert(_heh.is_valid() && (size_t)_heh.idx() < edges_.size() * 2u);
2104 assert(_hfh.is_valid() && (size_t)_hfh.idx() < faces_.size() * 2u);
2105
2106 std::vector<HalfEdgeHandle> hes = halfface(_hfh).halfedges();
2107
2108 for(std::vector<HalfEdgeHandle>::const_iterator it = hes.begin();
2109 it != hes.end(); ++it) {
2110 if(*it == _heh) {
2111 if((it + 1) != hes.end()) return *(it + 1);
2112 else return *hes.begin();
2113 }
2114 }
2115
2116 return InvalidHalfEdgeHandle;
2117}
2118
2119//========================================================================================
2120
2122
2123 assert(_heh.is_valid() && (size_t)_heh.idx() < edges_.size() * 2u);
2124 assert(_hfh.is_valid() && (size_t)_hfh.idx() < faces_.size() * 2u);
2125
2126 std::vector<HalfEdgeHandle> hes = halfface(_hfh).halfedges();
2127
2128 for(std::vector<HalfEdgeHandle>::const_iterator it = hes.begin();
2129 it != hes.end(); ++it) {
2130 if(*it == _heh) {
2131 if(it != hes.begin()) return *(it - 1);
2132 else return *(hes.end() - 1);
2133 }
2134 }
2135
2136 return InvalidHalfEdgeHandle;
2137}
2138
2139
2140//========================================================================================
2141
2142
2143std::vector<VertexHandle> TopologyKernel::get_halfface_vertices(HalfFaceHandle hfh) const
2144{
2145 std::vector<VertexHandle> vhs;
2146 vhs.reserve(valence(hfh.face_handle()));
2147 for (VertexHandle vh : halfface_vertices(hfh)) {
2148 vhs.push_back(vh);
2149 }
2150 return vhs;
2151}
2152
2153
2154//========================================================================================
2155
2156
2158{
2159 std::vector<VertexHandle> vertices;
2160 const size_t n = valence(hfh.face_handle());
2161 vertices.reserve(n);
2162
2163 // Circulate until we're at the vertex of interest
2164 auto hfv_it = hfv_iter(hfh, 2);
2165 for (size_t i = 0; i < n; ++i)
2166 {
2167 if (*hfv_it == vh) {break;}
2168 ++hfv_it;
2169 }
2170
2171 // Circulate n times to get all the vertices
2172 for (size_t i = 0; i < n; ++i)
2173 {
2174 vertices.push_back(*hfv_it);
2175 ++hfv_it;
2176 }
2177
2178 return vertices;
2179}
2180
2181
2182//========================================================================================
2183
2184
2186{
2187 return get_halfface_vertices(hfh, from_vertex_handle(heh));
2188}
2189
2190
2191//========================================================================================
2192
2193
2194bool
2196is_incident( FaceHandle _fh, EdgeHandle _eh) const
2197{
2198 const auto f = face(_fh);
2199 for (HalfEdgeHandle heh: f.halfedges())
2200 if(edge_handle(heh) == _eh)
2201 return true;
2202
2203 return false;
2204}
2205
2206
2207//========================================================================================
2208
2209
2212 HalfEdgeHandle _halfEdgeHandle) const
2213{
2214 assert(_halfFaceHandle.is_valid() && (size_t)_halfFaceHandle.idx() < faces_.size() * 2u);
2215 assert(_halfEdgeHandle.is_valid() && (size_t)_halfEdgeHandle.idx() < edges_.size() * 2u);
2216 assert(has_face_bottom_up_incidences());
2217
2218 const auto ch = incident_cell(_halfFaceHandle);
2219 if(!ch.is_valid()) {
2220 // Specified halfface is on the outside of the complex
2221 return InvalidHalfFaceHandle;
2222 }
2223
2224 // Make sure that _halfFaceHandle is incident to _halfEdgeHandle
2225 bool skipped = false;
2226 HalfFaceHandle idx = InvalidHalfFaceHandle;
2227
2228 // For face-selfadjacent cells, we have to ensure the actual halfedge information
2229 // is used here, BUT...
2230 // To support legacy code, we have to flip the halfedge if it's the wrong one
2231 HalfEdgeHandle hehOpp = opposite_halfedge_handle(_halfEdgeHandle);
2232 bool hasHalfedge = false;
2233 bool hasOppHalfedge = false;
2234 const auto hf = halfface(_halfFaceHandle);
2235 for (HalfEdgeHandle heh: hf.halfedges()) {
2236 if (heh == hehOpp)
2237 hasOppHalfedge = true;
2238 else if (heh == _halfEdgeHandle)
2239 hasHalfedge = true;
2240 }
2241 if (!hasHalfedge) {
2242 if (hasOppHalfedge)
2243 _halfEdgeHandle = hehOpp;
2244 else
2245 return InvalidHalfFaceHandle;
2246 }
2247
2248 for(const auto &hfh: cell(ch).halffaces()) {
2249 if(hfh == _halfFaceHandle) {
2250 assert(!skipped); // a halfface may only appear once in a cell!
2251 skipped = true;
2252 if (idx.is_valid()) {
2253 return idx;
2254 }
2255 } else {
2256 const auto hf_cur = halfface(hfh);
2257 for (const auto heh: hf_cur.halfedges()) {
2258 // For face-selfadjacent cells, we look for a halfface that
2259 // contains the opposite halfedge but isnt the opposite halfface
2260 if(opposite_halfedge_handle(heh) == _halfEdgeHandle && hfh != opposite_halfface_handle(_halfFaceHandle)) {
2261 if (idx.is_valid()) {
2262 // we found two(!) other halffaces that contain the given edge.
2263 // likely the given halfedge is not part of the given halfface
2264 return InvalidHalfFaceHandle;
2265 }
2266 if (skipped) {
2267 return hfh;
2268 } else {
2269 idx = hfh;
2270 continue;
2271 }
2272 }
2273 }
2274 }
2275 }
2276 return InvalidHalfFaceHandle;
2277}
2278
2279
2280//========================================================================================
2281
2283{
2284 assert((size_t)_halfFaceHandle.idx() < incident_cell_per_hf_.size() && _halfFaceHandle.is_valid());
2285 assert(has_face_bottom_up_incidences());
2286
2287 return incident_cell_per_hf_[_halfFaceHandle];
2288}
2289
2290//========================================================================================
2291
2292void TopologyKernel::compute_vertex_bottom_up_incidences() {
2293
2294 // Clear incidences
2295 outgoing_hes_per_vertex_.clear();
2296 outgoing_hes_per_vertex_.resize(n_vertices());
2297 VertexVector<int> n_edges_per_vertex(n_vertices(), 0);
2298
2299 for (const auto &eh: edges()) {
2300 const auto &e = edge(eh);
2301 ++n_edges_per_vertex[e.from_vertex()];
2302 ++n_edges_per_vertex[e.to_vertex()];
2303 }
2304 for (const auto &vh: vertices()) {
2305 outgoing_hes_per_vertex_[vh].reserve(n_edges_per_vertex[vh]);
2306 }
2307
2308 // Store outgoing halfedges per vertex
2309 for (const auto eh: edges()) {
2310 const auto &e = edge(eh);
2311 VertexHandle from = e.from_vertex();
2312 // If this condition is not fulfilled, it is out of caller's control and
2313 // definitely our bug, therefore an assert
2314 assert((size_t)from.idx() < outgoing_hes_per_vertex_.size());
2315
2316 outgoing_hes_per_vertex_[from].push_back(halfedge_handle(eh, 0));
2317
2318 VertexHandle to = e.to_vertex();
2319 assert((size_t)to.idx() < outgoing_hes_per_vertex_.size());
2320
2321 // Store opposite halfedge handle
2322 outgoing_hes_per_vertex_[to].push_back(halfedge_handle(eh, 1));
2323 }
2324}
2325
2326//========================================================================================
2327
2328void TopologyKernel::compute_edge_bottom_up_incidences() {
2329
2330 // Clear
2331 incident_hfs_per_he_.clear();
2332 incident_hfs_per_he_.resize(n_halfedges());
2333
2334 EdgeVector<int> n_faces_per_edge(n_edges(), 0);
2335 for (const auto &fh: faces()) {
2336 for (const auto &heh: face_halfedges(fh)) {
2337 ++n_faces_per_edge[edge_handle(heh)];
2338 }
2339 }
2340 for (const auto &eh: edges()) {
2341 incident_hfs_per_he_[halfedge_handle(eh, 0)].reserve(n_faces_per_edge[eh]);
2342 incident_hfs_per_he_[halfedge_handle(eh, 1)].reserve(n_faces_per_edge[eh]);
2343 }
2344 // Store incident halffaces per halfedge
2345 for (const auto &fh: faces()) {
2346 for (const auto &heh: face_halfedges(fh)) {
2347 auto opp = opposite_halfedge_handle(heh);
2348 incident_hfs_per_he_[heh].push_back(halfface_handle(fh, 0));
2349 incident_hfs_per_he_[opp].push_back(halfface_handle(fh, 1));
2350 }
2351 }
2352}
2353
2354//========================================================================================
2355
2356void TopologyKernel::compute_face_bottom_up_incidences() {
2357
2358 // Clear
2359 incident_cell_per_hf_.clear();
2360 incident_cell_per_hf_.resize(faces_.size() * 2u, InvalidCellHandle);
2361
2362 for (const auto ch: cells()) {
2363 for (const auto hfh: cell_halffaces(ch)) {
2364 if(incident_cell_per_hf_[hfh] == InvalidCellHandle) {
2365
2366 incident_cell_per_hf_[hfh] = ch;
2367
2368 } else {
2369#ifndef NDEBUG
2370 std::cerr << "compute_face_bottom_up_incidences(): Detected non-three-manifold configuration!" << std::endl;
2371 std::cerr << "Connectivity probably won't work." << std::endl;
2372#endif
2373 }
2374 }
2375 }
2376}
2377
2378} // Namespace OpenVolumeMesh
void resize_vprops(size_t _nv)
Change size of stored vertex properties.
size_t n() const
Get number of entities of given kind in mesh.
void resize_cprops(size_t _nc)
Change size of stored cell properties.
void resize_eprops(size_t _ne)
Change size of stored edge properties.
void resize_fprops(size_t _nf)
Change size of stored face properties.
Face opposite_halfface(HalfFaceHandle _halfFaceHandle) const
Get opposite halfface that corresponds to halfface with handle _halfFaceHandle.
size_t valence(VertexHandle _vh) const
Get valence of vertex (number of incident edges)
virtual VertexIter delete_vertex(VertexHandle _h)
Delete vertex from mesh.
CellHandle incident_cell(HalfFaceHandle _halfFaceHandle) const
Get cell that is incident to the given halfface.
void set_cell(CellHandle _ch, const std::vector< HalfFaceHandle > &_hfs)
Set the half-faces of a cell.
const Cell & cell(CellHandle _cellHandle) const
Get cell with handle _cellHandle.
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
CellIter delete_cell_core(CellHandle _h)
Delete cell from mesh.
HalfEdgeHandle prev_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get previous halfedge within a halfface.
HalfFaceHandle find_halfface_in_cell(const std::vector< VertexHandle > &_vs, CellHandle _ch) const
HalfEdgeHandle find_halfedge_in_cell(VertexHandle _vh1, VertexHandle _vh2, CellHandle _ch) const
Get halfedge from vertex _vh1 to _vh2 but restricted to halfedges of cell _ch.
static HalfEdgeHandle halfedge_handle(EdgeHandle _h, const unsigned char _subIdx)
Conversion function.
HalfFaceHandle find_halfface_extensive(const std::vector< VertexHandle > &_vs) const
HalfEdgeHandle find_halfedge(VertexHandle _vh1, VertexHandle _vh2) const
Get halfedge from vertex _vh1 to _vh2.
virtual CellIter delete_cell(CellHandle _h)
Delete cell from mesh.
void set_edge(EdgeHandle _eh, VertexHandle _fromVertex, VertexHandle _toVertex)
Set the vertices of an edge.
HalfEdgeHandle next_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get next halfedge within a halfface.
virtual void swap_vertex_indices(VertexHandle _h1, VertexHandle _h2)
Exchanges the indices of two vertices while keeping the mesh otherwise unaffected.
EdgeIter delete_edge_core(EdgeHandle _h)
Delete edge from mesh.
static EdgeHandle edge_handle(HalfEdgeHandle _h)
Handle conversion.
size_t n_vertices() const override
Get number of vertices in mesh.
virtual FaceIter delete_face(FaceHandle _h)
Delete face from mesh.
virtual FaceHandle add_face(std::vector< HalfEdgeHandle > _halfedges, bool _topologyCheck=false)
Add face via incident edges.
static HalfFaceHandle halfface_handle(FaceHandle _h, const unsigned char _subIdx)
Conversion function.
size_t n_faces() const override
Get number of faces in mesh.
void set_face(FaceHandle _fh, const std::vector< HalfEdgeHandle > &_hes)
Set the half-edges of a face.
virtual CellHandle add_cell(std::vector< HalfFaceHandle > _halffaces, bool _topologyCheck=false)
Add cell via incident halffaces.
virtual void swap_edge_indices(EdgeHandle _h1, EdgeHandle _h2)
Exchanges the indices of two edges while keeping the mesh otherwise unaffected.
size_t n_cells() const override
Get number of cells in mesh.
std::vector< VertexHandle > get_halfface_vertices(HalfFaceHandle hfh) const
Get vertices of a halfface.
virtual void swap_cell_indices(CellHandle _h1, CellHandle _h2)
Exchanges the indices of two cells while keeping the mesh otherwise unaffected.
size_t n_edges() const override
Get number of edges in mesh.
Face halfface(HalfFaceHandle _halfFaceHandle) const
Get face that corresponds to halfface with handle _halfFaceHandle.
Edge opposite_halfedge(HalfEdgeHandle _halfEdgeHandle) const
Get opposite halfedge that corresponds to halfedge with handle _halfEdgeHandle.
Edge halfedge(HalfEdgeHandle _halfEdgeHandle) const
Get edge that corresponds to halfedge with handle _halfEdgeHandle.
VertexHandle from_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge starts from.
HalfFaceHandle find_halfface(const std::vector< VertexHandle > &_vs) const
const Edge & edge(EdgeHandle _edgeHandle) const
Get edge with handle _edgeHandle.
virtual EdgeHandle add_edge(VertexHandle _fromVertex, VertexHandle _toHandle, bool _allowDuplicates=false)
Add edge.
virtual VertexHandle add_vertex()
Add abstract vertex.
virtual EdgeIter delete_edge(EdgeHandle _h)
Delete edge from mesh.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.
virtual void swap_face_indices(FaceHandle _h1, FaceHandle _h2)
Exchanges the indices of two faces while keeping the mesh otherwise unaffected.
FaceIter delete_face_core(FaceHandle _h)
Delete face from mesh.
bool is_incident(FaceHandle _fh, EdgeHandle _eh) const
check whether face _fh and edge _eh are incident
HalfFaceHandle adjacent_halfface_in_cell(HalfFaceHandle _halfFaceHandle, HalfEdgeHandle _halfEdgeHandle) const
Get halfface that is adjacent (w.r.t. a common halfedge) within the same cell. It correctly handles s...
size_t n_halffaces() const override
Get number of halffaces in mesh.
void reorder_incident_halffaces(EdgeHandle _eh)
Recompute cyclic ordering of (half)faces incident to an edge (used by iterators)
const Face & face(FaceHandle _faceHandle) const
Get face with handle _faceHandle.
VertexIter delete_vertex_core(VertexHandle _h)
Delete vertex from mesh.
virtual void collect_garbage()
Delete all entities that are marked as deleted.