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