36#include <OpenVolumeMesh/Attribs/StatusAttrib.hh>
38#include <OpenVolumeMesh/Core/TopologyKernel.hh>
39#include <OpenVolumeMesh/Core/Properties/PropertyPtr.hh>
43namespace OpenVolumeMesh {
46template<
typename std_API_Container_VHandlePointer,
47 typename std_API_Container_HHandlePointer,
48 typename std_API_Container_HFHandlePointer,
49 typename std_API_Container_CHandlePointer>
51 std_API_Container_HHandlePointer & hh_to_update,
52 std_API_Container_HFHandlePointer & hfh_to_update,
53 std_API_Container_CHandlePointer & ch_to_update,
54 bool _preserveManifoldness)
56 const auto &status = *
this;
57 auto def = kernel_->deferred_deletion_enabled();
58 kernel_->enable_deferred_deletion(
true);
59 for (
const auto vh: kernel_->vertices()) {
60 if (status[vh].deleted()) {
64 for (
const auto eh: kernel_->edges()) {
65 if (status[eh].deleted() && !kernel_->is_deleted(eh)) {
69 for (
const auto fh: kernel_->faces()) {
70 if (status[fh].deleted() && !kernel_->is_deleted(fh)) {
74 for (
const auto ch: kernel_->cells()) {
75 if (status[ch].deleted() && !kernel_->is_deleted(ch)) {
81 if (_preserveManifoldness) {
82 kernel_->enable_bottom_up_incidences(
true);
83 for (
const auto fh: kernel_->faces()) {
88 for (
const auto eh: kernel_->edges()) {
89 if (kernel_->
valence(eh) == 0) {
93 for (
const auto vh: kernel_->vertices()) {
94 if (kernel_->
valence(vh) == 0) {
99 if (!vh_to_update.empty()
100 || !hh_to_update.empty()
101 || !hfh_to_update.empty()
102 || !ch_to_update.empty())
104 auto nv =
static_cast<int>(kernel_->
n_vertices());
105 auto nhe =
static_cast<int>(kernel_->
n_halfedges());
106 auto nhf =
static_cast<int>(kernel_->
n_halffaces());
107 auto nc =
static_cast<int>(kernel_->
n_cells());
109 auto old_vh = kernel_->request_vertex_property<
int>();
110 for (
int i = 0; i < nv; ++i) { old_vh[
VertexHandle(i)] = i; }
111 auto old_heh = kernel_->request_halfedge_property<
int>();
113 auto old_hfh = kernel_->request_halfface_property<
int>();
115 auto old_ch = kernel_->request_cell_property<
int>();
116 for (
int i = 0; i < nc; ++i) { old_ch[
CellHandle(i)] = i; }
120 std::vector<VertexHandle> new_vh; new_vh.resize(nv);
121 std::vector<CellHandle> new_ch; new_ch.resize(nc);
122 std::vector<HalfEdgeHandle> new_heh; new_heh.resize(nhe);
123 std::vector<HalfFaceHandle> new_hfh; new_hfh.resize(nhf);
125 for (
const auto vh: kernel_->vertices()) { new_vh[old_vh[vh]] = vh; }
126 for (
const auto heh: kernel_->halfedges()) { new_heh[old_heh[heh]] = heh; }
127 for (
const auto hfh: kernel_->halffaces()) { new_hfh[old_hfh[hfh]] = hfh; }
128 for (
const auto ch: kernel_->cells()) { new_ch[old_ch[ch]] = ch; }
130 for (
auto *vh: vh_to_update) {
if (vh->is_valid()) *vh = new_vh[vh->idx()]; }
131 for (
auto *heh: hh_to_update) {
if (heh->is_valid()) *heh = new_heh[heh->idx()]; }
132 for (
auto *hfh: hfh_to_update) {
if (hfh->is_valid()) *hfh = new_hfh[hfh->idx()]; }
133 for (
auto *ch: ch_to_update) {
if (ch->is_valid()) *ch = new_ch[ch->idx()]; }
139 kernel_->enable_deferred_deletion(def);
160 bool track_vh = !vh_to_update.empty();
161 bool track_hh = !hh_to_update.empty();
162 bool track_hfh = !hfh_to_update.empty();
163 bool track_ch = !ch_to_update.empty();
169 std::map<int,int> vh_map;
170 std::map<int,int> hh_map;
171 std::map<int,int> hfh_map;
172 std::map<int,int> ch_map;
176 typename std_API_Container_VHandlePointer::iterator it = vh_to_update.begin();
177 typename std_API_Container_VHandlePointer::iterator end = vh_to_update.end();
179 for (; it != end; ++it) {
180 vh_map[(*it)->idx()] = (*it)->idx();
184 typename std_API_Container_HHandlePointer::iterator it = hh_to_update.begin();
185 typename std_API_Container_HHandlePointer::iterator end = hh_to_update.end();
187 for (; it != end; ++it) {
188 hh_map[(*it)->idx()] = (*it)->idx();
192 typename std_API_Container_HFHandlePointer::iterator it = hfh_to_update.begin();
193 typename std_API_Container_HFHandlePointer::iterator end = hfh_to_update.end();
195 for (; it != end; ++it) {
196 hfh_map[(*it)->idx()] = (*it)->idx();
200 typename std_API_Container_CHandlePointer::iterator it = ch_to_update.begin();
201 typename std_API_Container_CHandlePointer::iterator end = ch_to_update.end();
203 for (; it != end; ++it) {
204 ch_map[(*it)->idx()] = (*it)->idx();
210 mark_higher_dim_entities();
212 std::vector<int> vertexIndexMap(kernel_->
n_vertices(), -1);
215 bool v_bu = kernel_->has_vertex_bottom_up_incidences();
216 bool e_bu = kernel_->has_edge_bottom_up_incidences();
217 bool f_bu = kernel_->has_face_bottom_up_incidences();
219 kernel_->enable_bottom_up_incidences(
false);
221 std::vector<bool> tags(kernel_->
n_cells(),
false);
222 std::vector<bool>::iterator tag_it = tags.begin();
224 for(
CellIter c_it = kernel_->cells_begin(); c_it != kernel_->cells_end(); ++c_it, ++tag_it) {
225 *tag_it = c_status_[*c_it].deleted();
228 if (c_status_[*c_it].deleted()) {
230 auto it = ch_map.find(c_it->idx());
231 if (it != ch_map.end()) {
235 auto it = ch_map.find(c_it->idx());
236 if (it != ch_map.end()) {
237 it->second = c_it->idx() - offset_ch;
242 kernel_->delete_multiple_cells(tags);
244 tags.resize(kernel_->
n_faces(),
false);
245 tag_it = tags.begin();
247 for(
FaceIter f_it = kernel_->faces_begin(); f_it != kernel_->faces_end(); ++f_it, ++tag_it) {
248 *tag_it = f_status_[*f_it].deleted();
251 int halfface_idx = f_it->idx() * 2;
252 if (f_status_[*f_it].deleted()) {
254 auto it = hfh_map.find(halfface_idx);
255 if (it != hfh_map.end()) {
258 it = hfh_map.find(halfface_idx + 1);
259 if (it != hfh_map.end()) {
263 auto it = hfh_map.find(halfface_idx);
264 if (it != hfh_map.end()) {
265 it->second = halfface_idx - offset_hfh;
267 it = hfh_map.find(halfface_idx + 1);
268 if (it != hfh_map.end()) {
269 it->second = halfface_idx + 1 - offset_hfh;
274 kernel_->delete_multiple_faces(tags);
276 tags.resize(kernel_->
n_edges(),
false);
277 tag_it = tags.begin();
279 for(
EdgeIter e_it = kernel_->edges_begin(); e_it != kernel_->edges_end(); ++e_it, ++tag_it) {
280 *tag_it = e_status_[*e_it].deleted();
283 int halfedge_idx = e_it->idx() * 2;
284 if (e_status_[*e_it].deleted()) {
286 auto it = hh_map.find(halfedge_idx);
287 if (it != hh_map.end()) {
290 it = hh_map.find(halfedge_idx + 1);
291 if (it != hh_map.end()) {
295 auto it = hh_map.find(halfedge_idx);
296 if (it != hh_map.end()) {
297 it->second = halfedge_idx - offset_hh;
299 it = hh_map.find(halfedge_idx + 1);
300 if (it != hh_map.end()) {
301 it->second = halfedge_idx + 1 - offset_hh;
306 kernel_->delete_multiple_edges(tags);
309 tag_it = tags.begin();
311 for(
VertexIter v_it = kernel_->vertices_begin(); v_it != kernel_->vertices_end(); ++v_it, ++tag_it) {
312 *tag_it = v_status_[*v_it].deleted();
315 if (v_status_[*v_it].deleted()) {
316 auto it = vh_map.find(v_it->idx());
317 if (it != vh_map.end()) {
322 if (vh_map.find(v_it->idx()) != vh_map.end()) {
323 vh_map[v_it->idx()] = v_it->idx() - offset_vh;
328 kernel_->delete_multiple_vertices(tags);
332 typename std_API_Container_VHandlePointer::iterator it = vh_to_update.begin();
333 typename std_API_Container_VHandlePointer::iterator end = vh_to_update.end();
335 for (; it != end; ++it) {
340 typename std_API_Container_HHandlePointer::iterator it = hh_to_update.begin();
341 typename std_API_Container_HHandlePointer::iterator end = hh_to_update.end();
343 for (; it != end; ++it) {
348 typename std_API_Container_HFHandlePointer::iterator it = hfh_to_update.begin();
349 typename std_API_Container_HFHandlePointer::iterator end = hfh_to_update.end();
351 for (; it != end; ++it) {
356 typename std_API_Container_CHandlePointer::iterator it = ch_to_update.begin();
357 typename std_API_Container_CHandlePointer::iterator end = ch_to_update.end();
359 for (; it != end; ++it) {
366 if(v_bu) kernel_->enable_vertex_bottom_up_incidences(
true);
367 if(e_bu) kernel_->enable_edge_bottom_up_incidences(
true);
368 if(f_bu) kernel_->enable_face_bottom_up_incidences(
true);
371 if(_preserveManifoldness) {
372 if(kernel_->has_full_bottom_up_incidences()) {
376 for(
FaceIter f_it = kernel_->faces_begin(); f_it != kernel_->faces_end(); ++f_it) {
383 if(kernel_->
incident_cell(hf0) == TopologyKernel::InvalidCellHandle &&
384 kernel_->
incident_cell(hf1) == TopologyKernel::InvalidCellHandle) {
386 f_status_[*f_it].set_deleted(
true);
392 for(
EdgeIter e_it = kernel_->edges_begin(); e_it != kernel_->edges_end(); ++e_it) {
400 if(!hehf_it.valid()) {
402 e_status_[*e_it].set_deleted(
true);
405 bool validFace =
false;
406 for(; hehf_it.valid(); ++hehf_it) {
407 if(!f_status_[kernel_->face_handle(*hehf_it)].deleted()) {
413 e_status_[*e_it].set_deleted(
true);
420 for(
VertexIter v_it = kernel_->vertices_begin(); v_it != kernel_->vertices_end(); ++v_it) {
425 if(!voh_it.valid()) {
427 v_status_[*v_it].set_deleted(
true);
430 bool validEdge =
false;
431 for(; voh_it.valid(); ++voh_it) {
432 if(!e_status_[kernel_->
edge_handle(*voh_it)].deleted()) {
438 v_status_[*v_it].set_deleted(
true);
448 std::cerr <<
"Preservation of three-manifoldness in garbage_collection() "
449 <<
"requires bottom-up incidences!" << std::endl;
void garbage_collection(bool _preserveManifoldness=false)
Delete all entities that have been marked as deleted.
size_t valence(VertexHandle _vh) const
Get valence of vertex (number of incident edges)
virtual VertexIter delete_vertex(VertexHandle _h)
Delete vertex from mesh.
CellHandle incident_cell(HalfFaceHandle _halfFaceHandle) const
Get cell that is incident to the given halfface.
size_t n_halfedges() const override
Get number of halfedges in mesh.
static HalfEdgeHandle halfedge_handle(EdgeHandle _h, const unsigned char _subIdx)
Conversion function.
virtual CellIter delete_cell(CellHandle _h)
Delete cell from mesh.
static EdgeHandle edge_handle(HalfEdgeHandle _h)
Handle conversion.
size_t n_vertices() const override
Get number of vertices in mesh.
virtual FaceIter delete_face(FaceHandle _h)
Delete face from mesh.
static HalfFaceHandle halfface_handle(FaceHandle _h, const unsigned char _subIdx)
Conversion function.
size_t n_faces() const override
Get number of faces in mesh.
size_t n_cells() const override
Get number of cells in mesh.
size_t n_edges() const override
Get number of edges in mesh.
virtual EdgeIter delete_edge(EdgeHandle _h)
Delete edge from mesh.
size_t n_halffaces() const override
Get number of halffaces in mesh.
virtual void collect_garbage()
Delete all entities that are marked as deleted.