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