42#include <OpenVolumeMesh/Core/TopologyKernel.hh>
43#include <OpenVolumeMesh/Core/detail/swap_bool.hh>
45namespace OpenVolumeMesh {
49const VertexHandle TopologyKernel::InvalidVertexHandle = VertexHandle(-1);
50const EdgeHandle TopologyKernel::InvalidEdgeHandle = EdgeHandle(-1);
51const HalfEdgeHandle TopologyKernel::InvalidHalfEdgeHandle = HalfEdgeHandle(-1);
52const FaceHandle TopologyKernel::InvalidFaceHandle = FaceHandle(-1);
53const HalfFaceHandle TopologyKernel::InvalidHalfFaceHandle = HalfFaceHandle(-1);
54const CellHandle TopologyKernel::InvalidCellHandle = CellHandle(-1);
58void TopologyKernel::reserve_vertices(
size_t n)
60 ResourceManager::reserve_vprops(
n);
61 vertex_deleted_.reserve(
n);
64void TopologyKernel::reserve_edges(
size_t n)
66 ResourceManager::reserve_eprops(
n);
68 edge_deleted_.reserve(
n);
71void TopologyKernel::reserve_faces(
size_t n)
73 ResourceManager::reserve_fprops(
n);
75 face_deleted_.reserve(
n);
78void TopologyKernel::reserve_cells(
size_t n)
80 ResourceManager::reserve_cprops(
n);
82 cell_deleted_.reserve(
n);
85void TopologyKernel::add_n_vertices(
size_t n)
89 vertex_deleted_.resize(n_vertices_,
false);
90 if(has_vertex_bottom_up_incidences()) {
91 outgoing_hes_per_vertex_.resize(n_vertices_);
98 vertex_deleted_.push_back(
false);
101 if(has_vertex_bottom_up_incidences()) {
102 outgoing_hes_per_vertex_.resize(n_vertices_);
117 bool _allowDuplicates) {
121 assert(_fromVertex.is_valid() && (
size_t)_fromVertex.idx() <
n_vertices() && !is_deleted(_fromVertex));
122 assert(_toVertex.is_valid() && (
size_t)_toVertex.idx() <
n_vertices() && !is_deleted(_toVertex));
125 if(!_allowDuplicates) {
126 if(has_vertex_bottom_up_incidences()) {
128 assert((
size_t)_fromVertex.idx() < outgoing_hes_per_vertex_.size());
129 std::vector<HalfEdgeHandle>& ohes = outgoing_hes_per_vertex_[_fromVertex];
130 for(std::vector<HalfEdgeHandle>::const_iterator he_it = ohes.begin(),
131 he_end = ohes.end(); he_it != he_end; ++he_it) {
132 if(
halfedge(*he_it).to_vertex() == _toVertex) {
137 for(
int i = 0; i < (int)edges_.size(); ++i) {
148 edges_.emplace_back(_fromVertex, _toVertex);
149 edge_deleted_.push_back(
false);
156 if(has_vertex_bottom_up_incidences()) {
157 assert((
size_t)_fromVertex.idx() < outgoing_hes_per_vertex_.size());
158 assert((
size_t)_toVertex.idx() < outgoing_hes_per_vertex_.size());
160 outgoing_hes_per_vertex_[_fromVertex].push_back(
halfedge_handle(eh, 0));
165 if(has_edge_bottom_up_incidences()) {
180 for(std::vector<HalfEdgeHandle>::const_iterator it = _halfedges.begin(),
181 end = _halfedges.end(); it != end; ++it)
182 assert(it->is_valid() && (size_t)it->idx() < edges_.size() * 2u && !is_deleted(*it));
187 for (
size_t i = 0; i + 1< _halfedges.size(); ++i) {
189 return InvalidFaceHandle;
193 return InvalidFaceHandle;
199 faces_.emplace_back(std::move(_halfedges));
200 face_deleted_.push_back(
false);
209 if(has_edge_bottom_up_incidences()) {
211 for (
const auto heh: face_halfedges(fh)) {
212 auto opp = opposite_halfedge_handle(heh);
214 assert((
size_t)heh.idx() < incident_hfs_per_he_.size());
215 assert((
size_t)opp.idx() < incident_hfs_per_he_.size());
223 if(has_face_bottom_up_incidences()) {
224 incident_cell_per_hf_.resize(
n_halffaces(), InvalidCellHandle);
241 for(std::vector<VertexHandle>::const_iterator it = _vertices.begin(),
242 end = _vertices.end(); it != end; ++it)
243 assert(it->is_valid() && (size_t)it->idx() <
n_vertices() && !is_deleted(*it));
247 std::vector<HalfEdgeHandle> halfedges;
248 std::vector<VertexHandle>::const_iterator it = _vertices.begin();
249 std::vector<VertexHandle>::const_iterator end = _vertices.end();
250 for(; (it+1) != end; ++it) {
255 char swap =
edge(e_idx).to_vertex() == *it;
260 char swap =
edge(e_idx).to_vertex() == *it;
293 assert((
size_t)heh.idx() < incident_hfs_per_he_.size());
294 auto &incident_hfs = incident_hfs_per_he_[heh];
296 const size_t n_hfs = incident_hfs.size();
301 std::vector<HalfFaceHandle> new_halffaces;
302 new_halffaces.reserve(n_hfs);
305 auto start_hf = incident_hfs.front();
306 auto cur_hf = start_hf;
310 new_halffaces.push_back(cur_hf);
311 if (new_halffaces.size() > incident_hfs.size()) {
321 if(cur_hf == InvalidHalfFaceHandle) {
324 cur_hf = opposite_halfface_handle(cur_hf);
326 }
while (cur_hf != start_hf);
333 if(new_halffaces.size() != incident_hfs.size()) {
336 cur_heh = opposite_halfedge_handle(heh);
339 cur_hf = opposite_halfface_handle(cur_hf);
348 if (cur_hf == InvalidHalfFaceHandle) {
353 new_halffaces.insert(new_halffaces.begin(), cur_hf);
354 if(new_halffaces.size() > incident_hfs.size()) {
362 if(new_halffaces.size() == incident_hfs.size()) {
363 incident_hfs = std::move(new_halffaces);
365 std::transform(incident_hfs.rbegin(), incident_hfs.rend(),
366 incident_hfs_per_he_[opposite_halfedge_handle(heh)].begin(),
367 opposite_halfface_handle);
371 std::cerr <<
"reorder_incident_halffaces: found " << new_halffaces.size() <<
" of " << incident_hfs.size()
372 <<
" incident halffaces, likely the edge has more than one boundary! Currently not supported, not reordering." << std::endl;
384 for(std::vector<HalfFaceHandle>::const_iterator it = _halffaces.begin(),
385 end = _halffaces.end(); it != end; ++it)
386 assert(it->is_valid() && ((size_t)it->idx() < faces_.size() * 2u) && !is_deleted(*it));
399 std::vector<HalfEdgeHandle> incidentHalfedges;
400 size_t guess_n_halfedges = _halffaces.size() *
valence(face_handle(_halffaces[0]));
403 incidentHalfedges.reserve(2 * guess_n_halfedges);
405 for (
const auto &hfh: _halffaces) {
406 const auto &hes =
face(face_handle(hfh)).halfedges();
407 if ((hfh.idx() & 1) == 0) {
408 std::copy(hes.begin(), hes.end(),
409 std::back_inserter(incidentHalfedges));
411 std::transform(hes.rbegin(),
413 std::back_inserter(incidentHalfedges),
414 opposite_halfedge_handle);
417 std::sort(incidentHalfedges.begin(), incidentHalfedges.end());
418 auto duplicate = std::adjacent_find(incidentHalfedges.begin(), incidentHalfedges.end());
419 if (duplicate != incidentHalfedges.end()) {
421 std::cerr <<
"add_cell(): Halfedge #" << duplicate->idx() <<
" is contained in more than 1 halfface." << std::endl;
423 return InvalidCellHandle;
426 auto e_end = std::unique(incidentHalfedges.begin(), incidentHalfedges.end(),
428 auto n_edges =
static_cast<size_t>(std::distance(incidentHalfedges.begin(), e_end));
432 std::cerr <<
"add_cell(): The specified half-faces are not connected!" << std::endl;
434 return InvalidCellHandle;
440 cells_.emplace_back(std::move(_halffaces));
441 cell_deleted_.push_back(
false);
449 if(has_face_bottom_up_incidences()) {
451 const auto &cell_halffaces = cells_[ch].halffaces();
452 std::set<EdgeHandle> cell_edges;
453 for(
const auto &hfh: cell_halffaces) {
454 assert((
size_t)hfh.idx() < incident_cell_per_hf_.size());
458 if(incident_cell_per_hf_[hfh] != InvalidCellHandle) {
464 std::cerr <<
"add_cell(): One of the specified half-faces is already incident to another cell!" << std::endl;
470 incident_cell_per_hf_[hfh] = ch;
473 for(
const auto &eh: face_edges(face_handle(hfh))) {
474 cell_edges.insert(eh);
478 if(has_edge_bottom_up_incidences()) {
484 for (
const auto &eh: cell_edges) {
499 assert(_fromVertex.is_valid() && (
size_t)_fromVertex.idx() <
n_vertices() && !is_deleted(_fromVertex));
500 assert(_toVertex.is_valid() && (
size_t)_toVertex.idx() <
n_vertices() && !is_deleted(_toVertex));
505 if(has_vertex_bottom_up_incidences()) {
513 std::vector<HalfEdgeHandle>::iterator h_end =
514 std::remove(outgoing_hes_per_vertex_[fv].begin(), outgoing_hes_per_vertex_[fv].end(), heh0);
515 outgoing_hes_per_vertex_[fv].resize(h_end - outgoing_hes_per_vertex_[fv].begin());
517 h_end = std::remove(outgoing_hes_per_vertex_[tv].begin(), outgoing_hes_per_vertex_[tv].end(), heh1);
518 outgoing_hes_per_vertex_[tv].resize(h_end - outgoing_hes_per_vertex_[tv].begin());
520 outgoing_hes_per_vertex_[_fromVertex].push_back(heh0);
521 outgoing_hes_per_vertex_[_toVertex].push_back(heh1);
524 e.set_from_vertex(_fromVertex);
525 e.set_to_vertex(_toVertex);
536 if(has_edge_bottom_up_incidences()) {
541 const std::vector<HalfEdgeHandle>& hes = f.halfedges();
543 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
544 he_end = hes.end(); he_it != he_end; ++he_it) {
546 std::vector<HalfFaceHandle>::iterator h_end =
547 std::remove(incident_hfs_per_he_[*he_it].begin(),
548 incident_hfs_per_he_[*he_it].end(), hf0);
549 incident_hfs_per_he_[*he_it].resize(h_end - incident_hfs_per_he_[*he_it].begin());
551 h_end = std::remove(incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin(),
552 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end(), hf1);
553 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].resize(h_end - incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin());
556 for(std::vector<HalfEdgeHandle>::const_iterator he_it = _hes.begin(),
557 he_end = _hes.end(); he_it != he_end; ++he_it) {
559 incident_hfs_per_he_[*he_it].push_back(hf0);
560 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].push_back(hf1);
566 f.set_halfedges(_hes);
577 if(has_face_bottom_up_incidences()) {
579 const std::vector<HalfFaceHandle>& hfs = c.halffaces();
580 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
581 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
583 incident_cell_per_hf_[*hf_it] = InvalidCellHandle;
586 for(std::vector<HalfFaceHandle>::const_iterator hf_it = _hfs.begin(),
587 hf_end = _hfs.end(); hf_it != hf_end; ++hf_it) {
589 incident_cell_per_hf_[*hf_it] = _ch;
593 c.set_halffaces(_hfs);
612 assert(!is_deleted(_h));
614 std::vector<VertexHandle> vs;
617 std::set<EdgeHandle> incidentEdges_s;
618 get_incident_edges(vs, incidentEdges_s);
620 std::set<FaceHandle> incidentFaces_s;
621 get_incident_faces(incidentEdges_s, incidentFaces_s);
623 std::set<CellHandle> incidentCells_s;
624 get_incident_cells(incidentFaces_s, incidentCells_s);
627 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
628 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
633 for(std::set<FaceHandle>::const_reverse_iterator f_it = incidentFaces_s.rbegin(),
634 f_end = incidentFaces_s.rend(); f_it != f_end; ++f_it) {
639 for(std::set<EdgeHandle>::const_reverse_iterator e_it = incidentEdges_s.rbegin(),
640 e_end = incidentEdges_s.rend(); e_it != e_end; ++e_it) {
664 assert(!is_deleted(_h));
666 std::vector<EdgeHandle> es;
669 std::set<FaceHandle> incidentFaces_s;
670 get_incident_faces(es, incidentFaces_s);
672 std::set<CellHandle> incidentCells_s;
673 get_incident_cells(incidentFaces_s, incidentCells_s);
676 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
677 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
682 for(std::set<FaceHandle>::const_reverse_iterator f_it = incidentFaces_s.rbegin(),
683 f_end = incidentFaces_s.rend(); f_it != f_end; ++f_it) {
707 assert(!is_deleted(_h));
709 std::vector<FaceHandle> fs;
712 std::set<CellHandle> incidentCells_s;
713 get_incident_cells(fs, incidentCells_s);
716 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
717 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
738 assert(!is_deleted(_h));
747 if (!deferred_deletion_enabled() || !needs_garbage_collection())
750 deferred_deletion_ =
false;
752 for (
int i = (
int)
n_cells(); i > 0; --i) {
754 if (is_deleted(ch)) {
755 cell_deleted_[ch] =
false;
759 n_deleted_cells_ = 0;
761 for (
int i = (
int)
n_faces(); i > 0; --i) {
763 if (is_deleted(fh)) {
764 face_deleted_[fh] =
false;
768 n_deleted_faces_ = 0;
770 for (
int i = (
int)
n_edges(); i > 0; --i) {
772 if (is_deleted(eh)) {
773 edge_deleted_[eh] =
false;
777 n_deleted_edges_ = 0;
781 if (is_deleted(vh)) {
782 vertex_deleted_[vh] =
false;
786 n_deleted_vertices_ = 0;
788 deferred_deletion_ =
true;
794template <
class ContainerT>
795void TopologyKernel::get_incident_edges(
const ContainerT& _vs,
796 std::set<EdgeHandle>& _es)
const {
800 if(has_vertex_bottom_up_incidences()) {
802 for(
typename ContainerT::const_iterator v_it = _vs.begin(),
803 v_end = _vs.end(); v_it != v_end; ++v_it) {
805 const std::vector<HalfEdgeHandle>& inc_hes = outgoing_hes_per_vertex_[*v_it];
807 for(std::vector<HalfEdgeHandle>::const_iterator he_it = inc_hes.begin(),
808 he_end = inc_hes.end(); he_it != he_end; ++he_it) {
815 for(
typename ContainerT::const_iterator v_it = _vs.begin(),
816 v_end = _vs.end(); v_it != v_end; ++v_it) {
818 for(EdgeIter e_it = edges_begin(), e_end = edges_end(); e_it != e_end; ++e_it) {
820 const Edge& e =
edge(*e_it);
822 if(e.from_vertex() == *v_it || e.to_vertex() == *v_it) {
832template <
class ContainerT>
833void TopologyKernel::get_incident_faces(
const ContainerT& _es,
834 std::set<FaceHandle>& _fs)
const {
838 if(has_edge_bottom_up_incidences()) {
840 for(
typename ContainerT::const_iterator e_it = _es.begin(),
841 e_end = _es.end(); e_it != e_end; ++e_it) {
843 for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(
halfedge_handle(*e_it, 0));
844 hehf_it.valid(); ++hehf_it) {
846 const FaceHandle fh = face_handle(*hehf_it);
853 for(
typename ContainerT::const_iterator e_it = _es.begin(),
854 e_end = _es.end(); e_it != e_end; ++e_it) {
856 for(FaceIter f_it = faces_begin(),
857 f_end = faces_end(); f_it != f_end; ++f_it) {
859 const std::vector<HalfEdgeHandle>& hes =
face(*f_it).halfedges();
861 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
862 he_end = hes.end(); he_it != he_end; ++he_it) {
876template <
class ContainerT>
877void TopologyKernel::get_incident_cells(
const ContainerT& _fs,
878 std::set<CellHandle>& _cs)
const {
882 if(has_face_bottom_up_incidences()) {
884 for(
typename ContainerT::const_iterator f_it = _fs.begin(),
885 f_end = _fs.end(); f_it != f_end; ++f_it) {
893 if(c0.is_valid()) _cs.insert(c0);
894 if(c1.is_valid()) _cs.insert(c1);
898 for(
typename ContainerT::const_iterator f_it = _fs.begin(),
899 f_end = _fs.end(); f_it != f_end; ++f_it) {
901 for(CellIter c_it = cells_begin(), c_end = cells_end();
902 c_it != c_end; ++c_it) {
904 const std::vector<HalfFaceHandle>& hfs =
cell(*c_it).halffaces();
906 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
907 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
909 if(face_handle(*hf_it) == *f_it) {
941 assert(h.is_valid() && (
size_t)h.idx() <
n_vertices());
943 if (fast_deletion_enabled() && !deferred_deletion_enabled())
946 assert(!vertex_deleted_[last_undeleted_vertex]);
948 h = last_undeleted_vertex;
951 if (deferred_deletion_enabled())
953 ++n_deleted_vertices_;
954 vertex_deleted_[h] =
true;
964 if(has_vertex_bottom_up_incidences()) {
967 for(
int i = h.idx(), end = (
int)
n_vertices(); i < end; ++i) {
968 const std::vector<HalfEdgeHandle>& hes = outgoing_hes_per_vertex_[
VertexHandle(i)];
969 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
970 he_end = hes.end(); he_it != he_end; ++he_it) {
973 if(e.from_vertex().idx() == i) {
976 if(e.to_vertex().idx() == i) {
985 for(
EdgeIter e_it = edges_begin(), e_end = edges_end();
986 e_it != e_end; ++e_it) {
989 if(
edge(*e_it).from_vertex() > h) {
992 if(
edge(*e_it).to_vertex() > h) {
1000 if(has_vertex_bottom_up_incidences()) {
1001 assert((
size_t)h.idx() < outgoing_hes_per_vertex_.size());
1002 outgoing_hes_per_vertex_.erase(outgoing_hes_per_vertex_.begin() + h.idx());
1009 vertex_deleted_.erase(vertex_deleted_.begin() + h.idx());
1047 assert(h.is_valid() && (
size_t)h.idx() < edges_.size());
1049 if (fast_deletion_enabled() && !deferred_deletion_enabled())
1052 assert(!edge_deleted_[last_edge]);
1059 if(has_vertex_bottom_up_incidences()) {
1063 assert(v0.is_valid() && (
size_t)v0.idx() < outgoing_hes_per_vertex_.size());
1064 assert(v1.is_valid() && (
size_t)v1.idx() < outgoing_hes_per_vertex_.size());
1066 outgoing_hes_per_vertex_[v0].erase(
1067 std::remove(outgoing_hes_per_vertex_[v0].begin(),
1068 outgoing_hes_per_vertex_[v0].end(),
1070 outgoing_hes_per_vertex_[v0].end());
1072 outgoing_hes_per_vertex_[v1].erase(
1073 std::remove(outgoing_hes_per_vertex_[v1].begin(),
1074 outgoing_hes_per_vertex_[v1].end(),
1076 outgoing_hes_per_vertex_[v1].end());
1079 if (deferred_deletion_enabled())
1082 edge_deleted_[h] =
true;
1092 if (!fast_deletion_enabled())
1095 if(has_edge_bottom_up_incidences()) {
1097 assert((
size_t)
halfedge_handle(h, 0).idx() < incident_hfs_per_he_.size());
1102 std::set<FaceHandle> update_faces;
1103 for(std::vector<std::vector<HalfFaceHandle> >::const_iterator iit =
1105 iit_end = incident_hfs_per_he_.end(); iit != iit_end; ++iit) {
1106 for(std::vector<HalfFaceHandle>::const_iterator it = iit->begin(),
1107 end = iit->end(); it != end; ++it) {
1108 update_faces.insert(face_handle(*it));
1113 for(std::set<FaceHandle>::iterator f_it = update_faces.begin(),
1114 f_end = update_faces.end(); f_it != f_end; ++f_it) {
1116 std::vector<HalfEdgeHandle> hes =
face(*f_it).halfedges();
1119 hes.erase(std::remove(hes.begin(), hes.end(),
halfedge_handle(h, 0)), hes.end());
1120 hes.erase(std::remove(hes.begin(), hes.end(),
halfedge_handle(h, 1)), hes.end());
1122 #if defined(__clang_major__) && (__clang_major__ >= 5)
1123 for(std::vector<HalfEdgeHandle>::iterator it = hes.begin(), end = hes.end();
1125 cor.correctValue(*it);
1128 std::for_each(hes.begin(), hes.end(),
1129 std::bind(&HEHandleCorrection::correctValue, &cor, std::placeholders::_1));
1131 face(*f_it).set_halfedges(hes);
1136 for(
FaceIter f_it = faces_begin(), f_end = faces_end();
1137 f_it != f_end; ++f_it) {
1140 std::vector<HalfEdgeHandle> hes =
face(*f_it).halfedges();
1143 hes.erase(std::remove(hes.begin(), hes.end(),
halfedge_handle(h, 0)), hes.end());
1144 hes.erase(std::remove(hes.begin(), hes.end(),
halfedge_handle(h, 1)), hes.end());
1148 #if defined(__clang_major__) && (__clang_major__ >= 5)
1149 for(std::vector<HalfEdgeHandle>::iterator it = hes.begin(), end = hes.end();
1151 cor.correctValue(*it);
1154 std::for_each(hes.begin(), hes.end(),
1155 std::bind(&HEHandleCorrection::correctValue, &cor, std::placeholders::_1));
1157 face(*f_it).set_halfedges(hes);
1164 if(has_edge_bottom_up_incidences()) {
1165 assert((
size_t)
halfedge_handle(h, 1).idx() < incident_hfs_per_he_.size());
1167 incident_hfs_per_he_.erase(incident_hfs_per_he_.begin() +
halfedge_handle(h, 1).idx());
1168 incident_hfs_per_he_.erase(incident_hfs_per_he_.begin() +
halfedge_handle(h, 0).idx());
1171 if (!fast_deletion_enabled())
1174 if(has_vertex_bottom_up_incidences()) {
1176 #if defined(__clang_major__) && (__clang_major__ >= 5)
1177 for(std::vector<std::vector<HalfEdgeHandle> >::iterator it = outgoing_hes_per_vertex_.begin(),
1178 end = outgoing_hes_per_vertex_.end(); it != end; ++it) {
1179 cor.correctVecValue(*it);
1182 std::for_each(outgoing_hes_per_vertex_.begin(),
1183 outgoing_hes_per_vertex_.end(),
1184 std::bind(&HEHandleCorrection::correctVecValue, &cor, std::placeholders::_1));
1191 edges_.erase(edges_.begin() + h.idx());
1192 edge_deleted_.erase(edge_deleted_.begin() + h.idx());
1231 assert(h.is_valid() && (
size_t)h.idx() < faces_.size());
1234 if (fast_deletion_enabled() && !deferred_deletion_enabled())
1237 assert(!face_deleted_[last_face]);
1243 if(has_edge_bottom_up_incidences()) {
1245 const std::vector<HalfEdgeHandle>& hes =
face(h).halfedges();
1246 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
1247 he_end = hes.end(); he_it != he_end; ++he_it) {
1249 assert((
size_t)std::max(he_it->idx(), opposite_halfedge_handle(*he_it).idx()) < incident_hfs_per_he_.size());
1251 incident_hfs_per_he_[*he_it].erase(
1252 std::remove(incident_hfs_per_he_[*he_it].begin(),
1253 incident_hfs_per_he_[*he_it].end(),
1257 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].erase(
1258 std::remove(incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin(),
1259 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end(),
1260 halfface_handle(h, 1)), incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end());
1266 if (deferred_deletion_enabled())
1269 face_deleted_[h] =
true;
1279 if (!fast_deletion_enabled())
1282 if(has_face_bottom_up_incidences()) {
1286 std::set<CellHandle> update_cells;
1287 for(std::vector<CellHandle>::const_iterator c_it = (incident_cell_per_hf_.begin() +
halfface_handle(h, 0).idx()),
1288 c_end = incident_cell_per_hf_.end(); c_it != c_end; ++c_it) {
1289 if(!c_it->is_valid())
continue;
1290 update_cells.insert(*c_it);
1292 for(std::set<CellHandle>::const_iterator c_it = update_cells.begin(),
1293 c_end = update_cells.end(); c_it != c_end; ++c_it) {
1295 std::vector<HalfFaceHandle> hfs =
cell(*c_it).halffaces();
1298 hfs.erase(std::remove(hfs.begin(), hfs.end(),
halfface_handle(h, 0)), hfs.end());
1299 hfs.erase(std::remove(hfs.begin(), hfs.end(),
halfface_handle(h, 1)), hfs.end());
1302#if defined(__clang_major__) && (__clang_major__ >= 5)
1303 for(std::vector<HalfFaceHandle>::iterator it = hfs.begin(),
1304 end = hfs.end(); it != end; ++it) {
1305 cor.correctValue(*it);
1308 std::for_each(hfs.begin(), hfs.end(),
1309 std::bind(&HFHandleCorrection::correctValue, &cor, std::placeholders::_1));
1311 cell(*c_it).set_halffaces(hfs);
1317 for(
CellIter c_it = cells_begin(), c_end = cells_end(); c_it != c_end; ++c_it) {
1319 std::vector<HalfFaceHandle> hfs =
cell(*c_it).halffaces();
1322 hfs.erase(std::remove(hfs.begin(), hfs.end(),
halfface_handle(h, 0)), hfs.end());
1323 hfs.erase(std::remove(hfs.begin(), hfs.end(),
halfface_handle(h, 1)), hfs.end());
1326#if defined(__clang_major__) && (__clang_major__ >= 5)
1327 for(std::vector<HalfFaceHandle>::iterator it = hfs.begin(),
1328 end = hfs.end(); it != end; ++it) {
1329 cor.correctValue(*it);
1332 std::for_each(hfs.begin(), hfs.end(),
1333 std::bind(&HFHandleCorrection::correctValue, &cor, std::placeholders::_1));
1335 cell(*c_it).set_halffaces(hfs);
1342 if(has_face_bottom_up_incidences()) {
1343 assert((
size_t)
halfface_handle(h, 1).idx() < incident_cell_per_hf_.size());
1345 incident_cell_per_hf_.erase(incident_cell_per_hf_.begin() +
halfface_handle(h, 1).idx());
1346 incident_cell_per_hf_.erase(incident_cell_per_hf_.begin() +
halfface_handle(h, 0).idx());
1350 if (!fast_deletion_enabled())
1353 if(has_edge_bottom_up_incidences()) {
1355#if defined(__clang_major__) && (__clang_major__ >= 5)
1356 for(std::vector<std::vector<HalfFaceHandle> >::iterator it = incident_hfs_per_he_.begin(), end = incident_hfs_per_he_.end(); it != end; ++it) {
1357 cor.correctVecValue(*it);
1360 std::for_each(incident_hfs_per_he_.begin(),
1361 incident_hfs_per_he_.end(),
1362 std::bind(&HFHandleCorrection::correctVecValue, &cor, std::placeholders::_1));
1368 faces_.erase(faces_.begin() + h.idx());
1369 face_deleted_.erase(face_deleted_.begin() + h.idx());
1402 assert(h.is_valid() && (
size_t)h.idx() < cells_.size());
1405 if (fast_deletion_enabled() && !deferred_deletion_enabled())
1408 assert(!cell_deleted_[last_undeleted_cell]);
1410 h = last_undeleted_cell;
1415 if(has_face_bottom_up_incidences()) {
1416 const std::vector<HalfFaceHandle>& hfs =
cell(h).halffaces();
1417 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
1418 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
1419 assert((
size_t)hf_it->idx() < incident_cell_per_hf_.size());
1420 if (incident_cell_per_hf_[*hf_it] == h)
1421 incident_cell_per_hf_[*hf_it] = InvalidCellHandle;
1423 std::set<EdgeHandle> edges;
1424 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
1425 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
1427 for (
const auto& heh : hf.halfedges())
1430 for (
auto eh : edges)
1434 if (deferred_deletion_enabled())
1437 cell_deleted_[h] =
true;
1447 if (!fast_deletion_enabled())
1449 if(has_face_bottom_up_incidences()) {
1451#if defined(__clang_major__) && (__clang_major__ >= 5)
1452 for(std::vector<CellHandle>::iterator it = incident_cell_per_hf_.begin(),
1453 end = incident_cell_per_hf_.end(); it != end; ++it) {
1454 cor.correctValue(*it);
1457 std::for_each(incident_cell_per_hf_.begin(),
1458 incident_cell_per_hf_.end(),
1459 std::bind(&CHandleCorrection::correctValue, &cor, std::placeholders::_1));
1465 cells_.erase(cells_.begin() + h.idx());
1466 cell_deleted_.erase(cell_deleted_.begin() + h.idx());
1479 assert(_h1.idx() >= 0 && _h1.idx() < (
int)cells_.size());
1480 assert(_h2.idx() >= 0 && _h2.idx() < (
int)cells_.size());
1486 for (
const auto hfh: cells_[_h1].halffaces()) {
1487 if (incident_cell_per_hf_[hfh] == _h1)
1488 incident_cell_per_hf_[hfh] = _h2;
1490 for (
const auto hfh: cells_[_h2].halffaces()) {
1491 if (incident_cell_per_hf_[hfh] == _h2)
1492 incident_cell_per_hf_[hfh] = _h1;
1496 std::swap(cells_[_h1], cells_[_h2]);
1497 detail::swap_bool(cell_deleted_[_h1], cell_deleted_[_h2]);
1498 swap_property_elements(_h1, _h2);
1503 assert(_h1.idx() >= 0 && _h1.idx() < (
int)faces_.size());
1504 assert(_h2.idx() >= 0 && _h2.idx() < (
int)faces_.size());
1510 std::vector<unsigned int> ids;
1511 ids.push_back(_h1.idx());
1512 ids.push_back(_h2.idx());
1514 unsigned int id1 = _h1.idx();
1515 unsigned int id2 = _h2.idx();
1520 if (has_face_bottom_up_incidences())
1522 std::set<unsigned int> processed_cells;
1523 for (
unsigned int i = 0; i < 2; ++i)
1525 unsigned int id = ids[i];
1526 for (
unsigned int j = 0; j < 2; ++j)
1535 if (processed_cells.find(ch.idx()) == processed_cells.end())
1538 Cell& c = cells_[ch];
1542 std::vector<HalfFaceHandle> new_halffaces;
1543 for (
unsigned int k = 0; k < c.halffaces().size(); ++k)
1544 if (c.halffaces()[k].idx()/2 == (
int)id1)
1545 new_halffaces.push_back(
HalfFaceHandle(2 * id2 + (c.halffaces()[k].idx() % 2)));
1546 else if (c.halffaces()[k].idx()/2 == (
int)id2)
1547 new_halffaces.push_back(
HalfFaceHandle(2 * id1 + (c.halffaces()[k].idx() % 2)));
1549 new_halffaces.push_back(c.halffaces()[k]);
1550 c.set_halffaces(new_halffaces);
1552 processed_cells.insert(ch.idx());
1560 for (
unsigned int i = 0; i < cells_.size(); ++i)
1565 bool contains_swapped_face =
false;
1566 for (
unsigned int k = 0; k < c.halffaces().size(); ++k)
1568 if (c.halffaces()[k].idx()/2 == (
int)id1)
1569 contains_swapped_face =
true;
1570 if (c.halffaces()[k].idx()/2 == (
int)id2)
1571 contains_swapped_face =
true;
1572 if (contains_swapped_face)
1576 if (contains_swapped_face)
1579 std::vector<HalfFaceHandle> new_halffaces;
1580 for (
unsigned int k = 0; k < c.halffaces().size(); ++k)
1581 if (c.halffaces()[k].idx()/2 == (
int)id1)
1582 new_halffaces.push_back(
HalfFaceHandle(2 * id2 + (c.halffaces()[k].idx() % 2)));
1583 else if (c.halffaces()[k].idx()/2 == (
int)id2)
1584 new_halffaces.push_back(
HalfFaceHandle(2 * id1 + (c.halffaces()[k].idx() % 2)));
1586 new_halffaces.push_back(c.halffaces()[k]);
1587 c.set_halffaces(new_halffaces);
1594 if (has_edge_bottom_up_incidences())
1596 std::set<HalfEdgeHandle> processed_halfedges;
1597 for (
unsigned int i = 0; i < 2; ++i)
1599 unsigned int id = ids[i];
1600 for (
unsigned int j = 0; j < 2; ++j)
1605 for (
unsigned int k = 0; k < hf.halfedges().size(); ++k)
1609 if (processed_halfedges.find(heh) != processed_halfedges.end())
1612 std::vector<HalfFaceHandle>& incident_halffaces = incident_hfs_per_he_[heh];
1613 for (
unsigned int l = 0; l < incident_halffaces.size(); ++l)
1617 if (hfh2.idx()/2 == (
int)id1)
1619 else if (hfh2.idx()/2 == (
int)id2)
1623 processed_halfedges.insert(heh);
1630 std::swap(faces_[_h1], faces_[_h2]);
1631 detail::swap_bool(face_deleted_[_h1], face_deleted_[_h2]);
1632 std::swap(incident_cell_per_hf_[_h1.halfface_handle(0)], incident_cell_per_hf_[_h2.halfface_handle(0)]);
1633 std::swap(incident_cell_per_hf_[_h1.halfface_handle(1)], incident_cell_per_hf_[_h2.halfface_handle(1)]);
1634 swap_property_elements(_h1, _h2);
1642 assert(_h1.idx() >= 0 && _h1.idx() < (
int)edges_.size());
1643 assert(_h2.idx() >= 0 && _h2.idx() < (
int)edges_.size());
1648 std::vector<unsigned int> ids;
1649 ids.push_back(_h1.idx());
1650 ids.push_back(_h2.idx());
1655 if (has_edge_bottom_up_incidences())
1657 std::set<unsigned int> processed_faces;
1659 for (
unsigned int i = 0; i < 2; ++i)
1664 std::vector<HalfFaceHandle>& incident_halffaces = incident_hfs_per_he_[heh];
1665 for (
unsigned int j = 0; j < incident_halffaces.size(); ++j)
1669 unsigned int f_id = hfh.idx() / 2;
1671 if (processed_faces.find(f_id) == processed_faces.end())
1677 std::vector<HalfEdgeHandle> new_halfedges;
1678 for (
unsigned int k = 0; k < f.halfedges().size(); ++k)
1681 if (heh2.idx() / 2 == (
int)ids[0])
1682 new_halfedges.push_back(
HalfEdgeHandle(2*ids[1] + (heh2.idx() % 2)));
1683 else if (heh2.idx() / 2 == (
int)ids[1])
1684 new_halfedges.push_back(
HalfEdgeHandle(2*ids[0] + (heh2.idx() % 2)));
1686 new_halfedges.push_back(heh2);
1688 f.set_halfedges(new_halfedges);
1690 processed_faces.insert(f_id);
1698 for (
unsigned int i = 0; i < faces_.size(); ++i)
1703 bool contains_swapped_edge =
false;
1704 for (
unsigned int k = 0; k < f.halfedges().size(); ++k)
1706 if (f.halfedges()[k].idx()/2 == (
int)ids[0])
1707 contains_swapped_edge =
true;
1708 if (f.halfedges()[k].idx()/2 == (
int)ids[1])
1709 contains_swapped_edge =
true;
1710 if (contains_swapped_edge)
1714 if (contains_swapped_edge)
1717 std::vector<HalfEdgeHandle> new_halfedges;
1718 for (
unsigned int k = 0; k < f.halfedges().size(); ++k)
1721 if (heh2.idx() / 2 == (
int)ids[0])
1722 new_halfedges.push_back(
HalfEdgeHandle(2*ids[1] + (heh2.idx() % 2)));
1723 else if (heh2.idx() / 2 == (
int)ids[1])
1724 new_halfedges.push_back(
HalfEdgeHandle(2*ids[0] + (heh2.idx() % 2)));
1726 new_halfedges.push_back(heh2);
1728 f.set_halfedges(new_halfedges);
1735 if (has_vertex_bottom_up_incidences())
1737 std::set<VertexHandle> processed_vertices;
1738 for (
unsigned int i = 0; i < 2; ++i)
1741 std::vector<VertexHandle> vhs;
1742 vhs.push_back(e.from_vertex());
1743 vhs.push_back(e.to_vertex());
1745 for (
unsigned int j = 0; j < 2; ++j)
1747 if (processed_vertices.find(vhs[j]) != processed_vertices.end())
1750 std::vector<HalfEdgeHandle>& outgoing_hes = outgoing_hes_per_vertex_[vhs[j]];
1751 for (
unsigned int k = 0; k < outgoing_hes.size(); ++k)
1754 if (heh.idx() / 2 == (
int)ids[0])
1756 else if (heh.idx() / 2 == (
int)ids[1])
1759 processed_vertices.insert(vhs[j]);
1766 std::swap(edges_[_h1], edges_[_h2]);
1767 detail::swap_bool(edge_deleted_[_h1], edge_deleted_[_h2]);
1768 std::swap(incident_hfs_per_he_[_h1.halfedge_handle(0)], incident_hfs_per_he_[_h2.halfedge_handle(0)]);
1769 std::swap(incident_hfs_per_he_[_h1.halfedge_handle(1)], incident_hfs_per_he_[_h2.halfedge_handle(1)]);
1770 swap_property_elements(_h1, _h2);
1784 std::array<VH, 2> ids {_h1, _h2};
1788 if (has_vertex_bottom_up_incidences())
1790 std::set<EH> processed_edges;
1791 for (
unsigned int i = 0; i < 2; ++i)
1793 for (
const auto heh: outgoing_hes_per_vertex_[ids[i]]) {
1794 const auto eh = heh.edge_handle();
1796 if (processed_edges.find(eh) == processed_edges.end())
1798 Edge& e = edges_[eh];
1799 if (e.from_vertex() == ids[0])
1800 e.set_from_vertex(ids[1]);
1801 else if (e.from_vertex() == ids[1])
1802 e.set_from_vertex(ids[0]);
1804 if (e.to_vertex() == ids[0])
1805 e.set_to_vertex(ids[1]);
1806 else if (e.to_vertex() == ids[1])
1807 e.set_to_vertex(ids[0]);
1809 processed_edges.insert(eh);
1819 for (
auto &e: edges_)
1821 if (e.from_vertex() == ids[0])
1822 e.set_from_vertex(ids[1]);
1823 else if (e.from_vertex() == ids[1])
1824 e.set_from_vertex(ids[0]);
1826 if (e.to_vertex() == ids[0])
1827 e.set_to_vertex(ids[1]);
1828 else if (e.to_vertex() == ids[1])
1829 e.set_to_vertex(ids[0]);
1834 detail::swap_bool(vertex_deleted_[_h1], vertex_deleted_[_h2]);
1835 std::swap(outgoing_hes_per_vertex_[_h1], outgoing_hes_per_vertex_[_h2]);
1836 swap_property_elements(_h1, _h2);
1840void TopologyKernel::enable_deferred_deletion(
bool _enable)
1842 if (deferred_deletion_ && !_enable)
1845 deferred_deletion_ = _enable;
1854 return edges_[_edgeHandle];
1863 return faces_[_faceHandle];
1872 return cells_[_cellHandle];
1881 return edges_[_edgeHandle];
1891 return faces_[_faceHandle];
1900 return cells_[_cellHandle];
1912 if(_halfEdgeHandle.subidx() == 0)
1913 return edges_[_halfEdgeHandle.edge_handle()];
1927 if(_halfFaceHandle.idx() % 2 == 0)
1928 return faces_[_halfFaceHandle.face_handle()];
1938 return halfedge(_halfEdgeHandle.opposite_handle());
1946 return halfface(_halfFaceHandle.opposite_handle());
1968 if(
halfedge(*voh_it).to_vertex() == _vh2) {
1973 return InvalidHalfEdgeHandle;
1983 for(
auto hfh :
cell(_ch).halffaces())
1985 for(
auto heh :
halfface(hfh).halfedges() )
1990 return opposite_halfedge_handle(heh);
1994 return InvalidHalfEdgeHandle;
2008 assert(_vs.size() > 2);
2012 assert(v0.is_valid() && v1.is_valid() && v2.is_valid());
2015 if(!he0.is_valid())
return InvalidHalfFaceHandle;
2017 if(!he1.is_valid())
return InvalidHalfFaceHandle;
2019 std::vector<HalfEdgeHandle> hes;
2030 assert(_vs.size() > 2);
2034 assert(v0.is_valid() && v1.is_valid() && v2.is_valid());
2037 for(
auto hfh :
cell(_ch).halffaces())
2039 for(
auto heh :
halfface(hfh).halfedges() )
2056 return InvalidHalfFaceHandle;
2063HalfFaceHandle TopologyKernel::halfface_extensive(
const std::vector<VertexHandle>& _vs)
const
2075 assert(_vs.size() > 2);
2080 assert(v0.is_valid() && v1.is_valid());
2083 if(!he0.is_valid())
return InvalidHalfFaceHandle;
2087 std::vector<HalfEdgeHandle> hes =
halfface(*hehf_it).halfedges();
2089 if (hes.size() != _vs.size())
2093 for (
unsigned int i = 0; i < hes.size(); ++i)
2097 bool all_vertices_found =
true;
2099 for (
unsigned int i = 0; i < hes.size(); ++i)
2102 if (
halfedge(heh).from_vertex() != _vs[i])
2104 all_vertices_found =
false;
2109 if (all_vertices_found)
2113 return InvalidHalfFaceHandle;
2128 assert(_hes.size() >= 2);
2132 assert(he0.is_valid() && he1.is_valid());
2136 std::vector<HalfEdgeHandle> hes =
halfface(*hehf_it).halfedges();
2137 if(std::find(hes.begin(), hes.end(), he1) != hes.end()) {
2142 return InvalidHalfFaceHandle;
2149 assert(_heh.is_valid() && (
size_t)_heh.idx() < edges_.size() * 2u);
2150 assert(_hfh.is_valid() && (
size_t)_hfh.idx() < faces_.size() * 2u);
2152 std::vector<HalfEdgeHandle> hes =
halfface(_hfh).halfedges();
2154 for(std::vector<HalfEdgeHandle>::const_iterator it = hes.begin();
2155 it != hes.end(); ++it) {
2157 if((it + 1) != hes.end())
return *(it + 1);
2158 else return *hes.begin();
2162 return InvalidHalfEdgeHandle;
2169 assert(_heh.is_valid() && (
size_t)_heh.idx() < edges_.size() * 2u);
2170 assert(_hfh.is_valid() && (
size_t)_hfh.idx() < faces_.size() * 2u);
2172 std::vector<HalfEdgeHandle> hes =
halfface(_hfh).halfedges();
2174 for(std::vector<HalfEdgeHandle>::const_iterator it = hes.begin();
2175 it != hes.end(); ++it) {
2177 if(it != hes.begin())
return *(it - 1);
2178 else return *(hes.end() - 1);
2182 return InvalidHalfEdgeHandle;
2201 for (
size_t i = 0; i < hf.halfedges().size(); ++i)
2202 if (
halfedge(hf.halfedges()[i]).from_vertex() == vh)
2205 return std::vector<VertexHandle>();
2214 std::vector<VertexHandle> vertices;
2218 auto n =
valence(hfh.face_handle());
2219 for (
unsigned int i = 0; i <
n; ++i)
2221 vertices.push_back(
halfedge(heh).from_vertex());
2236 const auto f =
face(_fh);
2252 assert(_halfFaceHandle.is_valid() && (
size_t)_halfFaceHandle.idx() < faces_.size() * 2u);
2253 assert(_halfEdgeHandle.is_valid() && (
size_t)_halfEdgeHandle.idx() < edges_.size() * 2u);
2254 assert(has_face_bottom_up_incidences());
2257 if(!ch.is_valid()) {
2259 return InvalidHalfFaceHandle;
2263 bool skipped =
false;
2269 HalfEdgeHandle hehOpp = opposite_halfedge_handle(_halfEdgeHandle);
2270 bool hasHalfedge =
false;
2271 bool hasOppHalfedge =
false;
2272 const auto hf =
halfface(_halfFaceHandle);
2275 hasOppHalfedge =
true;
2276 else if (heh == _halfEdgeHandle)
2281 _halfEdgeHandle = hehOpp;
2283 return InvalidHalfFaceHandle;
2286 for(
const auto &hfh:
cell(ch).halffaces()) {
2287 if(hfh == _halfFaceHandle) {
2290 if (idx.is_valid()) {
2295 for (
const auto heh: hf_cur.halfedges()) {
2298 if(opposite_halfedge_handle(heh) == _halfEdgeHandle && hfh != opposite_halfface_handle(_halfFaceHandle)) {
2299 if (idx.is_valid()) {
2302 return InvalidHalfFaceHandle;
2314 return InvalidHalfFaceHandle;
2322 assert((
size_t)_halfFaceHandle.idx() < incident_cell_per_hf_.size() && _halfFaceHandle.is_valid());
2323 assert(has_face_bottom_up_incidences());
2325 return incident_cell_per_hf_[_halfFaceHandle];
2330void TopologyKernel::compute_vertex_bottom_up_incidences() {
2333 outgoing_hes_per_vertex_.clear();
2334 outgoing_hes_per_vertex_.resize(
n_vertices());
2337 for (
const auto &eh: edges()) {
2338 const auto &e =
edge(eh);
2339 ++n_edges_per_vertex[e.from_vertex()];
2340 ++n_edges_per_vertex[e.to_vertex()];
2342 for (
const auto &vh: vertices()) {
2343 outgoing_hes_per_vertex_[vh].reserve(n_edges_per_vertex[vh]);
2347 for (
const auto eh: edges()) {
2348 const auto &e =
edge(eh);
2349 VertexHandle from = e.from_vertex();
2352 assert((
size_t)from.idx() < outgoing_hes_per_vertex_.size());
2356 VertexHandle to = e.to_vertex();
2357 assert((
size_t)to.idx() < outgoing_hes_per_vertex_.size());
2366void TopologyKernel::compute_edge_bottom_up_incidences() {
2369 incident_hfs_per_he_.clear();
2372 EdgeVector<int> n_faces_per_edge(
n_edges(), 0);
2373 for (
const auto &fh: faces()) {
2374 for (
const auto &heh: face_halfedges(fh)) {
2378 for (
const auto &eh: edges()) {
2379 incident_hfs_per_he_[
halfedge_handle(eh, 0)].reserve(n_faces_per_edge[eh]);
2380 incident_hfs_per_he_[
halfedge_handle(eh, 1)].reserve(n_faces_per_edge[eh]);
2383 for (
const auto &fh: faces()) {
2384 for (
const auto &heh: face_halfedges(fh)) {
2385 auto opp = opposite_halfedge_handle(heh);
2394void TopologyKernel::compute_face_bottom_up_incidences() {
2397 incident_cell_per_hf_.clear();
2398 incident_cell_per_hf_.resize(faces_.size() * 2u, InvalidCellHandle);
2400 for (
const auto ch: cells()) {
2401 for (
const auto hfh: cell_halffaces(ch)) {
2402 if(incident_cell_per_hf_[hfh] == InvalidCellHandle) {
2404 incident_cell_per_hf_[hfh] = ch;
2408 std::cerr <<
"compute_face_bottom_up_incidences(): Detected non-three-manifold configuration!" << std::endl;
2409 std::cerr <<
"Connectivity probably won't work." << std::endl;
void resize_vprops(size_t _nv)
Change size of stored vertex properties.
size_t n() const
Get number of entities of given kind in mesh.
void resize_cprops(size_t _nc)
Change size of stored cell properties.
void resize_eprops(size_t _ne)
Change size of stored edge properties.
void resize_fprops(size_t _nf)
Change size of stored face properties.
Face opposite_halfface(HalfFaceHandle _halfFaceHandle) const
Get opposite halfface that corresponds to halfface with handle _halfFaceHandle.
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.
void set_cell(CellHandle _ch, const std::vector< HalfFaceHandle > &_hfs)
Set the half-faces of a cell.
const Cell & cell(CellHandle _cellHandle) const
Get cell with handle _cellHandle.
size_t n_halfedges() const override
Get number of halfedges in mesh.
bool is_valid(Handle _h) const
test is_valid and perform index range check
CellIter delete_cell_core(CellHandle _h)
Delete cell from mesh.
HalfEdgeHandle prev_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get previous halfedge within a halfface.
HalfFaceHandle find_halfface_in_cell(const std::vector< VertexHandle > &_vs, CellHandle _ch) const
HalfEdgeHandle find_halfedge_in_cell(VertexHandle _vh1, VertexHandle _vh2, CellHandle _ch) const
Get halfedge from vertex _vh1 to _vh2 but restricted to halfedges of cell _ch.
static HalfEdgeHandle halfedge_handle(EdgeHandle _h, const unsigned char _subIdx)
Conversion function.
HalfFaceHandle find_halfface_extensive(const std::vector< VertexHandle > &_vs) const
HalfEdgeHandle find_halfedge(VertexHandle _vh1, VertexHandle _vh2) const
Get halfedge from vertex _vh1 to _vh2.
virtual CellIter delete_cell(CellHandle _h)
Delete cell from mesh.
void set_edge(EdgeHandle _eh, VertexHandle _fromVertex, VertexHandle _toVertex)
Set the vertices of an edge.
HalfEdgeHandle next_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get next halfedge within a halfface.
virtual void swap_vertex_indices(VertexHandle _h1, VertexHandle _h2)
Exchanges the indices of two vertices while keeping the mesh otherwise unaffected.
EdgeIter delete_edge_core(EdgeHandle _h)
Delete edge 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.
virtual FaceHandle add_face(std::vector< HalfEdgeHandle > _halfedges, bool _topologyCheck=false)
Add face via incident edges.
static HalfFaceHandle halfface_handle(FaceHandle _h, const unsigned char _subIdx)
Conversion function.
size_t n_faces() const override
Get number of faces in mesh.
void set_face(FaceHandle _fh, const std::vector< HalfEdgeHandle > &_hes)
Set the half-edges of a face.
virtual CellHandle add_cell(std::vector< HalfFaceHandle > _halffaces, bool _topologyCheck=false)
Add cell via incident halffaces.
virtual void swap_edge_indices(EdgeHandle _h1, EdgeHandle _h2)
Exchanges the indices of two edges while keeping the mesh otherwise unaffected.
size_t n_cells() const override
Get number of cells in mesh.
std::vector< VertexHandle > get_halfface_vertices(HalfFaceHandle hfh) const
Get vertices of a halfface.
virtual void swap_cell_indices(CellHandle _h1, CellHandle _h2)
Exchanges the indices of two cells while keeping the mesh otherwise unaffected.
size_t n_edges() const override
Get number of edges in mesh.
Face halfface(HalfFaceHandle _halfFaceHandle) const
Get face that corresponds to halfface with handle _halfFaceHandle.
Edge opposite_halfedge(HalfEdgeHandle _halfEdgeHandle) const
Get opposite halfedge that corresponds to halfedge with handle _halfEdgeHandle.
Edge halfedge(HalfEdgeHandle _halfEdgeHandle) const
Get edge that corresponds to halfedge with handle _halfEdgeHandle.
VertexHandle from_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge starts from.
HalfFaceHandle find_halfface(const std::vector< VertexHandle > &_vs) const
const Edge & edge(EdgeHandle _edgeHandle) const
Get edge with handle _edgeHandle.
virtual EdgeHandle add_edge(VertexHandle _fromVertex, VertexHandle _toHandle, bool _allowDuplicates=false)
Add edge.
virtual VertexHandle add_vertex()
Add abstract vertex.
virtual EdgeIter delete_edge(EdgeHandle _h)
Delete edge from mesh.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.
virtual void swap_face_indices(FaceHandle _h1, FaceHandle _h2)
Exchanges the indices of two faces while keeping the mesh otherwise unaffected.
FaceIter delete_face_core(FaceHandle _h)
Delete face from mesh.
bool is_incident(FaceHandle _fh, EdgeHandle _eh) const
check whether face _fh and edge _eh are incident
HalfFaceHandle adjacent_halfface_in_cell(HalfFaceHandle _halfFaceHandle, HalfEdgeHandle _halfEdgeHandle) const
Get halfface that is adjacent (w.r.t. a common halfedge) within the same cell. It correctly handles s...
size_t n_halffaces() const override
Get number of halffaces in mesh.
void reorder_incident_halffaces(EdgeHandle _eh)
Recompute cyclic ordering of (half)faces incident to an edge (used by iterators)
const Face & face(FaceHandle _faceHandle) const
Get face with handle _faceHandle.
VertexIter delete_vertex_core(VertexHandle _h)
Delete vertex from mesh.
virtual void collect_garbage()
Delete all entities that are marked as deleted.