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