40#include <OpenVolumeMesh/Core/TopologyKernel.hh>
41#include <OpenVolumeMesh/Core/detail/swap_bool.hh>
43namespace OpenVolumeMesh {
47const VertexHandle TopologyKernel::InvalidVertexHandle = VertexHandle(-1);
48const EdgeHandle TopologyKernel::InvalidEdgeHandle = EdgeHandle(-1);
49const HalfEdgeHandle TopologyKernel::InvalidHalfEdgeHandle = HalfEdgeHandle(-1);
50const FaceHandle TopologyKernel::InvalidFaceHandle = FaceHandle(-1);
51const HalfFaceHandle TopologyKernel::InvalidHalfFaceHandle = HalfFaceHandle(-1);
52const CellHandle TopologyKernel::InvalidCellHandle = CellHandle(-1);
56void TopologyKernel::reserve_vertices(
size_t n)
58 ResourceManager::reserve_vprops(
n);
59 vertex_deleted_.reserve(
n);
62void TopologyKernel::reserve_edges(
size_t n)
64 ResourceManager::reserve_eprops(
n);
66 edge_deleted_.reserve(
n);
69void TopologyKernel::reserve_faces(
size_t n)
71 ResourceManager::reserve_fprops(
n);
73 face_deleted_.reserve(
n);
76void TopologyKernel::reserve_cells(
size_t n)
78 ResourceManager::reserve_cprops(
n);
80 cell_deleted_.reserve(
n);
83void TopologyKernel::add_n_vertices(
size_t n)
87 vertex_deleted_.resize(n_vertices_,
false);
88 if(has_vertex_bottom_up_incidences()) {
89 outgoing_hes_per_vertex_.resize(n_vertices_);
96 vertex_deleted_.push_back(
false);
99 if(has_vertex_bottom_up_incidences()) {
100 outgoing_hes_per_vertex_.resize(n_vertices_);
115 bool _allowDuplicates) {
119 assert(_fromVertex.is_valid() && (
size_t)_fromVertex.idx() <
n_vertices() && !is_deleted(_fromVertex));
120 assert(_toVertex.is_valid() && (
size_t)_toVertex.idx() <
n_vertices() && !is_deleted(_toVertex));
123 if(!_allowDuplicates) {
124 if(has_vertex_bottom_up_incidences()) {
126 assert((
size_t)_fromVertex.idx() < outgoing_hes_per_vertex_.size());
127 std::vector<HalfEdgeHandle>& ohes = outgoing_hes_per_vertex_[_fromVertex];
128 for(std::vector<HalfEdgeHandle>::const_iterator he_it = ohes.begin(),
129 he_end = ohes.end(); he_it != he_end; ++he_it) {
130 if(
halfedge(*he_it).to_vertex() == _toVertex) {
135 for(
int i = 0; i < (int)edges_.size(); ++i) {
146 edges_.emplace_back(_fromVertex, _toVertex);
147 edge_deleted_.push_back(
false);
154 if(has_vertex_bottom_up_incidences()) {
155 assert((
size_t)_fromVertex.idx() < outgoing_hes_per_vertex_.size());
156 assert((
size_t)_toVertex.idx() < outgoing_hes_per_vertex_.size());
158 outgoing_hes_per_vertex_[_fromVertex].push_back(
halfedge_handle(eh, 0));
163 if(has_edge_bottom_up_incidences()) {
178 for(std::vector<HalfEdgeHandle>::const_iterator it = _halfedges.begin(),
179 end = _halfedges.end(); it != end; ++it)
180 assert(it->is_valid() && (size_t)it->idx() < edges_.size() * 2u && !is_deleted(*it));
185 for (
size_t i = 0; i + 1< _halfedges.size(); ++i) {
187 return InvalidFaceHandle;
191 return InvalidFaceHandle;
197 faces_.emplace_back(std::move(_halfedges));
198 face_deleted_.push_back(
false);
207 if(has_edge_bottom_up_incidences()) {
209 for (
const auto heh: face_halfedges(fh)) {
210 auto opp = opposite_halfedge_handle(heh);
212 assert((
size_t)heh.idx() < incident_hfs_per_he_.size());
213 assert((
size_t)opp.idx() < incident_hfs_per_he_.size());
221 if(has_face_bottom_up_incidences()) {
222 incident_cell_per_hf_.resize(
n_halffaces(), InvalidCellHandle);
239 for(std::vector<VertexHandle>::const_iterator it = _vertices.begin(),
240 end = _vertices.end(); it != end; ++it)
241 assert(it->is_valid() && (size_t)it->idx() <
n_vertices() && !is_deleted(*it));
245 std::vector<HalfEdgeHandle> halfedges;
246 std::vector<VertexHandle>::const_iterator it = _vertices.begin();
247 std::vector<VertexHandle>::const_iterator end = _vertices.end();
248 for(; (it+1) != end; ++it) {
253 char swap =
edge(e_idx).to_vertex() == *it;
258 char swap =
edge(e_idx).to_vertex() == *it;
291 assert((
size_t)heh.idx() < incident_hfs_per_he_.size());
292 auto &incident_hfs = incident_hfs_per_he_[heh];
294 const size_t n_hfs = incident_hfs.size();
299 std::vector<HalfFaceHandle> new_halffaces;
300 new_halffaces.reserve(n_hfs);
303 auto start_hf = incident_hfs.front();
304 auto cur_hf = start_hf;
308 new_halffaces.push_back(cur_hf);
309 if (new_halffaces.size() > incident_hfs.size()) {
319 if(cur_hf == InvalidHalfFaceHandle) {
322 cur_hf = opposite_halfface_handle(cur_hf);
324 }
while (cur_hf != start_hf);
331 if(new_halffaces.size() != incident_hfs.size()) {
334 cur_heh = opposite_halfedge_handle(heh);
337 cur_hf = opposite_halfface_handle(cur_hf);
346 if (cur_hf == InvalidHalfFaceHandle) {
351 new_halffaces.insert(new_halffaces.begin(), cur_hf);
352 if(new_halffaces.size() > incident_hfs.size()) {
360 if(new_halffaces.size() == incident_hfs.size()) {
361 incident_hfs = std::move(new_halffaces);
363 std::transform(incident_hfs.rbegin(), incident_hfs.rend(),
364 incident_hfs_per_he_[opposite_halfedge_handle(heh)].begin(),
365 opposite_halfface_handle);
369 std::cerr <<
"reorder_incident_halffaces: found " << new_halffaces.size() <<
" of " << incident_hfs.size()
370 <<
" incident halffaces, likely the edge has more than one boundary! Currently not supported, not reordering." << std::endl;
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) && !is_deleted(*it));
397 std::vector<HalfEdgeHandle> incidentHalfedges;
398 size_t guess_n_halfedges = _halffaces.size() *
valence(face_handle(_halffaces[0]));
401 incidentHalfedges.reserve(2 * guess_n_halfedges);
403 for (
const auto &hfh: _halffaces) {
404 const auto &hes =
face(face_handle(hfh)).halfedges();
405 if ((hfh.idx() & 1) == 0) {
406 std::copy(hes.begin(), hes.end(),
407 std::back_inserter(incidentHalfedges));
409 std::transform(hes.rbegin(),
411 std::back_inserter(incidentHalfedges),
412 opposite_halfedge_handle);
415 std::sort(incidentHalfedges.begin(), incidentHalfedges.end());
416 auto duplicate = std::adjacent_find(incidentHalfedges.begin(), incidentHalfedges.end());
417 if (duplicate != incidentHalfedges.end()) {
419 std::cerr <<
"add_cell(): Halfedge #" << duplicate->idx() <<
" is contained in more than 1 halfface." << std::endl;
421 return InvalidCellHandle;
424 auto e_end = std::unique(incidentHalfedges.begin(), incidentHalfedges.end(),
426 auto n_edges =
static_cast<size_t>(std::distance(incidentHalfedges.begin(), e_end));
430 std::cerr <<
"add_cell(): The specified half-faces are not connected!" << std::endl;
432 return InvalidCellHandle;
438 cells_.emplace_back(std::move(_halffaces));
439 cell_deleted_.push_back(
false);
447 if(has_face_bottom_up_incidences()) {
449 const auto &cell_halffaces = cells_[ch].halffaces();
450 std::set<EdgeHandle> cell_edges;
451 for(
const auto &hfh: cell_halffaces) {
452 assert((
size_t)hfh.idx() < incident_cell_per_hf_.size());
456 if(incident_cell_per_hf_[hfh] != InvalidCellHandle) {
462 std::cerr <<
"add_cell(): One of the specified half-faces is already incident to another cell!" << std::endl;
468 incident_cell_per_hf_[hfh] = ch;
471 for(
const auto &eh: face_edges(face_handle(hfh))) {
472 cell_edges.insert(eh);
476 if(has_edge_bottom_up_incidences()) {
482 for (
const auto &eh: cell_edges) {
497 assert(_fromVertex.is_valid() && (
size_t)_fromVertex.idx() <
n_vertices() && !is_deleted(_fromVertex));
498 assert(_toVertex.is_valid() && (
size_t)_toVertex.idx() <
n_vertices() && !is_deleted(_toVertex));
503 if(has_vertex_bottom_up_incidences()) {
511 std::vector<HalfEdgeHandle>::iterator h_end =
512 std::remove(outgoing_hes_per_vertex_[fv].begin(), outgoing_hes_per_vertex_[fv].end(), heh0);
513 outgoing_hes_per_vertex_[fv].resize(h_end - outgoing_hes_per_vertex_[fv].begin());
515 h_end = std::remove(outgoing_hes_per_vertex_[tv].begin(), outgoing_hes_per_vertex_[tv].end(), heh1);
516 outgoing_hes_per_vertex_[tv].resize(h_end - outgoing_hes_per_vertex_[tv].begin());
518 outgoing_hes_per_vertex_[_fromVertex].push_back(heh0);
519 outgoing_hes_per_vertex_[_toVertex].push_back(heh1);
522 e.set_from_vertex(_fromVertex);
523 e.set_to_vertex(_toVertex);
534 if(has_edge_bottom_up_incidences()) {
539 const std::vector<HalfEdgeHandle>& hes = f.halfedges();
541 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
542 he_end = hes.end(); he_it != he_end; ++he_it) {
544 std::vector<HalfFaceHandle>::iterator h_end =
545 std::remove(incident_hfs_per_he_[*he_it].begin(),
546 incident_hfs_per_he_[*he_it].end(), hf0);
547 incident_hfs_per_he_[*he_it].resize(h_end - incident_hfs_per_he_[*he_it].begin());
549 h_end = std::remove(incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin(),
550 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end(), hf1);
551 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].resize(h_end - incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin());
554 for(std::vector<HalfEdgeHandle>::const_iterator he_it = _hes.begin(),
555 he_end = _hes.end(); he_it != he_end; ++he_it) {
557 incident_hfs_per_he_[*he_it].push_back(hf0);
558 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].push_back(hf1);
564 f.set_halfedges(_hes);
575 if(has_face_bottom_up_incidences()) {
577 const std::vector<HalfFaceHandle>& hfs = c.halffaces();
578 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
579 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
581 incident_cell_per_hf_[*hf_it] = InvalidCellHandle;
584 for(std::vector<HalfFaceHandle>::const_iterator hf_it = _hfs.begin(),
585 hf_end = _hfs.end(); hf_it != hf_end; ++hf_it) {
587 incident_cell_per_hf_[*hf_it] = _ch;
591 c.set_halffaces(_hfs);
610 assert(!is_deleted(_h));
612 std::vector<VertexHandle> vs;
615 std::set<EdgeHandle> incidentEdges_s;
616 get_incident_edges(vs, incidentEdges_s);
618 std::set<FaceHandle> incidentFaces_s;
619 get_incident_faces(incidentEdges_s, incidentFaces_s);
621 std::set<CellHandle> incidentCells_s;
622 get_incident_cells(incidentFaces_s, incidentCells_s);
625 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
626 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
631 for(std::set<FaceHandle>::const_reverse_iterator f_it = incidentFaces_s.rbegin(),
632 f_end = incidentFaces_s.rend(); f_it != f_end; ++f_it) {
637 for(std::set<EdgeHandle>::const_reverse_iterator e_it = incidentEdges_s.rbegin(),
638 e_end = incidentEdges_s.rend(); e_it != e_end; ++e_it) {
662 assert(!is_deleted(_h));
664 std::vector<EdgeHandle> es;
667 std::set<FaceHandle> incidentFaces_s;
668 get_incident_faces(es, incidentFaces_s);
670 std::set<CellHandle> incidentCells_s;
671 get_incident_cells(incidentFaces_s, incidentCells_s);
674 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
675 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
680 for(std::set<FaceHandle>::const_reverse_iterator f_it = incidentFaces_s.rbegin(),
681 f_end = incidentFaces_s.rend(); f_it != f_end; ++f_it) {
705 assert(!is_deleted(_h));
707 std::vector<FaceHandle> fs;
710 std::set<CellHandle> incidentCells_s;
711 get_incident_cells(fs, incidentCells_s);
714 for(std::set<CellHandle>::const_reverse_iterator c_it = incidentCells_s.rbegin(),
715 c_end = incidentCells_s.rend(); c_it != c_end; ++c_it) {
736 assert(!is_deleted(_h));
745 if (!deferred_deletion_enabled() || !needs_garbage_collection())
748 deferred_deletion_ =
false;
750 for (
int i = (
int)
n_cells(); i > 0; --i) {
752 if (is_deleted(ch)) {
753 cell_deleted_[ch] =
false;
757 n_deleted_cells_ = 0;
759 for (
int i = (
int)
n_faces(); i > 0; --i) {
761 if (is_deleted(fh)) {
762 face_deleted_[fh] =
false;
766 n_deleted_faces_ = 0;
768 for (
int i = (
int)
n_edges(); i > 0; --i) {
770 if (is_deleted(eh)) {
771 edge_deleted_[eh] =
false;
775 n_deleted_edges_ = 0;
779 if (is_deleted(vh)) {
780 vertex_deleted_[vh] =
false;
784 n_deleted_vertices_ = 0;
786 deferred_deletion_ =
true;
792template <
class ContainerT>
793void TopologyKernel::get_incident_edges(
const ContainerT& _vs,
794 std::set<EdgeHandle>& _es)
const {
798 if(has_vertex_bottom_up_incidences()) {
800 for(
typename ContainerT::const_iterator v_it = _vs.begin(),
801 v_end = _vs.end(); v_it != v_end; ++v_it) {
803 const std::vector<HalfEdgeHandle>& inc_hes = outgoing_hes_per_vertex_[*v_it];
805 for(std::vector<HalfEdgeHandle>::const_iterator he_it = inc_hes.begin(),
806 he_end = inc_hes.end(); he_it != he_end; ++he_it) {
813 for(
typename ContainerT::const_iterator v_it = _vs.begin(),
814 v_end = _vs.end(); v_it != v_end; ++v_it) {
816 for(EdgeIter e_it = edges_begin(), e_end = edges_end(); e_it != e_end; ++e_it) {
818 const Edge& e =
edge(*e_it);
820 if(e.from_vertex() == *v_it || e.to_vertex() == *v_it) {
830template <
class ContainerT>
831void TopologyKernel::get_incident_faces(
const ContainerT& _es,
832 std::set<FaceHandle>& _fs)
const {
836 if(has_edge_bottom_up_incidences()) {
838 for(
typename ContainerT::const_iterator e_it = _es.begin(),
839 e_end = _es.end(); e_it != e_end; ++e_it) {
841 for(HalfEdgeHalfFaceIter hehf_it = hehf_iter(
halfedge_handle(*e_it, 0));
842 hehf_it.valid(); ++hehf_it) {
844 const FaceHandle fh = face_handle(*hehf_it);
851 for(
typename ContainerT::const_iterator e_it = _es.begin(),
852 e_end = _es.end(); e_it != e_end; ++e_it) {
854 for(FaceIter f_it = faces_begin(),
855 f_end = faces_end(); f_it != f_end; ++f_it) {
857 const std::vector<HalfEdgeHandle>& hes =
face(*f_it).halfedges();
859 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
860 he_end = hes.end(); he_it != he_end; ++he_it) {
874template <
class ContainerT>
875void TopologyKernel::get_incident_cells(
const ContainerT& _fs,
876 std::set<CellHandle>& _cs)
const {
880 if(has_face_bottom_up_incidences()) {
882 for(
typename ContainerT::const_iterator f_it = _fs.begin(),
883 f_end = _fs.end(); f_it != f_end; ++f_it) {
891 if(c0.is_valid()) _cs.insert(c0);
892 if(c1.is_valid()) _cs.insert(c1);
896 for(
typename ContainerT::const_iterator f_it = _fs.begin(),
897 f_end = _fs.end(); f_it != f_end; ++f_it) {
899 for(CellIter c_it = cells_begin(), c_end = cells_end();
900 c_it != c_end; ++c_it) {
902 const std::vector<HalfFaceHandle>& hfs =
cell(*c_it).halffaces();
904 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
905 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
907 if(face_handle(*hf_it) == *f_it) {
939 assert(h.is_valid() && (
size_t)h.idx() <
n_vertices());
941 if (fast_deletion_enabled() && !deferred_deletion_enabled())
944 assert(!vertex_deleted_[last_undeleted_vertex]);
946 h = last_undeleted_vertex;
949 if (deferred_deletion_enabled())
951 ++n_deleted_vertices_;
952 vertex_deleted_[h] =
true;
962 if(has_vertex_bottom_up_incidences()) {
965 for(
int i = h.idx(), end = (
int)
n_vertices(); i < end; ++i) {
966 const std::vector<HalfEdgeHandle>& hes = outgoing_hes_per_vertex_[
VertexHandle(i)];
967 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
968 he_end = hes.end(); he_it != he_end; ++he_it) {
971 if(e.from_vertex().idx() == i) {
974 if(e.to_vertex().idx() == i) {
983 for(
EdgeIter e_it = edges_begin(), e_end = edges_end();
984 e_it != e_end; ++e_it) {
987 if(
edge(*e_it).from_vertex() > h) {
990 if(
edge(*e_it).to_vertex() > h) {
998 if(has_vertex_bottom_up_incidences()) {
999 assert((
size_t)h.idx() < outgoing_hes_per_vertex_.size());
1000 outgoing_hes_per_vertex_.erase(outgoing_hes_per_vertex_.begin() + h.idx());
1007 vertex_deleted_.erase(vertex_deleted_.begin() + h.idx());
1045 assert(h.is_valid() && (
size_t)h.idx() < edges_.size());
1047 if (fast_deletion_enabled() && !deferred_deletion_enabled())
1050 assert(!edge_deleted_[last_edge]);
1057 if(has_vertex_bottom_up_incidences()) {
1061 assert(v0.is_valid() && (
size_t)v0.idx() < outgoing_hes_per_vertex_.size());
1062 assert(v1.is_valid() && (
size_t)v1.idx() < outgoing_hes_per_vertex_.size());
1064 outgoing_hes_per_vertex_[v0].erase(
1065 std::remove(outgoing_hes_per_vertex_[v0].begin(),
1066 outgoing_hes_per_vertex_[v0].end(),
1068 outgoing_hes_per_vertex_[v0].end());
1070 outgoing_hes_per_vertex_[v1].erase(
1071 std::remove(outgoing_hes_per_vertex_[v1].begin(),
1072 outgoing_hes_per_vertex_[v1].end(),
1074 outgoing_hes_per_vertex_[v1].end());
1077 if (deferred_deletion_enabled())
1080 edge_deleted_[h] =
true;
1090 if (!fast_deletion_enabled())
1093 if(has_edge_bottom_up_incidences()) {
1095 assert((
size_t)
halfedge_handle(h, 0).idx() < incident_hfs_per_he_.size());
1100 std::set<FaceHandle> update_faces;
1101 for(std::vector<std::vector<HalfFaceHandle> >::const_iterator iit =
1103 iit_end = incident_hfs_per_he_.end(); iit != iit_end; ++iit) {
1104 for(std::vector<HalfFaceHandle>::const_iterator it = iit->begin(),
1105 end = iit->end(); it != end; ++it) {
1106 update_faces.insert(face_handle(*it));
1111 for(std::set<FaceHandle>::iterator f_it = update_faces.begin(),
1112 f_end = update_faces.end(); f_it != f_end; ++f_it) {
1114 std::vector<HalfEdgeHandle> hes =
face(*f_it).halfedges();
1117 hes.erase(std::remove(hes.begin(), hes.end(),
halfedge_handle(h, 0)), hes.end());
1118 hes.erase(std::remove(hes.begin(), hes.end(),
halfedge_handle(h, 1)), hes.end());
1120 for (
auto &it: hes) {
1121 cor.correctValue(it);
1123 face(*f_it).set_halfedges(hes);
1128 for(
FaceIter f_it = faces_begin(), f_end = faces_end();
1129 f_it != f_end; ++f_it) {
1132 std::vector<HalfEdgeHandle> hes =
face(*f_it).halfedges();
1135 hes.erase(std::remove(hes.begin(), hes.end(),
halfedge_handle(h, 0)), hes.end());
1136 hes.erase(std::remove(hes.begin(), hes.end(),
halfedge_handle(h, 1)), hes.end());
1140 for (
auto &it: hes) {
1141 cor.correctValue(it);
1143 face(*f_it).set_halfedges(hes);
1150 if(has_edge_bottom_up_incidences()) {
1151 assert((
size_t)
halfedge_handle(h, 1).idx() < incident_hfs_per_he_.size());
1153 incident_hfs_per_he_.erase(incident_hfs_per_he_.begin() +
halfedge_handle(h, 1).idx());
1154 incident_hfs_per_he_.erase(incident_hfs_per_he_.begin() +
halfedge_handle(h, 0).idx());
1157 if (!fast_deletion_enabled())
1160 if(has_vertex_bottom_up_incidences()) {
1162 for (
auto &it: outgoing_hes_per_vertex_) {
1163 cor.correctVecValue(it);
1170 edges_.erase(edges_.begin() + h.idx());
1171 edge_deleted_.erase(edge_deleted_.begin() + h.idx());
1210 assert(h.is_valid() && (
size_t)h.idx() < faces_.size());
1213 if (fast_deletion_enabled() && !deferred_deletion_enabled())
1216 assert(!face_deleted_[last_face]);
1222 if(has_edge_bottom_up_incidences()) {
1224 const std::vector<HalfEdgeHandle>& hes =
face(h).halfedges();
1225 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hes.begin(),
1226 he_end = hes.end(); he_it != he_end; ++he_it) {
1228 assert((
size_t)std::max(he_it->idx(), opposite_halfedge_handle(*he_it).idx()) < incident_hfs_per_he_.size());
1230 incident_hfs_per_he_[*he_it].erase(
1231 std::remove(incident_hfs_per_he_[*he_it].begin(),
1232 incident_hfs_per_he_[*he_it].end(),
1236 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].erase(
1237 std::remove(incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].begin(),
1238 incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end(),
1239 halfface_handle(h, 1)), incident_hfs_per_he_[opposite_halfedge_handle(*he_it)].end());
1245 if (deferred_deletion_enabled())
1248 face_deleted_[h] =
true;
1258 if (!fast_deletion_enabled())
1261 if(has_face_bottom_up_incidences()) {
1265 std::set<CellHandle> update_cells;
1266 for(std::vector<CellHandle>::const_iterator c_it = (incident_cell_per_hf_.begin() +
halfface_handle(h, 0).idx()),
1267 c_end = incident_cell_per_hf_.end(); c_it != c_end; ++c_it) {
1268 if(!c_it->is_valid())
continue;
1269 update_cells.insert(*c_it);
1271 for(std::set<CellHandle>::const_iterator c_it = update_cells.begin(),
1272 c_end = update_cells.end(); c_it != c_end; ++c_it) {
1274 std::vector<HalfFaceHandle> hfs =
cell(*c_it).halffaces();
1277 hfs.erase(std::remove(hfs.begin(), hfs.end(),
halfface_handle(h, 0)), hfs.end());
1278 hfs.erase(std::remove(hfs.begin(), hfs.end(),
halfface_handle(h, 1)), hfs.end());
1281 for (
auto &it: hfs) {
1282 cor.correctValue(it);
1284 cell(*c_it).set_halffaces(hfs);
1290 for(
CellIter c_it = cells_begin(), c_end = cells_end(); c_it != c_end; ++c_it) {
1292 std::vector<HalfFaceHandle> hfs =
cell(*c_it).halffaces();
1295 hfs.erase(std::remove(hfs.begin(), hfs.end(),
halfface_handle(h, 0)), hfs.end());
1296 hfs.erase(std::remove(hfs.begin(), hfs.end(),
halfface_handle(h, 1)), hfs.end());
1299 for (
auto &it: hfs) {
1300 cor.correctValue(it);
1302 cell(*c_it).set_halffaces(hfs);
1309 if(has_face_bottom_up_incidences()) {
1310 assert((
size_t)
halfface_handle(h, 1).idx() < incident_cell_per_hf_.size());
1312 incident_cell_per_hf_.erase(incident_cell_per_hf_.begin() +
halfface_handle(h, 1).idx());
1313 incident_cell_per_hf_.erase(incident_cell_per_hf_.begin() +
halfface_handle(h, 0).idx());
1317 if (!fast_deletion_enabled())
1320 if(has_edge_bottom_up_incidences()) {
1322 for (
auto &it: incident_hfs_per_he_) {
1323 cor.correctVecValue(it);
1329 faces_.erase(faces_.begin() + h.idx());
1330 face_deleted_.erase(face_deleted_.begin() + h.idx());
1363 assert(h.is_valid() && (
size_t)h.idx() < cells_.size());
1366 if (fast_deletion_enabled() && !deferred_deletion_enabled())
1369 assert(!cell_deleted_[last_undeleted_cell]);
1371 h = last_undeleted_cell;
1376 if(has_face_bottom_up_incidences()) {
1377 const std::vector<HalfFaceHandle>& hfs =
cell(h).halffaces();
1378 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
1379 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
1380 assert((
size_t)hf_it->idx() < incident_cell_per_hf_.size());
1381 if (incident_cell_per_hf_[*hf_it] == h)
1382 incident_cell_per_hf_[*hf_it] = InvalidCellHandle;
1384 std::set<EdgeHandle> edges;
1385 for(std::vector<HalfFaceHandle>::const_iterator hf_it = hfs.begin(),
1386 hf_end = hfs.end(); hf_it != hf_end; ++hf_it) {
1388 for (
const auto& heh : hf.halfedges())
1391 for (
auto eh : edges)
1395 if (deferred_deletion_enabled())
1398 cell_deleted_[h] =
true;
1408 if (!fast_deletion_enabled())
1410 if(has_face_bottom_up_incidences()) {
1412 for (
auto &it: incident_cell_per_hf_) {
1413 cor.correctValue(it);
1419 cells_.erase(cells_.begin() + h.idx());
1420 cell_deleted_.erase(cell_deleted_.begin() + h.idx());
1433 assert(_h1.idx() >= 0 && _h1.idx() < (
int)cells_.size());
1434 assert(_h2.idx() >= 0 && _h2.idx() < (
int)cells_.size());
1440 for (
const auto hfh: cells_[_h1].halffaces()) {
1441 if (incident_cell_per_hf_[hfh] == _h1)
1442 incident_cell_per_hf_[hfh] = _h2;
1444 for (
const auto hfh: cells_[_h2].halffaces()) {
1445 if (incident_cell_per_hf_[hfh] == _h2)
1446 incident_cell_per_hf_[hfh] = _h1;
1450 std::swap(cells_[_h1], cells_[_h2]);
1451 detail::swap_bool(cell_deleted_[_h1], cell_deleted_[_h2]);
1452 swap_property_elements(_h1, _h2);
1457 assert(_h1.idx() >= 0 && _h1.idx() < (
int)faces_.size());
1458 assert(_h2.idx() >= 0 && _h2.idx() < (
int)faces_.size());
1464 std::vector<unsigned int> ids;
1465 ids.push_back(_h1.idx());
1466 ids.push_back(_h2.idx());
1468 unsigned int id1 = _h1.idx();
1469 unsigned int id2 = _h2.idx();
1474 if (has_face_bottom_up_incidences())
1476 std::set<unsigned int> processed_cells;
1477 for (
unsigned int i = 0; i < 2; ++i)
1479 unsigned int id = ids[i];
1480 for (
unsigned int j = 0; j < 2; ++j)
1489 if (processed_cells.find(ch.idx()) == processed_cells.end())
1492 Cell& c = cells_[ch];
1496 std::vector<HalfFaceHandle> new_halffaces;
1497 for (
unsigned int k = 0; k < c.halffaces().size(); ++k)
1498 if (c.halffaces()[k].idx()/2 == (
int)id1)
1499 new_halffaces.push_back(
HalfFaceHandle(2 * id2 + (c.halffaces()[k].idx() % 2)));
1500 else if (c.halffaces()[k].idx()/2 == (
int)id2)
1501 new_halffaces.push_back(
HalfFaceHandle(2 * id1 + (c.halffaces()[k].idx() % 2)));
1503 new_halffaces.push_back(c.halffaces()[k]);
1504 c.set_halffaces(new_halffaces);
1506 processed_cells.insert(ch.idx());
1514 for (
unsigned int i = 0; i < cells_.size(); ++i)
1519 bool contains_swapped_face =
false;
1520 for (
unsigned int k = 0; k < c.halffaces().size(); ++k)
1522 if (c.halffaces()[k].idx()/2 == (
int)id1)
1523 contains_swapped_face =
true;
1524 if (c.halffaces()[k].idx()/2 == (
int)id2)
1525 contains_swapped_face =
true;
1526 if (contains_swapped_face)
1530 if (contains_swapped_face)
1533 std::vector<HalfFaceHandle> new_halffaces;
1534 for (
unsigned int k = 0; k < c.halffaces().size(); ++k)
1535 if (c.halffaces()[k].idx()/2 == (
int)id1)
1536 new_halffaces.push_back(
HalfFaceHandle(2 * id2 + (c.halffaces()[k].idx() % 2)));
1537 else if (c.halffaces()[k].idx()/2 == (
int)id2)
1538 new_halffaces.push_back(
HalfFaceHandle(2 * id1 + (c.halffaces()[k].idx() % 2)));
1540 new_halffaces.push_back(c.halffaces()[k]);
1541 c.set_halffaces(new_halffaces);
1548 if (has_edge_bottom_up_incidences())
1550 std::set<HalfEdgeHandle> processed_halfedges;
1551 for (
unsigned int i = 0; i < 2; ++i)
1553 unsigned int id = ids[i];
1554 for (
unsigned int j = 0; j < 2; ++j)
1559 for (
unsigned int k = 0; k < hf.halfedges().size(); ++k)
1563 if (processed_halfedges.find(heh) != processed_halfedges.end())
1566 std::vector<HalfFaceHandle>& incident_halffaces = incident_hfs_per_he_[heh];
1567 for (
unsigned int l = 0; l < incident_halffaces.size(); ++l)
1571 if (hfh2.idx()/2 == (
int)id1)
1573 else if (hfh2.idx()/2 == (
int)id2)
1577 processed_halfedges.insert(heh);
1584 std::swap(faces_[_h1], faces_[_h2]);
1585 detail::swap_bool(face_deleted_[_h1], face_deleted_[_h2]);
1586 std::swap(incident_cell_per_hf_[_h1.halfface_handle(0)], incident_cell_per_hf_[_h2.halfface_handle(0)]);
1587 std::swap(incident_cell_per_hf_[_h1.halfface_handle(1)], incident_cell_per_hf_[_h2.halfface_handle(1)]);
1588 swap_property_elements(_h1, _h2);
1596 assert(_h1.idx() >= 0 && _h1.idx() < (
int)edges_.size());
1597 assert(_h2.idx() >= 0 && _h2.idx() < (
int)edges_.size());
1602 std::vector<unsigned int> ids;
1603 ids.push_back(_h1.idx());
1604 ids.push_back(_h2.idx());
1609 if (has_edge_bottom_up_incidences())
1611 std::set<unsigned int> processed_faces;
1613 for (
unsigned int i = 0; i < 2; ++i)
1618 std::vector<HalfFaceHandle>& incident_halffaces = incident_hfs_per_he_[heh];
1619 for (
unsigned int j = 0; j < incident_halffaces.size(); ++j)
1623 unsigned int f_id = hfh.idx() / 2;
1625 if (processed_faces.find(f_id) == processed_faces.end())
1631 std::vector<HalfEdgeHandle> new_halfedges;
1632 for (
unsigned int k = 0; k < f.halfedges().size(); ++k)
1635 if (heh2.idx() / 2 == (
int)ids[0])
1636 new_halfedges.push_back(
HalfEdgeHandle(2*ids[1] + (heh2.idx() % 2)));
1637 else if (heh2.idx() / 2 == (
int)ids[1])
1638 new_halfedges.push_back(
HalfEdgeHandle(2*ids[0] + (heh2.idx() % 2)));
1640 new_halfedges.push_back(heh2);
1642 f.set_halfedges(new_halfedges);
1644 processed_faces.insert(f_id);
1652 for (
unsigned int i = 0; i < faces_.size(); ++i)
1657 bool contains_swapped_edge =
false;
1658 for (
unsigned int k = 0; k < f.halfedges().size(); ++k)
1660 if (f.halfedges()[k].idx()/2 == (
int)ids[0])
1661 contains_swapped_edge =
true;
1662 if (f.halfedges()[k].idx()/2 == (
int)ids[1])
1663 contains_swapped_edge =
true;
1664 if (contains_swapped_edge)
1668 if (contains_swapped_edge)
1671 std::vector<HalfEdgeHandle> new_halfedges;
1672 for (
unsigned int k = 0; k < f.halfedges().size(); ++k)
1675 if (heh2.idx() / 2 == (
int)ids[0])
1676 new_halfedges.push_back(
HalfEdgeHandle(2*ids[1] + (heh2.idx() % 2)));
1677 else if (heh2.idx() / 2 == (
int)ids[1])
1678 new_halfedges.push_back(
HalfEdgeHandle(2*ids[0] + (heh2.idx() % 2)));
1680 new_halfedges.push_back(heh2);
1682 f.set_halfedges(new_halfedges);
1689 if (has_vertex_bottom_up_incidences())
1691 std::set<VertexHandle> processed_vertices;
1692 for (
unsigned int i = 0; i < 2; ++i)
1695 std::vector<VertexHandle> vhs;
1696 vhs.push_back(e.from_vertex());
1697 vhs.push_back(e.to_vertex());
1699 for (
unsigned int j = 0; j < 2; ++j)
1701 if (processed_vertices.find(vhs[j]) != processed_vertices.end())
1704 std::vector<HalfEdgeHandle>& outgoing_hes = outgoing_hes_per_vertex_[vhs[j]];
1705 for (
unsigned int k = 0; k < outgoing_hes.size(); ++k)
1708 if (heh.idx() / 2 == (
int)ids[0])
1710 else if (heh.idx() / 2 == (
int)ids[1])
1713 processed_vertices.insert(vhs[j]);
1720 std::swap(edges_[_h1], edges_[_h2]);
1721 detail::swap_bool(edge_deleted_[_h1], edge_deleted_[_h2]);
1722 std::swap(incident_hfs_per_he_[_h1.halfedge_handle(0)], incident_hfs_per_he_[_h2.halfedge_handle(0)]);
1723 std::swap(incident_hfs_per_he_[_h1.halfedge_handle(1)], incident_hfs_per_he_[_h2.halfedge_handle(1)]);
1724 swap_property_elements(_h1, _h2);
1738 std::array<VH, 2> ids {_h1, _h2};
1742 if (has_vertex_bottom_up_incidences())
1744 std::set<EH> processed_edges;
1745 for (
unsigned int i = 0; i < 2; ++i)
1747 for (
const auto heh: outgoing_hes_per_vertex_[ids[i]]) {
1748 const auto eh = heh.edge_handle();
1750 if (processed_edges.find(eh) == processed_edges.end())
1752 Edge& e = edges_[eh];
1753 if (e.from_vertex() == ids[0])
1754 e.set_from_vertex(ids[1]);
1755 else if (e.from_vertex() == ids[1])
1756 e.set_from_vertex(ids[0]);
1758 if (e.to_vertex() == ids[0])
1759 e.set_to_vertex(ids[1]);
1760 else if (e.to_vertex() == ids[1])
1761 e.set_to_vertex(ids[0]);
1763 processed_edges.insert(eh);
1773 for (
auto &e: edges_)
1775 if (e.from_vertex() == ids[0])
1776 e.set_from_vertex(ids[1]);
1777 else if (e.from_vertex() == ids[1])
1778 e.set_from_vertex(ids[0]);
1780 if (e.to_vertex() == ids[0])
1781 e.set_to_vertex(ids[1]);
1782 else if (e.to_vertex() == ids[1])
1783 e.set_to_vertex(ids[0]);
1788 detail::swap_bool(vertex_deleted_[_h1], vertex_deleted_[_h2]);
1789 std::swap(outgoing_hes_per_vertex_[_h1], outgoing_hes_per_vertex_[_h2]);
1790 swap_property_elements(_h1, _h2);
1794void TopologyKernel::enable_deferred_deletion(
bool _enable)
1796 if (deferred_deletion_ && !_enable)
1799 deferred_deletion_ = _enable;
1808 return edges_[_edgeHandle];
1817 return faces_[_faceHandle];
1826 return cells_[_cellHandle];
1835 return edges_[_edgeHandle];
1845 return faces_[_faceHandle];
1854 return cells_[_cellHandle];
1866 if(_halfEdgeHandle.subidx() == 0)
1867 return edges_[_halfEdgeHandle.edge_handle()];
1881 if(_halfFaceHandle.idx() % 2 == 0)
1882 return faces_[_halfFaceHandle.face_handle()];
1892 return halfedge(_halfEdgeHandle.opposite_handle());
1900 return halfface(_halfFaceHandle.opposite_handle());
1922 if(
halfedge(*voh_it).to_vertex() == _vh2) {
1927 return InvalidHalfEdgeHandle;
1937 for(
auto hfh :
cell(_ch).halffaces())
1939 for(
auto heh :
halfface(hfh).halfedges() )
1944 return opposite_halfedge_handle(heh);
1948 return InvalidHalfEdgeHandle;
1962 assert(_vs.size() > 2);
1966 assert(v0.is_valid() && v1.is_valid() && v2.is_valid());
1969 if(!he0.is_valid())
return InvalidHalfFaceHandle;
1971 if(!he1.is_valid())
return InvalidHalfFaceHandle;
1973 std::vector<HalfEdgeHandle> hes;
1984 assert(_vs.size() > 2);
1988 assert(v0.is_valid() && v1.is_valid() && v2.is_valid());
1991 for(
auto hfh :
cell(_ch).halffaces())
1993 for(
auto heh :
halfface(hfh).halfedges() )
2010 return InvalidHalfFaceHandle;
2017HalfFaceHandle TopologyKernel::halfface_extensive(
const std::vector<VertexHandle>& _vs)
const
2029 assert(_vs.size() > 2);
2034 assert(v0.is_valid() && v1.is_valid());
2037 if(!he0.is_valid())
return InvalidHalfFaceHandle;
2041 std::vector<HalfEdgeHandle> hes =
halfface(*hehf_it).halfedges();
2043 if (hes.size() != _vs.size())
2047 for (
unsigned int i = 0; i < hes.size(); ++i)
2051 bool all_vertices_found =
true;
2053 for (
unsigned int i = 0; i < hes.size(); ++i)
2056 if (
halfedge(heh).from_vertex() != _vs[i])
2058 all_vertices_found =
false;
2063 if (all_vertices_found)
2067 return InvalidHalfFaceHandle;
2082 assert(_hes.size() >= 2);
2086 assert(he0.is_valid() && he1.is_valid());
2090 std::vector<HalfEdgeHandle> hes =
halfface(*hehf_it).halfedges();
2091 if(std::find(hes.begin(), hes.end(), he1) != hes.end()) {
2096 return InvalidHalfFaceHandle;
2103 assert(_heh.is_valid() && (
size_t)_heh.idx() < edges_.size() * 2u);
2104 assert(_hfh.is_valid() && (
size_t)_hfh.idx() < faces_.size() * 2u);
2106 std::vector<HalfEdgeHandle> hes =
halfface(_hfh).halfedges();
2108 for(std::vector<HalfEdgeHandle>::const_iterator it = hes.begin();
2109 it != hes.end(); ++it) {
2111 if((it + 1) != hes.end())
return *(it + 1);
2112 else return *hes.begin();
2116 return InvalidHalfEdgeHandle;
2123 assert(_heh.is_valid() && (
size_t)_heh.idx() < edges_.size() * 2u);
2124 assert(_hfh.is_valid() && (
size_t)_hfh.idx() < faces_.size() * 2u);
2126 std::vector<HalfEdgeHandle> hes =
halfface(_hfh).halfedges();
2128 for(std::vector<HalfEdgeHandle>::const_iterator it = hes.begin();
2129 it != hes.end(); ++it) {
2131 if(it != hes.begin())
return *(it - 1);
2132 else return *(hes.end() - 1);
2136 return InvalidHalfEdgeHandle;
2145 std::vector<VertexHandle> vhs;
2146 vhs.reserve(
valence(hfh.face_handle()));
2159 std::vector<VertexHandle> vertices;
2160 const size_t n =
valence(hfh.face_handle());
2161 vertices.reserve(
n);
2164 auto hfv_it = hfv_iter(hfh, 2);
2165 for (
size_t i = 0; i <
n; ++i)
2167 if (*hfv_it == vh) {
break;}
2172 for (
size_t i = 0; i <
n; ++i)
2174 vertices.push_back(*hfv_it);
2198 const auto f =
face(_fh);
2214 assert(_halfFaceHandle.is_valid() && (
size_t)_halfFaceHandle.idx() < faces_.size() * 2u);
2215 assert(_halfEdgeHandle.is_valid() && (
size_t)_halfEdgeHandle.idx() < edges_.size() * 2u);
2216 assert(has_face_bottom_up_incidences());
2219 if(!ch.is_valid()) {
2221 return InvalidHalfFaceHandle;
2225 bool skipped =
false;
2231 HalfEdgeHandle hehOpp = opposite_halfedge_handle(_halfEdgeHandle);
2232 bool hasHalfedge =
false;
2233 bool hasOppHalfedge =
false;
2234 const auto hf =
halfface(_halfFaceHandle);
2237 hasOppHalfedge =
true;
2238 else if (heh == _halfEdgeHandle)
2243 _halfEdgeHandle = hehOpp;
2245 return InvalidHalfFaceHandle;
2248 for(
const auto &hfh:
cell(ch).halffaces()) {
2249 if(hfh == _halfFaceHandle) {
2252 if (idx.is_valid()) {
2257 for (
const auto heh: hf_cur.halfedges()) {
2260 if(opposite_halfedge_handle(heh) == _halfEdgeHandle && hfh != opposite_halfface_handle(_halfFaceHandle)) {
2261 if (idx.is_valid()) {
2264 return InvalidHalfFaceHandle;
2276 return InvalidHalfFaceHandle;
2284 assert((
size_t)_halfFaceHandle.idx() < incident_cell_per_hf_.size() && _halfFaceHandle.is_valid());
2285 assert(has_face_bottom_up_incidences());
2287 return incident_cell_per_hf_[_halfFaceHandle];
2292void TopologyKernel::compute_vertex_bottom_up_incidences() {
2295 outgoing_hes_per_vertex_.clear();
2296 outgoing_hes_per_vertex_.resize(
n_vertices());
2299 for (
const auto &eh: edges()) {
2300 const auto &e =
edge(eh);
2301 ++n_edges_per_vertex[e.from_vertex()];
2302 ++n_edges_per_vertex[e.to_vertex()];
2304 for (
const auto &vh: vertices()) {
2305 outgoing_hes_per_vertex_[vh].reserve(n_edges_per_vertex[vh]);
2309 for (
const auto eh: edges()) {
2310 const auto &e =
edge(eh);
2311 VertexHandle from = e.from_vertex();
2314 assert((
size_t)from.idx() < outgoing_hes_per_vertex_.size());
2318 VertexHandle to = e.to_vertex();
2319 assert((
size_t)to.idx() < outgoing_hes_per_vertex_.size());
2328void TopologyKernel::compute_edge_bottom_up_incidences() {
2331 incident_hfs_per_he_.clear();
2334 EdgeVector<int> n_faces_per_edge(
n_edges(), 0);
2335 for (
const auto &fh: faces()) {
2336 for (
const auto &heh: face_halfedges(fh)) {
2340 for (
const auto &eh: edges()) {
2341 incident_hfs_per_he_[
halfedge_handle(eh, 0)].reserve(n_faces_per_edge[eh]);
2342 incident_hfs_per_he_[
halfedge_handle(eh, 1)].reserve(n_faces_per_edge[eh]);
2345 for (
const auto &fh: faces()) {
2346 for (
const auto &heh: face_halfedges(fh)) {
2347 auto opp = opposite_halfedge_handle(heh);
2356void TopologyKernel::compute_face_bottom_up_incidences() {
2359 incident_cell_per_hf_.clear();
2360 incident_cell_per_hf_.resize(faces_.size() * 2u, InvalidCellHandle);
2362 for (
const auto ch: cells()) {
2363 for (
const auto hfh: cell_halffaces(ch)) {
2364 if(incident_cell_per_hf_[hfh] == InvalidCellHandle) {
2366 incident_cell_per_hf_[hfh] = ch;
2370 std::cerr <<
"compute_face_bottom_up_incidences(): Detected non-three-manifold configuration!" << std::endl;
2371 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.