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