35#include <OpenVolumeMesh/Mesh/TetrahedralMeshTopologyKernel.hh>
39namespace OpenVolumeMesh {
43 if(_halfedges.size() != 3) {
45 std::cerr <<
"TetrahedralMeshTopologyKernel::add_face(): Face valence is not three! Returning" << std::endl;
46 std::cerr <<
"invalid handle." << std::endl;
48 return TopologyKernel::InvalidFaceHandle;
60 if(_vertices.size() != 3) {
62 std::cerr <<
"TetrahedralMeshTopologyKernel::add_face(): Face valence is not three! Returning" << std::endl;
63 std::cerr <<
"invalid handle." << std::endl;
65 return TopologyKernel::InvalidFaceHandle;
77 if(_halffaces.size() != 4) {
80 std::cerr <<
"Cell valence is not four! Aborting." << std::endl;
82 return TopologyKernel::InvalidCellHandle;
84 for(
const auto &hfh: _halffaces) {
88 std::cerr <<
"TetrahedralMeshTopologyKernel::add_cell(): Incident face " << hfh.idx() <<
" does not have valence three: " <<
n_halfedges <<
"; not adding cell." << std::endl;
90 return TopologyKernel::InvalidCellHandle;
101 if (he != InvalidHalfEdgeHandle)
107HalfFaceHandle TetrahedralMeshTopologyKernel::add_halfface(
const std::vector<HalfEdgeHandle>& _halfedges,
bool _topologyCheck)
110 if (hf != InvalidHalfFaceHandle)
116HalfFaceHandle TetrahedralMeshTopologyKernel::add_halfface(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2,
bool _topologyCheck)
118 std::vector<HalfEdgeHandle> halfedges;
119 halfedges.push_back(add_halfedge(_vh0, _vh1));
120 halfedges.push_back(add_halfedge(_vh1, _vh2));
121 halfedges.push_back(add_halfedge(_vh2, _vh0));
122 return add_halfface(halfedges, _topologyCheck);
311VertexHandle TetrahedralMeshTopologyKernel::collapse_edge(HalfEdgeHandle _heh)
313 bool deferred_deletion_tmp = deferred_deletion_enabled();
315 if (!deferred_deletion_tmp)
316 enable_deferred_deletion(
true);
318 VertexHandle from_vh =
halfedge(_heh).from_vertex();
319 VertexHandle to_vh =
halfedge(_heh).to_vertex();
323 std::set<CellHandle> collapsingCells;
324 for (HalfEdgeHalfFaceIter hehf_it = hehf_iter(_heh); hehf_it.valid(); ++hehf_it)
326 HalfFaceHandle hfh = *hehf_it;
329 collapsingCells.insert(ch);
332 std::vector<CellHandle> incidentCells;
333 for (VertexCellIter vc_it = vc_iter(from_vh); vc_it.valid(); ++vc_it)
334 incidentCells.push_back(*vc_it);
336 std::vector<std::pair<CellHandle, std::vector<HalfFaceHandle>>> new_cells;
338 for (
const CellHandle &ch: incidentCells)
340 if (collapsingCells.find(ch) != collapsingCells.end())
345 std::vector<HalfFaceHandle> newHalffaces;
346 newHalffaces.reserve(4);
348 for (
unsigned int hf_idx = 0; hf_idx < 4; ++hf_idx)
350 Face hf =
halfface(c.halffaces()[hf_idx]);
351 std::vector<HalfEdgeHandle> newHalfedges;
353 for (
unsigned int j = 0; j < 3; ++j)
355 Edge e =
halfedge(hf.halfedges()[j]);
356 VertexHandle newStart = (e.from_vertex() == from_vh) ? to_vh: e.from_vertex();
357 VertexHandle newEnd = (e.to_vertex() == from_vh) ? to_vh : e.to_vertex();
359 HalfEdgeHandle heh = add_halfedge(newStart, newEnd);
360 newHalfedges.push_back(heh);
361 swap_property_elements(hf.halfedges()[j], heh);
364 HalfFaceHandle hfh = add_halfface(newHalfedges);
365 newHalffaces.push_back(hfh);
366 swap_property_elements(c.halffaces()[hf_idx], hfh);
370 new_cells.emplace_back(ch, newHalffaces);
373 VertexHandle survivingVertex = to_vh;
375 if (!deferred_deletion_tmp)
377 if (fast_deletion_enabled())
381 survivingVertex = from_vh;
386 if (from_vh.idx() < to_vh.idx())
387 survivingVertex = VertexHandle(to_vh.idx() - 1);
393 for (
const auto &
n: new_cells) {
394 CellHandle newCell =
add_cell(std::move(
n.second));
395 swap_property_elements(
n.first, newCell);
399 enable_deferred_deletion(deferred_deletion_tmp);
401 return survivingVertex;
406void TetrahedralMeshTopologyKernel::split_edge(HalfEdgeHandle _heh, VertexHandle _vh)
408 bool deferred_deletion_tmp = deferred_deletion_enabled();
410 if (!deferred_deletion_tmp)
411 enable_deferred_deletion(
true);
413 std::vector<HalfFaceHandle> incident_halffaces_with_cells;
414 for (HalfEdgeHalfFaceIter hehf_it = hehf_iter(_heh); hehf_it.valid(); ++hehf_it)
418 incident_halffaces_with_cells.push_back(*hehf_it);
421 std::vector<std::pair<CellHandle, std::array<VertexHandle, 4>>> new_cells;
423 for (
auto hfh : incident_halffaces_with_cells)
427 std::vector<VertexHandle> vertices = get_cell_vertices(hfh, _heh);
431 new_cells.emplace_back(ch, std::array<VertexHandle, 4>{vertices[0], _vh, vertices[2], vertices[3]});
432 new_cells.emplace_back(ch, std::array<VertexHandle, 4>{_vh, vertices[1], vertices[2], vertices[3]});
437 for (
const auto &
n: new_cells) {
438 const auto &vhs =
n.second;
439 CellHandle newCell =
add_cell(vhs[0], vhs[1], vhs[2], vhs[3]);
440 copy_property_elements(
n.first, newCell);
444 enable_deferred_deletion(deferred_deletion_tmp);
449void TetrahedralMeshTopologyKernel::split_face(FaceHandle _fh, VertexHandle _vh)
451 bool deferred_deletion_tmp = deferred_deletion_enabled();
453 if (!deferred_deletion_tmp)
454 enable_deferred_deletion(
true);
456 std::vector<std::pair<CellHandle, std::array<VertexHandle, 4>>> new_cells;
458 for (
char i = 0; i < 2; ++i)
464 std::vector<VertexHandle> vertices = get_cell_vertices(hfh);
467 new_cells.emplace_back(ch, std::array<VertexHandle, 4>{vertices[0], vertices[1], _vh, vertices[3]});
468 new_cells.emplace_back(ch, std::array<VertexHandle, 4>{vertices[0], _vh, vertices[2], vertices[3]});
469 new_cells.emplace_back(ch, std::array<VertexHandle, 4>{_vh, vertices[1], vertices[2], vertices[3]});
475 for (
const auto &
n: new_cells) {
476 const auto &vhs =
n.second;
477 CellHandle newCell =
add_cell(vhs[0], vhs[1], vhs[2], vhs[3]);
478 copy_property_elements(
n.first, newCell);
481 enable_deferred_deletion(deferred_deletion_tmp);
486std::vector<VertexHandle> TetrahedralMeshTopologyKernel::get_cell_vertices(CellHandle ch)
const
488 return get_cell_vertices(
cell(ch).halffaces().front());
491std::vector<VertexHandle> TetrahedralMeshTopologyKernel::get_cell_vertices(CellHandle ch, VertexHandle vh)
const
493 HalfFaceHandle hfh =
cell(ch).halffaces()[0];
496 for (
unsigned int i = 0; i < 3; ++i)
498 Edge e =
halfedge(f.halfedges()[i]);
499 if (e.from_vertex() == vh)
501 heh = f.halfedges()[i];
511 return get_cell_vertices(hfh,heh);
515std::vector<VertexHandle> TetrahedralMeshTopologyKernel::get_cell_vertices(HalfFaceHandle hfh)
const
517 return get_cell_vertices(hfh,
halfface(hfh).halfedges().front());
520std::vector<VertexHandle> TetrahedralMeshTopologyKernel::get_cell_vertices(HalfFaceHandle hfh, HalfEdgeHandle heh)
const
522 std::vector<VertexHandle> vertices;
525 for (
unsigned int i = 0; i < 3; ++i)
528 vertices.push_back(e.from_vertex());
533 HalfFaceHandle otherHfh = c.halffaces()[0];
535 otherHfh = c.halffaces()[1];
539 for (
unsigned int i = 0; i < otherF.halfedges().size(); ++i)
541 HalfEdgeHandle he = otherF.halfedges()[i];
543 if (std::find(vertices.begin(), vertices.end(), e.to_vertex()) == vertices.end())
545 vertices.push_back(e.to_vertex());
553VertexHandle TetrahedralMeshTopologyKernel::halfface_opposite_vertex(HalfFaceHandle hfh)
const
555 if (is_boundary(hfh)) {
556 return InvalidVertexHandle;
560 for (CellVertexIter it = cv_iter(
incident_cell(hfh)); it.valid(); ++it) {
561 const VertexHandle vh = *it;
562 if (vh != base[0] && vh != base[1] && vh != base[2]) {
567 return InvalidVertexHandle;
576 if(_vertices.size() != 4) {
577 return CellHandle(-1);
581 assert(TopologyKernel::has_full_bottom_up_incidences());
584 if(!TopologyKernel::has_full_bottom_up_incidences()) {
585 return CellHandle(-1);
589 HalfFaceHandle hf0, hf1, hf2, hf3;
591 std::vector<VertexHandle> vs;
593 vs.push_back(_vertices[0]);
594 vs.push_back(_vertices[1]);
595 vs.push_back(_vertices[2]);
597 if(!hf0.is_valid()) {
603 vs.push_back(_vertices[0]);
604 vs.push_back(_vertices[2]);
605 vs.push_back(_vertices[3]);
607 if(!hf1.is_valid()) {
613 vs.push_back(_vertices[0]);
614 vs.push_back(_vertices[3]);
615 vs.push_back(_vertices[1]);
617 if(!hf2.is_valid()) {
623 vs.push_back(_vertices[1]);
624 vs.push_back(_vertices[3]);
625 vs.push_back(_vertices[2]);
627 if(!hf3.is_valid()) {
633 assert(hf0.is_valid());
634 assert(hf1.is_valid());
635 assert(hf2.is_valid());
636 assert(hf3.is_valid());
639 std::vector<HalfFaceHandle> hfs;
645 if (_topologyCheck) {
654 std::set<HalfEdgeHandle> incidentHalfedges;
655 std::set<EdgeHandle> incidentEdges;
657 for(std::vector<HalfFaceHandle>::const_iterator it = hfs.begin(),
658 end = hfs.end(); it != end; ++it) {
660 OpenVolumeMeshFace hface =
halfface(*it);
661 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hface.halfedges().begin(),
662 he_end = hface.halfedges().end(); he_it != he_end; ++he_it) {
663 incidentHalfedges.insert(*he_it);
668 if(incidentHalfedges.size() != (incidentEdges.size() * 2u)) {
670 std::cerr <<
"The specified halffaces are not connected!" << std::endl;
672 return InvalidCellHandle;
676 if(has_face_bottom_up_incidences()) {
678 for(std::vector<HalfFaceHandle>::const_iterator it = hfs.begin(),
679 end = hfs.end(); it != end; ++it) {
682 std::cerr <<
"Warning: One of the specified half-faces is already incident to another cell!" << std::endl;
684 return InvalidCellHandle;
697 std::vector<HalfFaceHandle> halffaces;
698 halffaces.push_back(add_halfface(_vh0, _vh1, _vh2));
699 halffaces.push_back(add_halfface(_vh0, _vh2, _vh3));
700 halffaces.push_back(add_halfface(_vh0, _vh3, _vh1));
701 halffaces.push_back(add_halfface(_vh1, _vh3, _vh2));
702 return add_cell(halffaces, _topologyCheck);
size_t n() const
Get number of entities of given kind in mesh.
CellHandle add_cell(std::vector< HalfFaceHandle > _halffaces, bool _topologyCheck=false) override
Add cell via incident halffaces.
FaceHandle add_face(std::vector< HalfEdgeHandle > _halfedges, bool _topologyCheck=false) override
Add face via incident edges.
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.
const Cell & cell(CellHandle _cellHandle) const
Get cell with handle _cellHandle.
size_t n_halfedges() const override
Get number of halfedges in mesh.
HalfEdgeHandle prev_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get previous halfedge within a halfface.
static HalfEdgeHandle halfedge_handle(EdgeHandle _h, const unsigned char _subIdx)
Conversion function.
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.
HalfEdgeHandle next_halfedge_in_halfface(HalfEdgeHandle _heh, HalfFaceHandle _hfh) const
Get next halfedge within a halfface.
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.
virtual CellHandle add_cell(std::vector< HalfFaceHandle > _halffaces, bool _topologyCheck=false)
Add cell via incident halffaces.
std::vector< VertexHandle > get_halfface_vertices(HalfFaceHandle hfh) const
Get vertices of a halfface.
Face halfface(HalfFaceHandle _halfFaceHandle) const
Get face that corresponds to halfface with handle _halfFaceHandle.
Edge halfedge(HalfEdgeHandle _halfEdgeHandle) const
Get edge that corresponds to halfedge with handle _halfEdgeHandle.
HalfFaceHandle find_halfface(const std::vector< VertexHandle > &_vs) const
virtual EdgeHandle add_edge(VertexHandle _fromVertex, VertexHandle _toHandle, bool _allowDuplicates=false)
Add edge.
virtual EdgeIter delete_edge(EdgeHandle _h)
Delete edge from mesh.
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...