Developer Documentation
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  * link it with other files to produce an executable, this file does *
19  * not by itself cause the resulting executable to be covered by the *
20  * GNU Lesser General Public License. This exception does not however *
21  * invalidate any other reasons why the executable file might be *
22  * covered by the GNU Lesser General Public License. *
23  * *
24  * OpenVolumeMesh is distributed in the hope that it will be useful, *
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27  * GNU Lesser General Public License for more details. *
28  * *
29  * You should have received a copy of the GNU LesserGeneral Public *
30  * License along with OpenVolumeMesh. If not, *
31  * see <http://www.gnu.org/licenses/>. *
32  * *
33 \*===========================================================================*/
34 
35 /*===========================================================================*\
36  * *
37  * $Revision$ *
38  * $Date$ *
39  * $LastChangedBy$ *
40  * *
41 \*===========================================================================*/
42 
43 #ifndef NDEBUG
44 #include <iostream>
45 #endif
46 
47 #include <queue>
48 
49 #include "TopologyKernel.hh"
50 
51 namespace OpenVolumeMesh {
52 
53 // Initialize constants
54 const VertexHandle TopologyKernel::InvalidVertexHandle = VertexHandle(-1);
55 const EdgeHandle TopologyKernel::InvalidEdgeHandle = EdgeHandle(-1);
56 const HalfEdgeHandle TopologyKernel::InvalidHalfEdgeHandle = HalfEdgeHandle(-1);
57 const FaceHandle TopologyKernel::InvalidFaceHandle = FaceHandle(-1);
58 const HalfFaceHandle TopologyKernel::InvalidHalfFaceHandle = HalfFaceHandle(-1);
59 const CellHandle TopologyKernel::InvalidCellHandle = CellHandle(-1);
60 
61 //========================================================================================
62 
64 
65  ++n_vertices_;
66  vertex_deleted_.push_back(false);
67 
68  // Create item for vertex bottom-up incidences
69  if(v_bottom_up_) {
70  outgoing_hes_per_vertex_.resize(n_vertices_);
71  }
72 
73  // Resize vertex props
74  resize_vprops(n_vertices_);
75 
76  // Return 0-indexed handle
77  return VertexHandle((int)(n_vertices_ - 1));
78 }
79 
80 //========================================================================================
81 
84  const VertexHandle& _toVertex,
85  bool _allowDuplicates) {
86 
87  // If the conditions are not fulfilled, assert will fail (instead
88  // of returning an invalid handle)
89  assert(_fromVertex.is_valid() && (size_t)_fromVertex.idx() < n_vertices() && !is_deleted(_fromVertex));
90  assert(_toVertex.is_valid() && (size_t)_toVertex.idx() < n_vertices() && !is_deleted(_toVertex));
91 
92  // Test if edge does not exist, yet
93  if(!_allowDuplicates) {
94  if(v_bottom_up_) {
95 
96  assert((size_t)_fromVertex.idx() < outgoing_hes_per_vertex_.size());
97  std::vector<HalfEdgeHandle>& ohes = outgoing_hes_per_vertex_[_fromVertex.idx()];
98  for(std::vector<HalfEdgeHandle>::const_iterator he_it = ohes.begin(),
99  he_end = ohes.end(); he_it != he_end; ++he_it) {
100  if(halfedge(*he_it).to_vertex() == _toVertex) {
101  return edge_handle(*he_it);
102  }
103  }
104  } else {
105  for(int i = 0; i < (int)edges_.size(); ++i) {
106  if(edge(EdgeHandle(i)).from_vertex() == _fromVertex && edge(EdgeHandle(i)).to_vertex() == _toVertex) {
107  return EdgeHandle(i);
108  } else if(edge(EdgeHandle(i)).from_vertex() == _toVertex && edge(EdgeHandle(i)).to_vertex() == _fromVertex) {
109  return EdgeHandle(i);
110  }
111  }
112  }
113  }
114 
115  // Create edge object
116  OpenVolumeMeshEdge e(_fromVertex, _toVertex);
117 
118  // Store edge locally
119  edges_.push_back(e);
120  edge_deleted_.push_back(false);
121 
122  // Resize props
124 
125  EdgeHandle eh((int)edges_.size()-1);
126 
127  // Update vertex bottom-up incidences
128  if(v_bottom_up_) {
129  assert((size_t)_fromVertex.idx() < outgoing_hes_per_vertex_.size());
130  assert((size_t)_toVertex.idx() < outgoing_hes_per_vertex_.size());
131 
132  outgoing_hes_per_vertex_[_fromVertex.idx()].push_back(halfedge_handle(eh, 0));
133  outgoing_hes_per_vertex_[_toVertex.idx()].push_back(halfedge_handle(eh, 1));
134  }
135 
136  // Create item for edge bottom-up incidences
137  if(e_bottom_up_) {
138  incident_hfs_per_he_.resize(n_halfedges());
139  }
140 
141  // Get handle of recently created edge
142  return eh;
143 }
144 
145 //========================================================================================
146 
148 FaceHandle TopologyKernel::add_face(const std::vector<HalfEdgeHandle>& _halfedges, bool _topologyCheck) {
149 
150 #ifndef NDEBUG
151  // Assert that halfedges are valid
152  for(std::vector<HalfEdgeHandle>::const_iterator it = _halfedges.begin(),
153  end = _halfedges.end(); it != end; ++it)
154  assert(it->is_valid() && (size_t)it->idx() < edges_.size() * 2u && !is_deleted(*it));
155 #endif
156 
157  // Perform topology check
158  if(_topologyCheck) {
159 
160  /*
161  * Test if halfedges are connected
162  *
163  * The test works as follows:
164  * For every edge in the parameter vector
165  * put all incident vertices into a
166  * set of either "from"-vertices or "to"-vertices,
167  * respectively.
168  * If and only if all edges are connected,
169  * then both sets are identical.
170  */
171 
172  std::set<VertexHandle> fromVertices;
173  std::set<VertexHandle> toVertices;
174 
175  for(std::vector<HalfEdgeHandle>::const_iterator it = _halfedges.begin(),
176  end = _halfedges.end(); it != end; ++it) {
177 
178  fromVertices.insert(halfedge(*it).from_vertex());
179  toVertices.insert(halfedge(*it).to_vertex());
180  }
181 
182  for(std::set<VertexHandle>::const_iterator v_it = fromVertices.begin(),
183  v_end = fromVertices.end(); v_it != v_end; ++v_it) {
184  if(toVertices.count(*v_it) != 1) {
185  // The situation here is different, the caller has requested a
186  // topology check and expects an invalid handle if the half-edges
187  // are not connected. Give him a message in debug mode.
188 #ifndef NDEBUG
189  std::cerr << "add_face(): The specified halfedges are not connected!" << std::endl;
190 #endif
191  return InvalidFaceHandle;
192  }
193  }
194 
195  // The halfedges are now guaranteed to be connected
196  }
197 
198  // Create face
199  OpenVolumeMeshFace face(_halfedges);
200 
201  faces_.push_back(face);
202  face_deleted_.push_back(false);
203 
204  // Get added face's handle
205  FaceHandle fh((int)faces_.size() - 1);
206 
207  // Resize props
209 
210  // Update edge bottom-up incidences
211  if(e_bottom_up_) {
212 
213  for(std::vector<HalfEdgeHandle>::const_iterator it = _halfedges.begin(),
214  end = _halfedges.end(); it != end; ++it) {
215 
216  assert((size_t)it->idx() < incident_hfs_per_he_.size());
217  assert((size_t)opposite_halfedge_handle(*it).idx() < incident_hfs_per_he_.size());
218 
219  incident_hfs_per_he_[it->idx()].push_back(halfface_handle(fh, 0));
220  incident_hfs_per_he_[opposite_halfedge_handle(*it).idx()].push_back(halfface_handle(fh, 1));
221  }
222  }
223 
224  // Create item for face bottom-up incidences
225  if(f_bottom_up_) {
226  incident_cell_per_hf_.resize(n_halffaces(), InvalidCellHandle);
227  }
228 
229  // Return handle of recently created face
230  return fh;
231 }
232 
233 //========================================================================================
234 
237 FaceHandle 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 
273 void TopologyKernel::reorder_incident_halffaces(const EdgeHandle& _eh) {
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  for(unsigned char s = 0; s <= 1; s++) {
293 
294  HalfEdgeHandle cur_he = halfedge_handle(_eh, s);
295  std::vector<HalfFaceHandle> new_halffaces;
296  HalfFaceHandle start_hf = InvalidHalfFaceHandle;
297  HalfFaceHandle cur_hf = InvalidHalfFaceHandle;
298 
299  // Start with one incident halfface and go into the first direction
300  assert((size_t)cur_he.idx() < incident_hfs_per_he_.size());
301 
302  if(incident_hfs_per_he_[cur_he.idx()].size() != 0) {
303 
304  // Get start halfface
305  cur_hf = *incident_hfs_per_he_[cur_he.idx()].begin();
306  start_hf = cur_hf;
307 
308  while(cur_hf != InvalidHalfFaceHandle) {
309 
310  // Add halfface
311  new_halffaces.push_back(cur_hf);
312 
313  // Go to next halfface
314  cur_hf = adjacent_halfface_in_cell(cur_hf, cur_he);
315 
316  if(cur_hf != InvalidHalfFaceHandle)
317  {
318  if (is_deleted(incident_cell(cur_hf)))
319  break; // pretend we ran into a boundary
320  cur_hf = opposite_halfface_handle(cur_hf);
321  }
322 
323  // End when we're through
324  if(cur_hf == start_hf) break;
325  // if one of the faces of the cell was already incident to another cell we need this check
326  // to prevent running into an infinite loop.
327  if(std::find(new_halffaces.begin(), new_halffaces.end(), cur_hf) != new_halffaces.end()) break;
328  }
329 
330  // First direction has terminated
331  // If new_halffaces has the same size as old (unordered)
332  // vector of incident halffaces, we are done here
333  // If not, try the other way round
334  if(new_halffaces.size() != incident_hfs_per_he_[cur_he.idx()].size()) {
335 
336  // Get opposite of start halfface
337  cur_hf = start_hf;
338 
339  while(cur_hf != InvalidHalfFaceHandle) {
340 
341  cur_hf = opposite_halfface_handle(cur_hf);
342  cur_hf = adjacent_halfface_in_cell(cur_hf, cur_he);
343 
344  if(cur_hf == start_hf) break;
345 
346  // if one of the faces of the cell was already incident to another cell we need this check
347  // to prevent running into an infinite loop.
348  if(std::find(new_halffaces.begin(), new_halffaces.end(), cur_hf) != new_halffaces.end()) break;
349 
350  if(cur_hf != InvalidHalfFaceHandle)
351  new_halffaces.insert(new_halffaces.begin(), cur_hf);
352  else break;
353  }
354  }
355 
356  // Everything worked just fine, set the new ordered vector
357  if(new_halffaces.size() == incident_hfs_per_he_[cur_he.idx()].size()) {
358  incident_hfs_per_he_[cur_he.idx()] = new_halffaces;
359  }
360  }
361  }
362 }
363 
364 //========================================================================================
365 
367 CellHandle TopologyKernel::add_cell(const std::vector<HalfFaceHandle>& _halffaces, bool _topologyCheck) {
368 
369 #ifndef NDEBUG
370  // Assert that halffaces have valid indices
371  for(std::vector<HalfFaceHandle>::const_iterator it = _halffaces.begin(),
372  end = _halffaces.end(); it != end; ++it)
373  assert(it->is_valid() && ((size_t)it->idx() < faces_.size() * 2u) && !is_deleted(*it));
374 #endif
375 
376  // Perform topology check
377  if(_topologyCheck) {
378 
379  /*
380  * Test if all halffaces are connected and form a two-manifold
381  * => Cell is closed
382  *
383  * This test is simple: The number of involved half-edges has to be
384  * exactly twice the number of involved edges.
385  */
386 
387  std::set<HalfEdgeHandle> incidentHalfedges;
388  std::set<EdgeHandle> incidentEdges;
389 
390  for(std::vector<HalfFaceHandle>::const_iterator it = _halffaces.begin(),
391  end = _halffaces.end(); it != end; ++it) {
392 
393  OpenVolumeMeshFace hface = halfface(*it);
394  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hface.halfedges().begin(),
395  he_end = hface.halfedges().end(); he_it != he_end; ++he_it) {
396  incidentHalfedges.insert(*he_it);
397  incidentEdges.insert(edge_handle(*he_it));
398  }
399  }
400 
401  if(incidentHalfedges.size() != (incidentEdges.size() * 2u)) {
402 #ifndef NDEBUG
403  std::cerr << "add_cell(): The specified half-faces are not connected!" << std::endl;
404 #endif
405  return InvalidCellHandle;
406  }
407 
408  // The halffaces are now guaranteed to form a two-manifold
409  }
410 
411  // Create new cell
412  OpenVolumeMeshCell cell(_halffaces);
413 
414  cells_.push_back(cell);
415  cell_deleted_.push_back(false);
416 
417  // Resize props
419 
420  CellHandle ch((int)cells_.size()-1);
421 
422  // Update face bottom-up incidences
423  if(f_bottom_up_) {
424 
425  std::set<EdgeHandle> cell_edges;
426  for(std::vector<HalfFaceHandle>::const_iterator it = _halffaces.begin(),
427  end = _halffaces.end(); it != end; ++it) {
428  assert((size_t)it->idx() < incident_cell_per_hf_.size());
429 
430 #ifndef NDEBUG
431  if(_topologyCheck) {
432  if(incident_cell_per_hf_[it->idx()] != InvalidCellHandle) {
433  // Shouldn't this situation be dealt with before adding the
434  // cell and return InvalidCellHandle in this case?
435  // Mike: Not if the user intends to add non-manifold
436  // configurations. Although, in this case, he should be
437  // warned about it.
438  std::cerr << "add_cell(): One of the specified half-faces is already incident to another cell!" << std::endl;
439  }
440  }
441 #endif
442 
443  // Overwrite incident cell for current half-face
444  incident_cell_per_hf_[it->idx()] = ch;
445 
446  // Collect all edges of cell
447  const std::vector<HalfEdgeHandle> hes = halfface(*it).halfedges();
448  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
449  he_end = hes.end(); he_it != he_end; ++he_it) {
450  cell_edges.insert(edge_handle(*he_it));
451  }
452  }
453 
454  if(e_bottom_up_) {
455 
456  // Try to reorder all half-faces w.r.t.
457  // their incident half-edges such that all
458  // half-faces are in cyclic order around
459  // a half-edge
460  for(std::set<EdgeHandle>::const_iterator e_it = cell_edges.begin(),
461  e_end = cell_edges.end(); e_it != e_end; ++e_it) {
462  reorder_incident_halffaces(*e_it);
463  }
464  }
465  }
466 
467  return ch;
468 }
469 
470 //========================================================================================
471 
473 // cppcheck-suppress unusedFunction ; public interface
474 void TopologyKernel::set_edge(const EdgeHandle& _eh, const VertexHandle& _fromVertex, const VertexHandle& _toVertex) {
475 
476  assert(_fromVertex.is_valid() && (size_t)_fromVertex.idx() < n_vertices() && !is_deleted(_fromVertex));
477  assert(_toVertex.is_valid() && (size_t)_toVertex.idx() < n_vertices() && !is_deleted(_toVertex));
478 
479  Edge& e = edge(_eh);
480 
481  // Update bottom-up entries
482  if(has_vertex_bottom_up_incidences()) {
483 
484  const VertexHandle& fv = e.from_vertex();
485  const VertexHandle& tv = e.to_vertex();
486 
487  const HalfEdgeHandle heh0 = halfedge_handle(_eh, 0);
488  const HalfEdgeHandle heh1 = halfedge_handle(_eh, 1);
489 
490  std::vector<HalfEdgeHandle>::iterator h_end =
491  std::remove(outgoing_hes_per_vertex_[fv.idx()].begin(), outgoing_hes_per_vertex_[fv.idx()].end(), heh0);
492  outgoing_hes_per_vertex_[fv.idx()].resize(h_end - outgoing_hes_per_vertex_[fv.idx()].begin());
493 
494  h_end = std::remove(outgoing_hes_per_vertex_[tv.idx()].begin(), outgoing_hes_per_vertex_[tv.idx()].end(), heh1);
495  outgoing_hes_per_vertex_[tv.idx()].resize(h_end - outgoing_hes_per_vertex_[tv.idx()].begin());
496 
497  outgoing_hes_per_vertex_[_fromVertex.idx()].push_back(heh0);
498  outgoing_hes_per_vertex_[_toVertex.idx()].push_back(heh1);
499  }
500 
501  e.set_from_vertex(_fromVertex);
502  e.set_to_vertex(_toVertex);
503 }
504 
505 //========================================================================================
506 
508 // cppcheck-suppress unusedFunction ; public interface
509 void TopologyKernel::set_face(const FaceHandle& _fh, const std::vector<HalfEdgeHandle>& _hes) {
510 
511  Face& f = face(_fh);
512 
513  if(has_edge_bottom_up_incidences()) {
514 
515  const HalfFaceHandle hf0 = halfface_handle(_fh, 0);
516  const HalfFaceHandle hf1 = halfface_handle(_fh, 1);
517 
518  const std::vector<HalfEdgeHandle>& hes = f.halfedges();
519 
520  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
521  he_end = hes.end(); he_it != he_end; ++he_it) {
522 
523  std::vector<HalfFaceHandle>::iterator h_end =
524  std::remove(incident_hfs_per_he_[he_it->idx()].begin(),
525  incident_hfs_per_he_[he_it->idx()].end(), hf0);
526  incident_hfs_per_he_[he_it->idx()].resize(h_end - incident_hfs_per_he_[he_it->idx()].begin());
527 
528  h_end = std::remove(incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].begin(),
529  incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].end(), hf1);
530  incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].resize(h_end - incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].begin());
531  }
532 
533  for(std::vector<HalfEdgeHandle>::const_iterator he_it = _hes.begin(),
534  he_end = _hes.end(); he_it != he_end; ++he_it) {
535 
536  incident_hfs_per_he_[he_it->idx()].push_back(hf0);
537  incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].push_back(hf1);
538  }
539 
540  // TODO: Reorder incident half-faces
541  }
542 
543  f.set_halfedges(_hes);
544 }
545 
546 //========================================================================================
547 
549 // cppcheck-suppress unusedFunction ; public interface
550 void TopologyKernel::set_cell(const CellHandle& _ch, const std::vector<HalfFaceHandle>& _hfs) {
551 
552  Cell& c = cell(_ch);
553 
554  if(has_face_bottom_up_incidences()) {
555 
556  const std::vector<HalfFaceHandle>& hfs = c.halffaces();
557  for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
558  hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
559 
560  incident_cell_per_hf_[hf_it->idx()] = InvalidCellHandle;
561  }
562 
563  for(std::vector<HalfFaceHandle>::const_iterator hf_it = _hfs.begin(),
564  hf_end = _hfs.end(); hf_it != hf_end; ++hf_it) {
565 
566  incident_cell_per_hf_[hf_it->idx()] = _ch;
567  }
568  }
569 
570  c.set_halffaces(_hfs);
571 }
572 
573 //========================================================================================
574 
588 
589  assert(!is_deleted(_h));
590 
591  std::vector<VertexHandle> vs;
592  vs.push_back(_h);
593 
594  std::set<EdgeHandle> incidentEdges_s;
595  get_incident_edges(vs, incidentEdges_s);
596 
597  std::set<FaceHandle> incidentFaces_s;
598  get_incident_faces(incidentEdges_s, incidentFaces_s);
599 
600  std::set<CellHandle> incidentCells_s;
601  get_incident_cells(incidentFaces_s, incidentCells_s);
602 
603  // Delete cells
604  for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
605  c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
606  delete_cell_core(*c_it);
607  }
608 
609  // Delete faces
610  for(std::set<FaceHandle>::const_reverse_iterator f_it = incidentFaces_s.rbegin(),
611  f_end = incidentFaces_s.rend(); f_it != f_end; ++f_it) {
612  delete_face_core(*f_it);
613  }
614 
615  // Delete edges
616  for(std::set<EdgeHandle>::const_reverse_iterator e_it = incidentEdges_s.rbegin(),
617  e_end = incidentEdges_s.rend(); e_it != e_end; ++e_it) {
618  delete_edge_core(*e_it);
619  }
620 
621  // Delete vertex
622  return delete_vertex_core(_h);
623 }
624 
625 //========================================================================================
626 
640 
641  assert(!is_deleted(_h));
642 
643  std::vector<EdgeHandle> es;
644  es.push_back(_h);
645 
646  std::set<FaceHandle> incidentFaces_s;
647  get_incident_faces(es, incidentFaces_s);
648 
649  std::set<CellHandle> incidentCells_s;
650  get_incident_cells(incidentFaces_s, incidentCells_s);
651 
652  // Delete cells
653  for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
654  c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
655  delete_cell_core(*c_it);
656  }
657 
658  // Delete faces
659  for(std::set<FaceHandle>::const_reverse_iterator f_it = incidentFaces_s.rbegin(),
660  f_end = incidentFaces_s.rend(); f_it != f_end; ++f_it) {
661  delete_face_core(*f_it);
662  }
663 
664  // Delete edge
665  return delete_edge_core(_h);
666 }
667 
668 //========================================================================================
669 
683 
684  assert(!is_deleted(_h));
685 
686  std::vector<FaceHandle> fs;
687  fs.push_back(_h);
688 
689  std::set<CellHandle> incidentCells_s;
690  get_incident_cells(fs, incidentCells_s);
691 
692  // Delete cells
693  for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
694  c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
695  delete_cell_core(*c_it);
696  }
697 
698  // Delete face
699  return delete_face_core(_h);
700 }
701 
702 //========================================================================================
703 
714 
715  assert(!is_deleted(_h));
716  return delete_cell_core(_h);
717 }
718 
723 {
724  if (!deferred_deletion_enabled() || !needs_garbage_collection())
725  return; // nothing todo
726 
727  deferred_deletion = false;
728 
729  for (int i = (int)n_cells(); i > 0; --i) {
730  if (is_deleted(CellHandle(i - 1))) {
731  cell_deleted_[i - 1] = false;
733  }
734  }
735  n_deleted_cells_ = 0;
736 
737  for (int i = (int)n_faces(); i > 0; --i) {
738  if (is_deleted(FaceHandle(i - 1))) {
739  face_deleted_[i - 1] = false;
741  }
742  }
743  n_deleted_faces_ = 0;
744 
745  for (int i = (int)n_edges(); i > 0; --i) {
746  if (is_deleted(EdgeHandle(i - 1))) {
747  edge_deleted_[i - 1] = false;
749  }
750  }
751  n_deleted_edges_ = 0;
752 
753  for (int i = (int)n_vertices(); i > 0; --i) {
754  if (is_deleted(VertexHandle(i - 1))) {
755  vertex_deleted_[i - 1] = false;
757  }
758  }
759  n_deleted_vertices_ = 0;
760 
761  deferred_deletion = true;
762 
763 }
764 
765 //========================================================================================
766 
767 template <class ContainerT>
768 void TopologyKernel::get_incident_edges(const ContainerT& _vs,
769  std::set<EdgeHandle>& _es) const {
770 
771  _es.clear();
772 
773  if(v_bottom_up_) {
774 
775  for(typename ContainerT::const_iterator v_it = _vs.begin(),
776  v_end = _vs.end(); v_it != v_end; ++v_it) {
777 
778  const std::vector<HalfEdgeHandle>& inc_hes = outgoing_hes_per_vertex_[v_it->idx()];
779 
780  for(std::vector<HalfEdgeHandle>::const_iterator he_it = inc_hes.begin(),
781  he_end = inc_hes.end(); he_it != he_end; ++he_it) {
782 
783  _es.insert(edge_handle(*he_it));
784  }
785  }
786  } else {
787 
788  for(typename ContainerT::const_iterator v_it = _vs.begin(),
789  v_end = _vs.end(); v_it != v_end; ++v_it) {
790 
791  for(EdgeIter e_it = edges_begin(), e_end = edges_end(); e_it != e_end; ++e_it) {
792 
793  const Edge& e = edge(*e_it);
794 
795  if(e.from_vertex() == *v_it || e.to_vertex() == *v_it) {
796  _es.insert(*e_it);
797  }
798  }
799  }
800  }
801 }
802 
803 //========================================================================================
804 
805 template <class ContainerT>
806 void TopologyKernel::get_incident_faces(const ContainerT& _es,
807  std::set<FaceHandle>& _fs) const {
808 
809  _fs.clear();
810 
811  if(e_bottom_up_) {
812 
813  for(typename ContainerT::const_iterator e_it = _es.begin(),
814  e_end = _es.end(); e_it != e_end; ++e_it) {
815 
816  for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(halfedge_handle(*e_it, 0));
817  hehf_it.valid(); ++hehf_it) {
818 
819  const FaceHandle fh = face_handle(*hehf_it);
820 
821  if(_fs.count(fh) == 0) {
822  _fs.insert(fh);
823  }
824  }
825  }
826  } else {
827 
828  for(typename ContainerT::const_iterator e_it = _es.begin(),
829  e_end = _es.end(); e_it != e_end; ++e_it) {
830 
831  for(FaceIter f_it = faces_begin(),
832  f_end = faces_end(); f_it != f_end; ++f_it) {
833 
834  const std::vector<HalfEdgeHandle>& hes = face(*f_it).halfedges();
835 
836  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
837  he_end = hes.end(); he_it != he_end; ++he_it) {
838 
839  if(edge_handle(*he_it) == *e_it) {
840  _fs.insert(*f_it);
841  break;
842  }
843  }
844  }
845  }
846  }
847 }
848 
849 //========================================================================================
850 
851 template <class ContainerT>
852 void TopologyKernel::get_incident_cells(const ContainerT& _fs,
853  std::set<CellHandle>& _cs) const {
854 
855  _cs.clear();
856 
857  if(f_bottom_up_) {
858 
859  for(typename ContainerT::const_iterator f_it = _fs.begin(),
860  f_end = _fs.end(); f_it != f_end; ++f_it) {
861 
862  const HalfFaceHandle hfh0 = halfface_handle(*f_it, 0);
863  const HalfFaceHandle hfh1 = halfface_handle(*f_it, 1);
864 
865  const CellHandle c0 = incident_cell(hfh0);
866  const CellHandle c1 = incident_cell(hfh1);
867 
868  if(c0.is_valid()) _cs.insert(c0);
869  if(c1.is_valid()) _cs.insert(c1);
870  }
871  } else {
872 
873  for(typename ContainerT::const_iterator f_it = _fs.begin(),
874  f_end = _fs.end(); f_it != f_end; ++f_it) {
875 
876  for(CellIter c_it = cells_begin(), c_end = cells_end();
877  c_it != c_end; ++c_it) {
878 
879  const std::vector<HalfFaceHandle>& hfs = cell(*c_it).halffaces();
880 
881  for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
882  hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
883 
884  if(face_handle(*hf_it) == *f_it) {
885  _cs.insert(*c_it);
886  break;
887  }
888  }
889  }
890  }
891  }
892 }
893 
894 //========================================================================================
895 
914 
915  VertexHandle h = _h;
916  assert(h.is_valid() && (size_t)h.idx() < n_vertices());
917 
918  if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last not deleted vertex
919  {
920  VertexHandle last_undeleted_vertex = VertexHandle((int)n_vertices()-1);
921  assert(!vertex_deleted_[last_undeleted_vertex.idx()]);
922  swap_vertex_indices(h, last_undeleted_vertex);
923  h = last_undeleted_vertex;
924  }
925 
926  if (deferred_deletion_enabled())
927  {
928  ++n_deleted_vertices_;
929  vertex_deleted_[h.idx()] = true;
930 // deleted_vertices_.push_back(h);
931 
932  // Iterator to next element in vertex list
933 // return (vertices_begin() + h.idx()+1);
934  return VertexIter(this, VertexHandle(h.idx()+1));
935  }
936  else
937  {
938  // 1)
939  if(v_bottom_up_) {
940 
941  // Decrease all vertex handles >= _h in all edge definitions
942  for(int i = h.idx(), end = (int)n_vertices(); i < end; ++i) {
943  const std::vector<HalfEdgeHandle>& hes = outgoing_hes_per_vertex_[i];
944  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
945  he_end = hes.end(); he_it != he_end; ++he_it) {
946 
947  Edge& e = edge(edge_handle(*he_it));
948  if(e.from_vertex().idx() == i) {
949  e.set_from_vertex(VertexHandle(i-1));
950  }
951  if(e.to_vertex().idx() == i) {
952  e.set_to_vertex(VertexHandle(i-1));
953  }
954  }
955  }
956 
957  } else {
958 
959  // Iterate over all edges
960  for(EdgeIter e_it = edges_begin(), e_end = edges_end();
961  e_it != e_end; ++e_it) {
962 
963  // Decrease all vertex handles in edge definitions that are greater than _h
964  if(edge(*e_it).from_vertex() > h) {
965  edge(*e_it).set_from_vertex(VertexHandle(edge(*e_it).from_vertex().idx() - 1));
966  }
967  if(edge(*e_it).to_vertex() > h) {
968  edge(*e_it).set_to_vertex(VertexHandle(edge(*e_it).to_vertex().idx() - 1));
969  }
970  }
971  }
972 
973  // 2)
974 
975  if(v_bottom_up_) {
976  assert((size_t)h.idx() < outgoing_hes_per_vertex_.size());
977  outgoing_hes_per_vertex_.erase(outgoing_hes_per_vertex_.begin() + h.idx());
978  }
979 
980 
981  // 3)
982 
983  --n_vertices_;
984  vertex_deleted_.erase(vertex_deleted_.begin() + h.idx());
985 
986  // 4)
987 
988  vertex_deleted(h);
989 
990  // Iterator to next element in vertex list
991 // return (vertices_begin() + h.idx());
992  return VertexIter(this, h);
993 
994  }
995 }
996 
997 //========================================================================================
998 
1019 
1020  EdgeHandle h = _h;
1021 
1022  assert(h.is_valid() && (size_t)h.idx() < edges_.size());
1023 
1024  if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last one
1025  {
1026  EdgeHandle last_edge = EdgeHandle((int)edges_.size()-1);
1027  assert(!edge_deleted_[last_edge.idx()]);
1028  swap_edge_indices(h, last_edge);
1029  h = last_edge;
1030  }
1031 
1032 
1033  // 1)
1034  if(v_bottom_up_) {
1035 
1036  VertexHandle v0 = edge(h).from_vertex();
1037  VertexHandle v1 = edge(h).to_vertex();
1038  assert(v0.is_valid() && (size_t)v0.idx() < outgoing_hes_per_vertex_.size());
1039  assert(v1.is_valid() && (size_t)v1.idx() < outgoing_hes_per_vertex_.size());
1040 
1041  outgoing_hes_per_vertex_[v0.idx()].erase(
1042  std::remove(outgoing_hes_per_vertex_[v0.idx()].begin(),
1043  outgoing_hes_per_vertex_[v0.idx()].end(),
1044  halfedge_handle(h, 0)),
1045  outgoing_hes_per_vertex_[v0.idx()].end());
1046 
1047  outgoing_hes_per_vertex_[v1.idx()].erase(
1048  std::remove(outgoing_hes_per_vertex_[v1.idx()].begin(),
1049  outgoing_hes_per_vertex_[v1.idx()].end(),
1050  halfedge_handle(h, 1)),
1051  outgoing_hes_per_vertex_[v1.idx()].end());
1052  }
1053 
1054  if (deferred_deletion_enabled())
1055  {
1056  ++n_deleted_edges_;
1057  edge_deleted_[h.idx()] = true;
1058 // deleted_edges_.push_back(h);
1059 
1060  // Return iterator to next element in list
1061 // return (edges_begin() + h.idx()+1);
1062  return EdgeIter(this, EdgeHandle(h.idx()+1));
1063  }
1064  else
1065  {
1066 
1067  if (!fast_deletion_enabled())
1068  {
1069  // 2)
1070  if(e_bottom_up_) {
1071 
1072  assert((size_t)halfedge_handle(h, 0).idx() < incident_hfs_per_he_.size());
1073 
1074  // Decrease all half-edge handles > he and
1075  // delete all half-edge handles == he in face definitions
1076  // Get all faces that need updates
1077  std::set<FaceHandle> update_faces;
1078  for(std::vector<std::vector<HalfFaceHandle> >::const_iterator iit =
1079  (incident_hfs_per_he_.begin() + halfedge_handle(h, 0).idx()),
1080  iit_end = incident_hfs_per_he_.end(); iit != iit_end; ++iit) {
1081  for(std::vector<HalfFaceHandle>::const_iterator it = iit->begin(),
1082  end = iit->end(); it != end; ++it) {
1083  update_faces.insert(face_handle(*it));
1084  }
1085  }
1086  // Update respective handles
1088  for(std::set<FaceHandle>::iterator f_it = update_faces.begin(),
1089  f_end = update_faces.end(); f_it != f_end; ++f_it) {
1090 
1091  std::vector<HalfEdgeHandle> hes = face(*f_it).halfedges();
1092 
1093  // Delete current half-edge from face's half-edge list
1094  hes.erase(std::remove(hes.begin(), hes.end(), halfedge_handle(h, 0)), hes.end());
1095  hes.erase(std::remove(hes.begin(), hes.end(), halfedge_handle(h, 1)), hes.end());
1096 
1097  #if defined(__clang_major__) && (__clang_major__ >= 5)
1098  for(std::vector<HalfEdgeHandle>::iterator it = hes.begin(), end = hes.end();
1099  it != end; ++it) {
1100  cor.correctValue(*it);
1101  }
1102  #else
1103  std::for_each(hes.begin(), hes.end(),
1104  fun::bind(&HEHandleCorrection::correctValue, &cor, fun::placeholders::_1));
1105  #endif
1106  face(*f_it).set_halfedges(hes);
1107  }
1108  } else {
1109 
1110  // Iterate over all faces
1111  for(FaceIter f_it = faces_begin(), f_end = faces_end();
1112  f_it != f_end; ++f_it) {
1113 
1114  // Get face's half-edges
1115  std::vector<HalfEdgeHandle> hes = face(*f_it).halfedges();
1116 
1117  // Delete current half-edge from face's half-edge list
1118  hes.erase(std::remove(hes.begin(), hes.end(), halfedge_handle(h, 0)), hes.end());
1119  hes.erase(std::remove(hes.begin(), hes.end(), halfedge_handle(h, 1)), hes.end());
1120 
1121  // Decrease all half-edge handles greater than _h in face
1123  #if defined(__clang_major__) && (__clang_major__ >= 5)
1124  for(std::vector<HalfEdgeHandle>::iterator it = hes.begin(), end = hes.end();
1125  it != end; ++it) {
1126  cor.correctValue(*it);
1127  }
1128  #else
1129  std::for_each(hes.begin(), hes.end(),
1130  fun::bind(&HEHandleCorrection::correctValue, &cor, fun::placeholders::_1));
1131  #endif
1132  face(*f_it).set_halfedges(hes);
1133  }
1134  }
1135  }
1136 
1137  // 3)
1138 
1139  if(e_bottom_up_) {
1140  assert((size_t)halfedge_handle(h, 1).idx() < incident_hfs_per_he_.size());
1141 
1142  incident_hfs_per_he_.erase(incident_hfs_per_he_.begin() + halfedge_handle(h, 1).idx());
1143  incident_hfs_per_he_.erase(incident_hfs_per_he_.begin() + halfedge_handle(h, 0).idx());
1144  }
1145 
1146  if (!fast_deletion_enabled())
1147  {
1148  // 4)
1149  if(v_bottom_up_) {
1151  #if defined(__clang_major__) && (__clang_major__ >= 5)
1152  for(std::vector<std::vector<HalfEdgeHandle> >::iterator it = outgoing_hes_per_vertex_.begin(),
1153  end = outgoing_hes_per_vertex_.end(); it != end; ++it) {
1154  cor.correctVecValue(*it);
1155  }
1156  #else
1157  std::for_each(outgoing_hes_per_vertex_.begin(),
1158  outgoing_hes_per_vertex_.end(),
1159  fun::bind(&HEHandleCorrection::correctVecValue, &cor, fun::placeholders::_1));
1160  #endif
1161  }
1162  }
1163 
1164 
1165  // 5)
1166  edges_.erase(edges_.begin() + h.idx());
1167  edge_deleted_.erase(edge_deleted_.begin() + h.idx());
1168 
1169 
1170  // 6)
1171 
1172  edge_deleted(h);
1173 
1174  // Return iterator to next element in list
1175 // return (edges_begin() + h.idx());
1176  return EdgeIter(this, h);
1177 
1178  }
1179 }
1180 
1181 //========================================================================================
1182 
1203 
1204  FaceHandle h = _h;
1205 
1206  assert(h.is_valid() && (size_t)h.idx() < faces_.size());
1207 
1208 
1209  if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last one
1210  {
1211  FaceHandle last_face = FaceHandle((int)faces_.size()-1);
1212  assert(!face_deleted_[last_face.idx()]);
1213  swap_face_indices(h, last_face);
1214  h = last_face;
1215  }
1216 
1217  // 1)
1218  if(e_bottom_up_) {
1219 
1220  const std::vector<HalfEdgeHandle>& hes = face(h).halfedges();
1221  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
1222  he_end = hes.end(); he_it != he_end; ++he_it) {
1223 
1224  assert((size_t)std::max(he_it->idx(), opposite_halfedge_handle(*he_it).idx()) < incident_hfs_per_he_.size());
1225 
1226  incident_hfs_per_he_[he_it->idx()].erase(
1227  std::remove(incident_hfs_per_he_[he_it->idx()].begin(),
1228  incident_hfs_per_he_[he_it->idx()].end(),
1229  halfface_handle(h, 0)), incident_hfs_per_he_[he_it->idx()].end());
1230 
1231 
1232  incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].erase(
1233  std::remove(incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].begin(),
1234  incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].end(),
1235  halfface_handle(h, 1)), incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].end());
1236 
1237  reorder_incident_halffaces(edge_handle(*he_it));
1238  }
1239  }
1240 
1241  if (deferred_deletion_enabled())
1242  {
1243  ++n_deleted_faces_;
1244  face_deleted_[h.idx()] = true;
1245 // deleted_faces_.push_back(h);
1246 
1247  // Return iterator to next element in list
1248 // return (faces_begin() + h.idx()+1);
1249  return FaceIter(this, FaceHandle(h.idx()+1));
1250  }
1251  else
1252  {
1253 
1254  if (!fast_deletion_enabled())
1255  {
1256  // 2)
1257  if(f_bottom_up_) {
1258 
1259  // Decrease all half-face handles > _h in all cells
1260  // and delete all half-face handles == _h
1261  std::set<CellHandle> update_cells;
1262  for(std::vector<CellHandle>::const_iterator c_it = (incident_cell_per_hf_.begin() + halfface_handle(h, 0).idx()),
1263  c_end = incident_cell_per_hf_.end(); c_it != c_end; ++c_it) {
1264  if(!c_it->is_valid()) continue;
1265  update_cells.insert(*c_it);
1266  }
1267  for(std::set<CellHandle>::const_iterator c_it = update_cells.begin(),
1268  c_end = update_cells.end(); c_it != c_end; ++c_it) {
1269 
1270  std::vector<HalfFaceHandle> hfs = cell(*c_it).halffaces();
1271 
1272  // Delete current half-faces from cell's half-face list
1273  hfs.erase(std::remove(hfs.begin(), hfs.end(), halfface_handle(h, 0)), hfs.end());
1274  hfs.erase(std::remove(hfs.begin(), hfs.end(), halfface_handle(h, 1)), hfs.end());
1275 
1277 #if defined(__clang_major__) && (__clang_major__ >= 5)
1278  for(std::vector<HalfFaceHandle>::iterator it = hfs.begin(),
1279  end = hfs.end(); it != end; ++it) {
1280  cor.correctValue(*it);
1281  }
1282 #else
1283  std::for_each(hfs.begin(), hfs.end(),
1284  fun::bind(&HFHandleCorrection::correctValue, &cor, fun::placeholders::_1));
1285 #endif
1286  cell(*c_it).set_halffaces(hfs);
1287  }
1288 
1289  } else {
1290 
1291  // Iterate over all cells
1292  for(CellIter c_it = cells_begin(), c_end = cells_end(); c_it != c_end; ++c_it) {
1293 
1294  std::vector<HalfFaceHandle> hfs = cell(*c_it).halffaces();
1295 
1296  // Delete current half-faces from cell's half-face list
1297  hfs.erase(std::remove(hfs.begin(), hfs.end(), halfface_handle(h, 0)), hfs.end());
1298  hfs.erase(std::remove(hfs.begin(), hfs.end(), halfface_handle(h, 1)), hfs.end());
1299 
1301 #if defined(__clang_major__) && (__clang_major__ >= 5)
1302  for(std::vector<HalfFaceHandle>::iterator it = hfs.begin(),
1303  end = hfs.end(); it != end; ++it) {
1304  cor.correctValue(*it);
1305  }
1306 #else
1307  std::for_each(hfs.begin(), hfs.end(),
1308  fun::bind(&HFHandleCorrection::correctValue, &cor, fun::placeholders::_1));
1309 #endif
1310  cell(*c_it).set_halffaces(hfs);
1311  }
1312  }
1313  }
1314 
1315 
1316  // 3)
1317  if(f_bottom_up_) {
1318  assert((size_t)halfface_handle(h, 1).idx() < incident_cell_per_hf_.size());
1319 
1320  incident_cell_per_hf_.erase(incident_cell_per_hf_.begin() + halfface_handle(h, 1).idx());
1321  incident_cell_per_hf_.erase(incident_cell_per_hf_.begin() + halfface_handle(h, 0).idx());
1322  }
1323 
1324 
1325  if (!fast_deletion_enabled())
1326  {
1327  // 4)
1328  if(e_bottom_up_) {
1330 #if defined(__clang_major__) && (__clang_major__ >= 5)
1331  for(std::vector<std::vector<HalfFaceHandle> >::iterator it = incident_hfs_per_he_.begin(), end = incident_hfs_per_he_.end(); it != end; ++it) {
1332  cor.correctVecValue(*it);
1333  }
1334 #else
1335  std::for_each(incident_hfs_per_he_.begin(),
1336  incident_hfs_per_he_.end(),
1337  fun::bind(&HFHandleCorrection::correctVecValue, &cor, fun::placeholders::_1));
1338 #endif
1339  }
1340  }
1341 
1342  // 5)
1343  faces_.erase(faces_.begin() + h.idx());
1344  face_deleted_.erase(face_deleted_.begin() + h.idx());
1345 
1346  // 6)
1347  face_deleted(h);
1348 
1349  // Return iterator to next element in list
1350 // return (faces_begin() + h.idx());
1351  return FaceIter(this, h);
1352  }
1353 
1354 }
1355 
1356 //========================================================================================
1357 
1374 
1375  CellHandle h = _h;
1376 
1377  assert(h.is_valid() && (size_t)h.idx() < cells_.size());
1378 
1379 
1380  if (fast_deletion_enabled() && !deferred_deletion_enabled()) // for fast deletion swap handle with last not deleted cell
1381  {
1382  CellHandle last_undeleted_cell = CellHandle((int)cells_.size()-1);
1383  assert(!cell_deleted_[last_undeleted_cell.idx()]);
1384  swap_cell_indices(h, last_undeleted_cell);
1385  h = last_undeleted_cell;
1386  }
1387 
1388 
1389  // 1)
1390  if(f_bottom_up_) {
1391  const std::vector<HalfFaceHandle>& hfs = cell(h).halffaces();
1392  for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
1393  hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
1394  assert((size_t)hf_it->idx() < incident_cell_per_hf_.size());
1395  if (incident_cell_per_hf_[hf_it->idx()] == h)
1396  incident_cell_per_hf_[hf_it->idx()] = InvalidCellHandle;
1397  }
1398  std::set<EdgeHandle> edges;
1399  for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
1400  hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
1401  const auto& hf = halfface(*hf_it);
1402  for (const auto& heh : hf.halfedges())
1403  edges.insert(edge_handle(heh));
1404  }
1405  for (auto eh : edges)
1406  reorder_incident_halffaces(eh);
1407  }
1408 
1409  if (deferred_deletion_enabled())
1410  {
1411  ++n_deleted_cells_;
1412  cell_deleted_[h.idx()] = true;
1413 // deleted_cells_.push_back(h);
1414 // deleted_cells_set.insert(h);
1415 
1416 // return (cells_begin() + h.idx()+1);
1417  return CellIter(this, CellHandle(h.idx()+1));
1418  }
1419  else
1420  {
1421  // 2)
1422  if (!fast_deletion_enabled())
1423  {
1424  if(f_bottom_up_) {
1425  CHandleCorrection cor(h);
1426 #if defined(__clang_major__) && (__clang_major__ >= 5)
1427  for(std::vector<CellHandle>::iterator it = incident_cell_per_hf_.begin(),
1428  end = incident_cell_per_hf_.end(); it != end; ++it) {
1429  cor.correctValue(*it);
1430  }
1431 #else
1432  std::for_each(incident_cell_per_hf_.begin(),
1433  incident_cell_per_hf_.end(),
1434  fun::bind(&CHandleCorrection::correctValue, &cor, fun::placeholders::_1));
1435 #endif
1436  }
1437  }
1438 
1439  // 3)
1440  cells_.erase(cells_.begin() + h.idx());
1441  cell_deleted_.erase(cell_deleted_.begin() + h.idx());
1442 
1443  // 4)
1444  cell_deleted(h);
1445 
1446  // return handle to original position
1447 // return (cells_begin() + h.idx()+1);
1448  return CellIter(this, h);
1449  }
1450 }
1451 
1453 {
1454  assert(_h1.idx() >= 0 && _h1.idx() < (int)cells_.size());
1455  assert(_h2.idx() >= 0 && _h2.idx() < (int)cells_.size());
1456 
1457  if (_h1 == _h2)
1458  return;
1459 
1460  int id1 = _h1.idx();
1461  int id2 = _h2.idx();
1462 
1463  Cell c1 = cells_[id1];
1464  Cell c2 = cells_[id2];
1465 
1466  // correct pointers to those cells
1467  std::vector<HalfFaceHandle> hfhs1 = c1.halffaces();
1468  for (unsigned int i = 0; i < hfhs1.size(); ++i)
1469  {
1470  HalfFaceHandle hfh = hfhs1[i];
1471  if (incident_cell_per_hf_[hfh.idx()] == _h1)
1472  incident_cell_per_hf_[hfh.idx()] = _h2;
1473  }
1474 
1475  std::vector<HalfFaceHandle> hfhs2 = c2.halffaces();
1476  for (unsigned int i = 0; i < hfhs2.size(); ++i)
1477  {
1478  HalfFaceHandle hfh = hfhs2[i];
1479  if (incident_cell_per_hf_[hfh.idx()] == _h2)
1480  incident_cell_per_hf_[hfh.idx()] = _h1;
1481  }
1482 
1483  // swap vector entries
1484  std::swap(cells_[id1], cells_[id2]);
1485  bool tmp = cell_deleted_[id1];
1486  cell_deleted_[id1] = cell_deleted_[id2];
1487  cell_deleted_[id2] = tmp;
1488  swap_cell_properties(_h1, _h2);
1489 }
1490 
1492 {
1493  assert(_h1.idx() >= 0 && _h1.idx() < (int)faces_.size());
1494  assert(_h2.idx() >= 0 && _h2.idx() < (int)faces_.size());
1495 
1496  if (_h1 == _h2)
1497  return;
1498 
1499 
1500  std::vector<unsigned int> ids;
1501  ids.push_back(_h1.idx());
1502  ids.push_back(_h2.idx());
1503 
1504  unsigned int id1 = _h1.idx();
1505  unsigned int id2 = _h2.idx();
1506 
1507  // correct pointers to those faces
1508 
1509  // correct cells that contain a swapped faces
1510  if (has_face_bottom_up_incidences())
1511  {
1512  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)
1513  for (unsigned int i = 0; i < 2; ++i) // For both swapped faces
1514  {
1515  unsigned int id = ids[i];
1516  for (unsigned int j = 0; j < 2; ++j) // for both halffaces
1517  {
1518  HalfFaceHandle hfh = HalfFaceHandle(2*id+j);
1519  CellHandle ch = incident_cell_per_hf_[hfh.idx()];
1520  if (!ch.is_valid())
1521  continue;
1522 
1523 
1524 
1525  if (processed_cells.find(ch.idx()) == processed_cells.end())
1526  {
1527 
1528  Cell& c = cells_[ch.idx()];
1529 
1530  // replace old halffaces with new halffaces where the ids are swapped
1531 
1532  std::vector<HalfFaceHandle> new_halffaces;
1533  for (unsigned int k = 0; k < c.halffaces().size(); ++k)
1534  if (c.halffaces()[k].idx()/2 == (int)id1) // if halfface belongs to swapped face
1535  new_halffaces.push_back(HalfFaceHandle(2 * id2 + (c.halffaces()[k].idx() % 2)));
1536  else if (c.halffaces()[k].idx()/2 == (int)id2) // if halfface belongs to swapped face
1537  new_halffaces.push_back(HalfFaceHandle(2 * id1 + (c.halffaces()[k].idx() % 2)));
1538  else
1539  new_halffaces.push_back(c.halffaces()[k]);
1540  c.set_halffaces(new_halffaces);
1541 
1542  processed_cells.insert(ch.idx());
1543  }
1544  }
1545  }
1546  }
1547  else
1548  {
1549  // serach for all cells that contain a swapped face
1550  for (unsigned int i = 0; i < cells_.size(); ++i)
1551  {
1552  Cell& c = cells_[i];
1553 
1554  // check if c contains a swapped face
1555  bool contains_swapped_face = false;
1556  for (unsigned int k = 0; k < c.halffaces().size(); ++k)
1557  {
1558  if (c.halffaces()[k].idx()/2 == (int)id1)
1559  contains_swapped_face = true;
1560  if (c.halffaces()[k].idx()/2 == (int)id2)
1561  contains_swapped_face = true;
1562  if (contains_swapped_face)
1563  break;
1564  }
1565 
1566  if (contains_swapped_face)
1567  {
1568  // replace old halffaces with new halffaces where the ids are swapped
1569  std::vector<HalfFaceHandle> new_halffaces;
1570  for (unsigned int k = 0; k < c.halffaces().size(); ++k)
1571  if (c.halffaces()[k].idx()/2 == (int)id1) // if halfface belongs to swapped face
1572  new_halffaces.push_back(HalfFaceHandle(2 * id2 + (c.halffaces()[k].idx() % 2)));
1573  else if (c.halffaces()[k].idx()/2 == (int)id2) // if halfface belongs to swapped face
1574  new_halffaces.push_back(HalfFaceHandle(2 * id1 + (c.halffaces()[k].idx() % 2)));
1575  else
1576  new_halffaces.push_back(c.halffaces()[k]);
1577  c.set_halffaces(new_halffaces);
1578  }
1579  }
1580  }
1581 
1582  // correct bottom up indices
1583 
1584  if (has_edge_bottom_up_incidences())
1585  {
1586  std::set<HalfEdgeHandle> processed_halfedges; // to ensure ids are only swapped once (in the case that a halfedge is incident to both swapped faces)
1587  for (unsigned int i = 0; i < 2; ++i) // For both swapped faces
1588  {
1589  unsigned int id = ids[i];
1590  for (unsigned int j = 0; j < 2; ++j) // for both halffaces
1591  {
1592  HalfFaceHandle hfh = HalfFaceHandle(2*id+j);
1593  Face hf = halfface(hfh);
1594 
1595  for (unsigned int k = 0; k < hf.halfedges().size(); ++k)
1596  {
1597  HalfEdgeHandle heh = hf.halfedges()[k];
1598 
1599  if (processed_halfedges.find(heh) != processed_halfedges.end())
1600  continue;
1601 
1602  std::vector<HalfFaceHandle>& incident_halffaces = incident_hfs_per_he_[heh.idx()];
1603  for (unsigned int l = 0; l < incident_halffaces.size(); ++l)
1604  {
1605  HalfFaceHandle& hfh2 = incident_halffaces[l];
1606 
1607  if (hfh2.idx()/2 == (int)id1) // if halfface belongs to swapped face
1608  hfh2 = HalfFaceHandle(2 * id2 + (hfh2.idx() % 2));
1609  else if (hfh2.idx()/2 == (int)id2) // if halfface belongs to swapped face
1610  hfh2 = HalfFaceHandle(2 * id1 + (hfh2.idx() % 2));
1611  }
1612 
1613  processed_halfedges.insert(heh);
1614  }
1615  }
1616  }
1617  }
1618 
1619  // swap vector entries
1620  std::swap(faces_[ids[0]], faces_[ids[1]]);
1621  bool tmp = face_deleted_[ids[0]];
1622  face_deleted_[ids[0]] = face_deleted_[ids[1]];
1623  face_deleted_[ids[1]] = tmp;
1624  std::swap(incident_cell_per_hf_[2*ids[0]+0], incident_cell_per_hf_[2*ids[1]+0]);
1625  std::swap(incident_cell_per_hf_[2*ids[0]+1], incident_cell_per_hf_[2*ids[1]+1]);
1626  swap_face_properties(_h1, _h2);
1627  swap_halfface_properties(halfface_handle(_h1, 0), halfface_handle(_h2, 0));
1628  swap_halfface_properties(halfface_handle(_h1, 1), halfface_handle(_h2, 1));
1629 
1630 }
1631 
1633 {
1634  assert(_h1.idx() >= 0 && _h1.idx() < (int)edges_.size());
1635  assert(_h2.idx() >= 0 && _h2.idx() < (int)edges_.size());
1636 
1637  if (_h1 == _h2)
1638  return;
1639 
1640  std::vector<unsigned int> ids;
1641  ids.push_back(_h1.idx());
1642  ids.push_back(_h2.idx());
1643 
1644 
1645  // correct pointers to those edges
1646 
1647  if (has_edge_bottom_up_incidences())
1648  {
1649  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)
1650 
1651  for (unsigned int i = 0; i < 2; ++i) // For both swapped edges
1652  {
1653  HalfEdgeHandle heh = HalfEdgeHandle(2*ids[i]);
1654 
1655 
1656  std::vector<HalfFaceHandle>& incident_halffaces = incident_hfs_per_he_[heh.idx()];
1657  for (unsigned int j = 0; j < incident_halffaces.size(); ++j) // for each incident halfface
1658  {
1659  HalfFaceHandle hfh = incident_halffaces[j];
1660 
1661  unsigned int f_id = hfh.idx() / 2;
1662 
1663  if (processed_faces.find(f_id) == processed_faces.end())
1664  {
1665 
1666  Face& f = faces_[f_id];
1667 
1668  // replace old incident halfedges with new incident halfedges where the ids are swapped
1669  std::vector<HalfEdgeHandle> new_halfedges;
1670  for (unsigned int k = 0; k < f.halfedges().size(); ++k)
1671  {
1672  HalfEdgeHandle heh2 = f.halfedges()[k];
1673  if (heh2.idx() / 2 == (int)ids[0])
1674  new_halfedges.push_back(HalfEdgeHandle(2*ids[1] + (heh2.idx() % 2)));
1675  else if (heh2.idx() / 2 == (int)ids[1])
1676  new_halfedges.push_back(HalfEdgeHandle(2*ids[0] + (heh2.idx() % 2)));
1677  else
1678  new_halfedges.push_back(heh2);
1679  }
1680  f.set_halfedges(new_halfedges);
1681 
1682  processed_faces.insert(f_id);
1683  }
1684  }
1685  }
1686  }
1687  else
1688  {
1689  // search for all faces that contain one of the swapped edges
1690  for (unsigned int i = 0; i < faces_.size(); ++i)
1691  {
1692  Face& f = faces_[i];
1693 
1694  // check if f contains a swapped edge
1695  bool contains_swapped_edge = false;
1696  for (unsigned int k = 0; k < f.halfedges().size(); ++k)
1697  {
1698  if (f.halfedges()[k].idx()/2 == (int)ids[0])
1699  contains_swapped_edge = true;
1700  if (f.halfedges()[k].idx()/2 == (int)ids[1])
1701  contains_swapped_edge = true;
1702  if (contains_swapped_edge)
1703  break;
1704  }
1705 
1706  if (contains_swapped_edge)
1707  {
1708  // replace old incident halfedges with new incident halfedges where the ids are swapped
1709  std::vector<HalfEdgeHandle> new_halfedges;
1710  for (unsigned int k = 0; k < f.halfedges().size(); ++k)
1711  {
1712  HalfEdgeHandle heh2 = f.halfedges()[k];
1713  if (heh2.idx() / 2 == (int)ids[0])
1714  new_halfedges.push_back(HalfEdgeHandle(2*ids[1] + (heh2.idx() % 2)));
1715  else if (heh2.idx() / 2 == (int)ids[1])
1716  new_halfedges.push_back(HalfEdgeHandle(2*ids[0] + (heh2.idx() % 2)));
1717  else
1718  new_halfedges.push_back(heh2);
1719  }
1720  f.set_halfedges(new_halfedges);
1721  }
1722  }
1723  }
1724 
1725  // correct bottom up incidences
1726 
1727  if (has_vertex_bottom_up_incidences())
1728  {
1729  std::set<VertexHandle> processed_vertices;
1730  for (unsigned int i = 0; i < 2; ++i) // For both swapped edges
1731  {
1732  Edge e = edge(EdgeHandle(ids[i]));
1733  std::vector<VertexHandle> vhs;
1734  vhs.push_back(e.from_vertex());
1735  vhs.push_back(e.to_vertex());
1736 
1737  for (unsigned int j = 0; j < 2; ++j) // for both incident vertices
1738  {
1739  if (processed_vertices.find(vhs[j]) != processed_vertices.end())
1740  continue;
1741 
1742  std::vector<HalfEdgeHandle>& outgoing_hes = outgoing_hes_per_vertex_[vhs[j].idx()];
1743  for (unsigned int k = 0; k < outgoing_hes.size(); ++k)
1744  {
1745  HalfEdgeHandle& heh = outgoing_hes[k];
1746  if (heh.idx() / 2 == (int)ids[0])
1747  heh = HalfEdgeHandle(2 * ids[1] + (heh.idx() % 2));
1748  else if (heh.idx() / 2 == (int)ids[1])
1749  heh = HalfEdgeHandle(2 * ids[0] + (heh.idx() % 2));
1750  }
1751  processed_vertices.insert(vhs[j]);
1752  }
1753 
1754  }
1755  }
1756 
1757  // swap vector entries
1758  std::swap(edges_[ids[0]], edges_[ids[1]]);
1759  bool tmp = edge_deleted_[ids[0]];
1760  edge_deleted_[ids[0]] = edge_deleted_[ids[1]];
1761  edge_deleted_[ids[1]] = tmp;
1762  std::swap(incident_hfs_per_he_[2*ids[0]+0], incident_hfs_per_he_[2*ids[1]+0]);
1763  std::swap(incident_hfs_per_he_[2*ids[0]+1], incident_hfs_per_he_[2*ids[1]+1]);
1764  swap_edge_properties(_h1, _h2);
1765  swap_halfedge_properties(halfedge_handle(_h1, 0), halfedge_handle(_h2, 0));
1766  swap_halfedge_properties(halfedge_handle(_h1, 1), halfedge_handle(_h2, 1));
1767 
1768 }
1769 
1771 {
1772  assert(_h1.idx() >= 0 && _h1.idx() < (int)n_vertices_);
1773  assert(_h2.idx() >= 0 && _h2.idx() < (int)n_vertices_);
1774 
1775  if (_h1 == _h2)
1776  return;
1777 
1778  std::vector<unsigned int> ids;
1779  ids.push_back(_h1.idx());
1780  ids.push_back(_h2.idx());
1781 
1782 
1783  // correct pointers to those vertices
1784 
1785  if (has_vertex_bottom_up_incidences())
1786  {
1787  for (unsigned int i = 0; i < 2; ++i) // For both swapped vertices
1788  {
1789  std::set<unsigned int> processed_edges; // to ensure ids are only swapped once (in the case that the two swapped vertices are connected by an edge)
1790  std::vector<HalfEdgeHandle>& outgoing_hes = outgoing_hes_per_vertex_[ids[i]];
1791  for (unsigned int k = 0; k < outgoing_hes.size(); ++k) // for each outgoing halfedge
1792  {
1793  unsigned int e_id = outgoing_hes[k].idx() / 2;
1794 
1795  if (processed_edges.find(e_id) == processed_edges.end())
1796  {
1797  Edge& e = edges_[e_id];
1798  if (e.from_vertex().idx() == (int)ids[0])
1799  e.set_from_vertex(VertexHandle(ids[1]));
1800  else if (e.from_vertex().idx() == (int)ids[1])
1801  e.set_from_vertex(VertexHandle(ids[0]));
1802 
1803  if (e.to_vertex().idx() == (int)ids[0])
1804  e.set_to_vertex(VertexHandle(ids[1]));
1805  else if (e.to_vertex().idx() == (int)ids[1])
1806  e.set_to_vertex(VertexHandle(ids[0]));
1807 
1808  processed_edges.insert(e_id);
1809  }
1810  }
1811  }
1812 
1813  }
1814  else
1815  {
1816  // search for all edges containing a swapped vertex
1817 
1818  for (unsigned int i = 0; i < edges_.size(); ++i)
1819  {
1820  Edge& e = edges_[i];
1821  if (e.from_vertex().idx() == (int)ids[0])
1822  e.set_from_vertex(VertexHandle(ids[1]));
1823  else if (e.from_vertex().idx() == (int)ids[1])
1824  e.set_from_vertex(VertexHandle(ids[0]));
1825 
1826  if (e.to_vertex().idx() == (int)ids[0])
1827  e.set_to_vertex(VertexHandle(ids[1]));
1828  else if (e.to_vertex().idx() == (int)ids[1])
1829  e.set_to_vertex(VertexHandle(ids[0]));
1830  }
1831  }
1832 
1833  // swap vector entries
1834  bool tmp = vertex_deleted_[ids[0]];
1835  vertex_deleted_[ids[0]] = vertex_deleted_[ids[1]];
1836  vertex_deleted_[ids[1]] = tmp;
1837  std::swap(outgoing_hes_per_vertex_[ids[0]], outgoing_hes_per_vertex_[ids[1]]);
1838  swap_vertex_properties(_h1, _h2);
1839 }
1840 
1841 //========================================================================================
1842 
1843 void TopologyKernel::delete_multiple_vertices(const std::vector<bool>& _tag) {
1844 
1845  assert(_tag.size() == n_vertices());
1846 
1847  std::vector<int> newIndices(n_vertices(), -1);
1848  int curIdx = 0;
1849 
1850  std::vector<int>::iterator idx_it = newIndices.begin();
1851  for(std::vector<bool>::const_iterator t_it = _tag.begin(),
1852  t_end = _tag.end(); t_it != t_end; ++t_it, ++idx_it) {
1853 
1854  if(!(*t_it)) {
1855  // Not marked as deleted
1856  *idx_it = curIdx;
1857  ++curIdx;
1858  } else {
1859  --n_vertices_;
1860  }
1861  }
1862 
1863  // Delete properties accordingly
1864  delete_multiple_vertex_props(_tag);
1865 
1866  EdgeCorrector corrector(newIndices);
1867  std::for_each(edges_.begin(), edges_.end(), corrector);
1868 }
1869 
1870 //========================================================================================
1871 
1872 void TopologyKernel::delete_multiple_edges(const std::vector<bool>& _tag) {
1873 
1874  assert(_tag.size() == n_edges());
1875 
1876  std::vector<int> newIndices(n_edges(), -1);
1877  int curIdx = 0;
1878 
1879  std::vector<Edge> newEdges;
1880 
1881  std::vector<int>::iterator idx_it = newIndices.begin();
1882  std::vector<Edge>::const_iterator e_it = edges_.begin();
1883 
1884  for(std::vector<bool>::const_iterator t_it = _tag.begin(),
1885  t_end = _tag.end(); t_it != t_end; ++t_it, ++idx_it, ++e_it) {
1886 
1887  if(!(*t_it)) {
1888  // Not marked as deleted
1889 
1890  newEdges.push_back(*e_it);
1891 
1892  *idx_it = curIdx;
1893  ++curIdx;
1894  }
1895  }
1896 
1897  // Swap edges
1898  edges_.swap(newEdges);
1899 
1900  // Delete properties accordingly
1901  delete_multiple_edge_props(_tag);
1902 
1903  FaceCorrector corrector(newIndices);
1904  std::for_each(faces_.begin(), faces_.end(), corrector);
1905 }
1906 
1907 //========================================================================================
1908 
1909 void TopologyKernel::delete_multiple_faces(const std::vector<bool>& _tag) {
1910 
1911  assert(_tag.size() == n_faces());
1912 
1913  std::vector<int> newIndices(n_faces(), -1);
1914  int curIdx = 0;
1915 
1916  std::vector<Face> newFaces;
1917 
1918  std::vector<int>::iterator idx_it = newIndices.begin();
1919  std::vector<Face>::const_iterator f_it = faces_.begin();
1920 
1921  for(std::vector<bool>::const_iterator t_it = _tag.begin(),
1922  t_end = _tag.end(); t_it != t_end; ++t_it, ++idx_it, ++f_it) {
1923 
1924  if(!(*t_it)) {
1925  // Not marked as deleted
1926 
1927  newFaces.push_back(*f_it);
1928 
1929  *idx_it = curIdx;
1930  ++curIdx;
1931  }
1932  }
1933 
1934  // Swap faces
1935  faces_.swap(newFaces);
1936 
1937  // Delete properties accordingly
1938  delete_multiple_face_props(_tag);
1939 
1940  CellCorrector corrector(newIndices);
1941  std::for_each(cells_.begin(), cells_.end(), corrector);
1942 }
1943 
1944 //========================================================================================
1945 
1946 void TopologyKernel::delete_multiple_cells(const std::vector<bool>& _tag) {
1947 
1948  assert(_tag.size() == n_cells());
1949 
1950  std::vector<Cell> newCells;
1951 
1952  std::vector<Cell>::const_iterator c_it = cells_.begin();
1953 
1954  for(std::vector<bool>::const_iterator t_it = _tag.begin(),
1955  t_end = _tag.end(); t_it != t_end; ++t_it, ++c_it) {
1956 
1957  if(!(*t_it)) {
1958  // Not marked as deleted
1959 
1960  newCells.push_back(*c_it);
1961  }
1962  }
1963 
1964  // Swap cells
1965  cells_.swap(newCells);
1966 
1967  // Delete properties accordingly
1968  delete_multiple_cell_props(_tag);
1969 }
1970 
1971 //========================================================================================
1972 
1973 // cppcheck-suppress unusedFunction ; public interface
1975 
1976  assert(_first >= cells_begin());
1977  assert(_last <= cells_end());
1978 
1979  std::vector<Cell>::iterator it = cells_.erase(cells_.begin() + _first->idx(), cells_.begin() + _last->idx());
1980 
1981  // Re-compute face bottom-up incidences if necessary
1982  if(f_bottom_up_) {
1983  f_bottom_up_ = false;
1984  enable_face_bottom_up_incidences(true);
1985  }
1986 
1987  return CellIter(this, CellHandle((int)(it - cells_.begin())));
1988 }
1989 
1990 void TopologyKernel::enable_deferred_deletion(bool _enable)
1991 {
1992  if (deferred_deletion && !_enable)
1993  collect_garbage();
1994 
1995  deferred_deletion = _enable;
1996 }
1997 
1998 //========================================================================================
1999 
2001 const OpenVolumeMeshEdge& TopologyKernel::edge(const EdgeHandle& _edgeHandle) const {
2002 
2003  // Test if edge is valid
2004  assert(_edgeHandle.is_valid() && (size_t)_edgeHandle.idx() < edges_.size());
2005 
2006  return edges_[_edgeHandle.idx()];
2007 }
2008 
2009 //========================================================================================
2010 
2012 const OpenVolumeMeshFace& TopologyKernel::face(const FaceHandle& _faceHandle) const {
2013 
2014  // Test if face is valid
2015  assert(_faceHandle.is_valid() && (size_t)_faceHandle.idx() < faces_.size());
2016 
2017  return faces_[_faceHandle.idx()];
2018 }
2019 
2020 //========================================================================================
2021 
2023 const OpenVolumeMeshCell& TopologyKernel::cell(const CellHandle& _cellHandle) const {
2024 
2025  // Test if cell is valid
2026  assert(_cellHandle.is_valid() && (size_t)_cellHandle.idx() < cells_.size());
2027 
2028  return cells_[_cellHandle.idx()];
2029 }
2030 
2031 //========================================================================================
2032 
2035 
2036  // Test if edge is valid
2037  assert(_edgeHandle.is_valid() && (size_t)_edgeHandle.idx() < edges_.size());
2038 
2039  return edges_[_edgeHandle.idx()];
2040 }
2041 
2042 //========================================================================================
2043 
2046 
2047  // Test if face is valid
2048  assert((size_t)_faceHandle.idx() < faces_.size());
2049  assert(_faceHandle.idx() >= 0);
2050 
2051  return faces_[_faceHandle.idx()];
2052 }
2053 
2054 //========================================================================================
2055 
2058 
2059  // Test if cell is valid
2060  assert((size_t)_cellHandle.idx() < cells_.size());
2061  assert(_cellHandle.idx() >= 0);
2062 
2063  return cells_[_cellHandle.idx()];
2064 }
2065 
2066 //========================================================================================
2067 
2070 
2071  // Is handle in range?
2072  assert((size_t)_halfEdgeHandle.idx() < (edges_.size() * 2));
2073  assert(_halfEdgeHandle.idx() >= 0);
2074 
2075  // In case the handle is even, just return the corresponding edge
2077  if(_halfEdgeHandle.idx() % 2 == 0)
2078  return edges_[(int)(_halfEdgeHandle.idx() / 2)];
2079  else
2080  return opposite_halfedge(edges_[(int)(_halfEdgeHandle.idx() / 2)]);
2081 }
2082 
2083 //========================================================================================
2084 
2087 
2088  // Is handle in range?
2089  assert((size_t)_halfFaceHandle.idx() < (faces_.size() * 2));
2090  assert(_halfFaceHandle.idx() >= 0);
2091 
2092  // In case the handle is even, just return the corresponding face
2093  // Otherwise return the opposite halfface via opposite()
2094  if(_halfFaceHandle.idx() % 2 == 0)
2095  return faces_[(int)(_halfFaceHandle.idx() / 2)];
2096  else
2097  return opposite_halfface(faces_[(int)(_halfFaceHandle.idx() / 2)]);
2098 }
2099 
2100 //========================================================================================
2101 
2104 
2105  // Is handle in range?
2106  assert(_halfEdgeHandle.idx() >= 0);
2107  assert((size_t)_halfEdgeHandle.idx() < (edges_.size() * 2));
2108 
2109  // In case the handle is not even, just return the corresponding edge
2110  // Otherwise return the opposite halfedge via opposite()
2111  if(_halfEdgeHandle.idx() % 2 != 0)
2112  return edges_[(int)(_halfEdgeHandle.idx() / 2)];
2113  else
2114  return opposite_halfedge(edges_[(int)(_halfEdgeHandle.idx() / 2)]);
2115 }
2116 
2117 //========================================================================================
2118 
2121 
2122  // Is handle in range?
2123  assert(_halfFaceHandle.idx() >= 0);
2124  assert((size_t)_halfFaceHandle.idx() < (faces_.size() * 2));
2125 
2126  // In case the handle is not even, just return the corresponding face
2127  // Otherwise return the opposite via the first face's opposite() function
2128  if(_halfFaceHandle.idx() % 2 != 0)
2129  return faces_[(int)(_halfFaceHandle.idx() / 2)];
2130  else
2131  return opposite_halfface(faces_[(int)(_halfFaceHandle.idx() / 2)]);
2132 }
2133 
2134 //========================================================================================
2135 
2137 
2138  assert(_vh1.idx() < (int)n_vertices());
2139  assert(_vh2.idx() < (int)n_vertices());
2140 
2141  for(VertexOHalfEdgeIter voh_it = voh_iter(_vh1); voh_it.valid(); ++voh_it) {
2142  if(halfedge(*voh_it).to_vertex() == _vh2) {
2143  return *voh_it;
2144  }
2145  }
2146 
2147  return InvalidHalfEdgeHandle;
2148 }
2149 
2150 //========================================================================================
2151 
2152 HalfFaceHandle TopologyKernel::halfface(const std::vector<VertexHandle>& _vs) const {
2153 
2154  assert(_vs.size() > 2);
2155 
2156  VertexHandle v0 = _vs[0], v1 = _vs[1], v2 = _vs[2];
2157 
2158  assert(v0.is_valid() && v1.is_valid() && v2.is_valid());
2159 
2160  HalfEdgeHandle he0 = halfedge(v0, v1);
2161  if(!he0.is_valid()) return InvalidHalfFaceHandle;
2162  HalfEdgeHandle he1 = halfedge(v1, v2);
2163  if(!he1.is_valid()) return InvalidHalfFaceHandle;
2164 
2165  std::vector<HalfEdgeHandle> hes;
2166  hes.push_back(he0);
2167  hes.push_back(he1);
2168 
2169  return halfface(hes);
2170 }
2171 
2172 HalfFaceHandle TopologyKernel::halfface_extensive(const std::vector<VertexHandle>& _vs) const
2173 {
2174  //TODO: schöner machen
2175 
2176  assert(_vs.size() > 2);
2177 
2178  VertexHandle v0 = _vs[0];
2179  VertexHandle v1 = _vs[1];
2180 
2181  assert(v0.is_valid() && v1.is_valid());
2182 
2183  HalfEdgeHandle he0 = halfedge(v0, v1);
2184  if(!he0.is_valid()) return InvalidHalfFaceHandle;
2185 
2186  for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(he0); hehf_it.valid(); ++hehf_it)
2187  {
2188  std::vector<HalfEdgeHandle> hes = halfface(*hehf_it).halfedges();
2189 
2190  if (hes.size() != _vs.size())
2191  continue;
2192 
2193  int offset = 0;
2194  for (unsigned int i = 0; i < hes.size(); ++i)
2195  if (hes[i] == he0)
2196  offset = i;
2197 
2198  bool all_vertices_found = true;
2199 
2200  for (unsigned int i = 0; i < hes.size(); ++i)
2201  {
2202  HalfEdgeHandle heh = hes[(i+offset)%hes.size()];
2203  if (halfedge(heh).from_vertex() != _vs[i])
2204  {
2205  all_vertices_found = false;
2206  break;
2207  }
2208  }
2209 
2210  if (all_vertices_found)
2211  return *hehf_it;
2212  }
2213 
2214  return InvalidHalfFaceHandle;
2215 }
2216 
2217 //========================================================================================
2218 
2219 HalfFaceHandle TopologyKernel::halfface(const std::vector<HalfEdgeHandle>& _hes) const {
2220 
2221  assert(_hes.size() >= 2);
2222 
2223  HalfEdgeHandle he0 = _hes[0], he1 = _hes[1];
2224 
2225  assert(he0.is_valid() && he1.is_valid());
2226 
2227  for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(he0); hehf_it.valid(); ++hehf_it) {
2228 
2229  std::vector<HalfEdgeHandle> hes = halfface(*hehf_it).halfedges();
2230  if(std::find(hes.begin(), hes.end(), he1) != hes.end()) {
2231  return *hehf_it;
2232  }
2233  }
2234 
2235  return InvalidHalfFaceHandle;
2236 }
2237 
2238 //========================================================================================
2239 
2241 
2242  assert(_heh.is_valid() && (size_t)_heh.idx() < edges_.size() * 2u);
2243  assert(_hfh.is_valid() && (size_t)_hfh.idx() < faces_.size() * 2u);
2244 
2245  std::vector<HalfEdgeHandle> hes = halfface(_hfh).halfedges();
2246 
2247  for(std::vector<HalfEdgeHandle>::const_iterator it = hes.begin();
2248  it != hes.end(); ++it) {
2249  if(*it == _heh) {
2250  if((it + 1) != hes.end()) return *(it + 1);
2251  else return *hes.begin();
2252  }
2253  }
2254 
2255  return InvalidHalfEdgeHandle;
2256 }
2257 
2258 //========================================================================================
2259 
2261 
2262  assert(_heh.is_valid() && (size_t)_heh.idx() < edges_.size() * 2u);
2263  assert(_hfh.is_valid() && (size_t)_hfh.idx() < faces_.size() * 2u);
2264 
2265  std::vector<HalfEdgeHandle> hes = halfface(_hfh).halfedges();
2266 
2267  for(std::vector<HalfEdgeHandle>::const_iterator it = hes.begin();
2268  it != hes.end(); ++it) {
2269  if(*it == _heh) {
2270  if(it != hes.begin()) return *(it - 1);
2271  else return *(hes.end() - 1);
2272  }
2273  }
2274 
2275  return InvalidHalfEdgeHandle;
2276 }
2277 
2278 //========================================================================================
2279 
2281 TopologyKernel::adjacent_halfface_in_cell(const HalfFaceHandle& _halfFaceHandle, const HalfEdgeHandle& _halfEdgeHandle) const {
2282 
2283  assert(_halfFaceHandle.is_valid() && (size_t)_halfFaceHandle.idx() < faces_.size() * 2u);
2284  assert(_halfEdgeHandle.is_valid() && (size_t)_halfEdgeHandle.idx() < edges_.size() * 2u);
2285  assert(has_face_bottom_up_incidences());
2286  assert((size_t)_halfFaceHandle.idx() < incident_cell_per_hf_.size());
2287 
2288  if(incident_cell_per_hf_[_halfFaceHandle.idx()] == InvalidCellHandle) {
2289  // Specified halfface is on the outside of the complex
2290  return InvalidHalfFaceHandle;
2291  }
2292 
2293  OpenVolumeMeshCell c = cell(incident_cell_per_hf_[_halfFaceHandle.idx()]);
2294 
2295  // Make sure that _halfFaceHandle is incident to _halfEdgeHandle
2296  bool skipped = false;
2297  bool found = false;
2298  HalfFaceHandle idx = InvalidHalfFaceHandle;
2299  for(std::vector<HalfFaceHandle>::const_iterator hf_it = c.halffaces().begin();
2300  hf_it != c.halffaces().end(); ++hf_it) {
2301 
2302  if(*hf_it == _halfFaceHandle) {
2303  skipped = true;
2304  continue;
2305  }
2306 
2307  OpenVolumeMeshFace hf = halfface(*hf_it);
2308  for(std::vector<HalfEdgeHandle>::const_iterator he_it = hf.halfedges().begin();
2309  he_it != hf.halfedges().end(); ++he_it) {
2310 
2311  if(edge_handle(*he_it) == edge_handle(_halfEdgeHandle)) {
2312  found = true;
2313  idx = *hf_it;
2314  }
2315  if(skipped && found) break;
2316  }
2317  if(skipped && found) break;
2318  }
2319  return ((skipped && found) ? idx : InvalidHalfFaceHandle);
2320 }
2321 
2322 //========================================================================================
2323 
2325 
2326  if(!has_face_bottom_up_incidences()) {
2327  return InvalidCellHandle;
2328  }
2329  if((size_t)_halfFaceHandle.idx() >= incident_cell_per_hf_.size() || _halfFaceHandle.idx() < 0) {
2330  return InvalidCellHandle;
2331  }
2332 
2333  return incident_cell_per_hf_[_halfFaceHandle.idx()];
2334 }
2335 
2336 //========================================================================================
2337 
2338 void TopologyKernel::compute_vertex_bottom_up_incidences() {
2339 
2340  // Clear incidences
2341  outgoing_hes_per_vertex_.clear();
2342  outgoing_hes_per_vertex_.resize(n_vertices());
2343 
2344  // Store outgoing halfedges per vertex
2345  int n_edges = (int)edges_.size();
2346  for(int i = 0; i < n_edges; ++i) {
2347  if (edge_deleted_[i])
2348  continue;
2349 
2350  VertexHandle from = edges_[i].from_vertex();
2351  // If this condition is not fulfilled, it is out of caller's control and
2352  // definitely our bug, therefore an assert
2353  assert((size_t)from.idx() < outgoing_hes_per_vertex_.size());
2354 
2355  outgoing_hes_per_vertex_[from.idx()].push_back(halfedge_handle(EdgeHandle(i), 0));
2356 
2357  VertexHandle to = edges_[i].to_vertex();
2358  assert((size_t)to.idx() < outgoing_hes_per_vertex_.size());
2359 
2360  // Store opposite halfedge handle
2361  outgoing_hes_per_vertex_[to.idx()].push_back(halfedge_handle(EdgeHandle(i), 1));
2362  }
2363 }
2364 
2365 //========================================================================================
2366 
2367 void TopologyKernel::compute_edge_bottom_up_incidences() {
2368 
2369  // Clear
2370  incident_hfs_per_he_.clear();
2371  incident_hfs_per_he_.resize(edges_.size() * 2u);
2372 
2373  // Store incident halffaces per halfedge
2374  int n_faces = (int)faces_.size();
2375  for(int i = 0; i < n_faces; ++i) {
2376  if (face_deleted_[i])
2377  continue;
2378 
2379  std::vector<HalfEdgeHandle> halfedges = faces_[i].halfedges();
2380 
2381  // Go over all halfedges
2382  for(std::vector<HalfEdgeHandle>::const_iterator he_it = halfedges.begin();
2383  he_it != halfedges.end(); ++he_it) {
2384 
2385  incident_hfs_per_he_[he_it->idx()].push_back(halfface_handle(FaceHandle(i), 0));
2386  incident_hfs_per_he_[opposite_halfedge_handle(*he_it).idx()].push_back(
2387  halfface_handle(FaceHandle(i), 1));
2388  }
2389  }
2390 }
2391 
2392 //========================================================================================
2393 
2394 void 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  int n_cells = (int)cells_.size();
2401  for(int i = 0; i < n_cells; ++i) {
2402  if (cell_deleted_[i])
2403  continue;
2404 
2405  std::vector<HalfFaceHandle> halffaces = cells_[i].halffaces();
2406 
2407  // Go over all halffaces
2408  for(std::vector<HalfFaceHandle>::const_iterator hf_it = halffaces.begin();
2409  hf_it != halffaces.end(); ++hf_it) {
2410 
2411  if(incident_cell_per_hf_[hf_it->idx()] == InvalidCellHandle) {
2412 
2413  incident_cell_per_hf_[hf_it->idx()] = CellHandle(i);
2414 
2415  } else {
2416 
2417 #ifndef NDEBUG
2418  std::cerr << "compute_face_bottom_up_incidences(): Detected non-three-manifold configuration!" << std::endl;
2419  std::cerr << "Connectivity probably won't work." << std::endl;
2420 #endif
2421  continue;
2422  }
2423  }
2424  }
2425 }
2426 
2427 } // Namespace OpenVolumeMesh
void resize_cprops(size_t _nc)
Change size of stored cell properties.
virtual VertexHandle add_vertex()
Add abstract vertex.
virtual void swap_vertex_indices(VertexHandle _h1, VertexHandle _h2)
Exchanges the indices of two vertices while keeping the mesh otherwise unaffected.
virtual FaceHandle add_face(const std::vector< HalfEdgeHandle > &_halfedges, bool _topologyCheck=false)
Add face via incident edges.
size_t n_edges() const override
Get number of edges in mesh.
const Face & face(const FaceHandle &_faceHandle) const
Get face with handle _faceHandle.
virtual CellIter delete_cell(const CellHandle &_h)
Delete cell from mesh.
size_t n_cells() const override
Get number of cells in mesh.
void resize_eprops(size_t _ne)
Change size of stored edge properties.
CellHandle incident_cell(const HalfFaceHandle &_halfFaceHandle) const
Get cell that is incident to the given halfface.
virtual void swap_edge_indices(EdgeHandle _h1, EdgeHandle _h2)
Exchanges the indices of two edges while keeping the mesh otherwise unaffected.
CellIter delete_cell_core(const CellHandle &_h)
Delete cell from mesh.
FaceIter delete_face_core(const FaceHandle &_h)
Delete face from mesh.
virtual EdgeHandle add_edge(const VertexHandle &_fromVertex, const VertexHandle &_toHandle, bool _allowDuplicates=false)
Add edge.
virtual EdgeIter delete_edge(const EdgeHandle &_h)
Delete edge from mesh.
static EdgeHandle edge_handle(const HalfEdgeHandle &_h)
Handle conversion.
HalfFaceHandle adjacent_halfface_in_cell(const HalfFaceHandle &_halfFaceHandle, const HalfEdgeHandle &_halfEdgeHandle) const
Get halfface that is adjacent (w.r.t. a common halfedge) within the same cell.
EdgeIter delete_edge_core(const EdgeHandle &_h)
Delete edge from mesh.
static HalfFaceHandle halfface_handle(const FaceHandle &_h, const unsigned char _subIdx)
Conversion function.
HalfEdgeHandle prev_halfedge_in_halfface(const HalfEdgeHandle &_heh, const HalfFaceHandle &_hfh) const
Get previous halfedge within a halfface.
size_t n_faces() const override
Get number of faces in mesh.
HalfEdgeHandle next_halfedge_in_halfface(const HalfEdgeHandle &_heh, const HalfFaceHandle &_hfh) const
Get next halfedge within a halfface.
size_t n_vertices() const override
Get number of vertices in mesh.
Face halfface(const HalfFaceHandle &_halfFaceHandle) const
Get face that corresponds to halfface with handle _halfFaceHandle.
void set_cell(const CellHandle &_ch, const std::vector< HalfFaceHandle > &_hfs)
Set the half-faces of a cell.
virtual VertexIter delete_vertex(const VertexHandle &_h)
Delete vertex from mesh.
virtual CellHandle add_cell(const std::vector< HalfFaceHandle > &_halffaces, bool _topologyCheck=false)
Add cell via incident halffaces.
void resize_fprops(size_t _nf)
Change size of stored face properties.
Edge opposite_halfedge(const HalfEdgeHandle &_halfEdgeHandle) const
Get opposite halfedge that corresponds to halfedge with handle _halfEdgeHandle.
bool bind(osg::GeometryPtr &_geo, Mesh &_mesh)
Definition: bindT.hh:101
Edge halfedge(const HalfEdgeHandle &_halfEdgeHandle) const
Get edge that corresponds to halfedge with handle _halfEdgeHandle.
virtual FaceIter delete_face(const FaceHandle &_h)
Delete face from mesh.
virtual void swap_face_indices(FaceHandle _h1, FaceHandle _h2)
Exchanges the indices of two faces while keeping the mesh otherwise unaffected.
const Cell & cell(const CellHandle &_cellHandle) const
Get cell with handle _cellHandle.
virtual void collect_garbage()
Delete all entities that are marked as deleted.
HalfFaceHandle halfface_extensive(const std::vector< VertexHandle > &_vs) const
VertexIter delete_vertex_core(const VertexHandle &_h)
Delete vertex from mesh.
virtual void swap_cell_indices(CellHandle _h1, CellHandle _h2)
Exchanges the indices of two cells while keeping the mesh otherwise unaffected.
CellIter delete_cell_range(const CellIter &_first, const CellIter &_last)
Delete range of cells.
size_t n_halffaces() const override
Get number of halffaces in mesh.
const Edge & edge(const EdgeHandle &_edgeHandle) const
Get edge with handle _edgeHandle.
Face opposite_halfface(const HalfFaceHandle &_halfFaceHandle) const
Get opposite halfface that corresponds to halfface with handle _halfFaceHandle.
void resize_vprops(size_t _nv)
Change size of stored vertex properties.
static HalfEdgeHandle halfedge_handle(const EdgeHandle &_h, const unsigned char _subIdx)
Conversion function.
size_t n_halfedges() const override
Get number of halfedges in mesh.
void set_face(const FaceHandle &_fh, const std::vector< HalfEdgeHandle > &_hes)
Set the half-edges of a face.
void set_edge(const EdgeHandle &_eh, const VertexHandle &_fromVertex, const VertexHandle &_toVertex)
Set the vertices of an edge.