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)
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)
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);
495 if (vhs[1]==vh) {
return {vhs[1], vhs[2], vhs[0], vhs[3]};}
496 if (vhs[2]==vh) {
return {vhs[2], vhs[0], vhs[1], vhs[3]};}
497 if (vhs[3]==vh) {
return {vhs[3], vhs[1], vhs[0], vhs[2]};}
504 assert(ch.is_valid());
505 if (!ch.is_valid())
return {};
507 const auto& hfhs =
cell(ch).halffaces();
510 std::vector<VertexHandle> cell_vhs;
513 cell_vhs.push_back(vh);
518 for (
VertexHandle other_vh : halfface_vertices(other_hfh))
520 if (cell_vhs[0] != other_vh && cell_vhs[1] != other_vh && cell_vhs[2] != other_vh)
522 cell_vhs.push_back(other_vh);
541 if (vhs[1] == vh0) vhs = {vhs[1],vhs[2],vhs[0],vhs[3]};
542 else if (vhs[2] == vh0) vhs = {vhs[2],vhs[0],vhs[1],vhs[3]};
545 if (vhs[2] == vh1) vhs = {vhs[0],vhs[1],vhs[2],vhs[3]};
546 else if (vhs[3] == vh1) vhs = {vhs[0],vhs[1],vhs[2],vhs[3]};
561 if (vhs[0] != vh && vhs[1] != vh && vhs[2] != vh)
566 return InvalidHalfFaceHandle;
575 if(_vertices.size() != 4) {
580 assert(TopologyKernel::has_full_bottom_up_incidences());
583 if(!TopologyKernel::has_full_bottom_up_incidences()) {
584 return CellHandle(-1);
588 HalfFaceHandle hf0, hf1, hf2, hf3;
590 std::vector<VertexHandle> vs;
592 vs.push_back(_vertices[0]);
593 vs.push_back(_vertices[1]);
594 vs.push_back(_vertices[2]);
596 if(!hf0.is_valid()) {
602 vs.push_back(_vertices[0]);
603 vs.push_back(_vertices[2]);
604 vs.push_back(_vertices[3]);
606 if(!hf1.is_valid()) {
612 vs.push_back(_vertices[0]);
613 vs.push_back(_vertices[3]);
614 vs.push_back(_vertices[1]);
616 if(!hf2.is_valid()) {
622 vs.push_back(_vertices[1]);
623 vs.push_back(_vertices[3]);
624 vs.push_back(_vertices[2]);
626 if(!hf3.is_valid()) {
632 assert(hf0.is_valid());
633 assert(hf1.is_valid());
634 assert(hf2.is_valid());
635 assert(hf3.is_valid());
638 std::vector<HalfFaceHandle> hfs;
644 if (_topologyCheck) {
653 std::set<HalfEdgeHandle> incidentHalfedges;
654 std::set<EdgeHandle> incidentEdges;
656 for(std::vector<HalfFaceHandle>::const_iterator it = hfs.begin(),
657 end = hfs.end(); it != end; ++it) {
659 OpenVolumeMeshFace hface =
halfface(*it);
660 for(std::vector<HalfEdgeHandle>::const_iterator he_it = hface.halfedges().begin(),
661 he_end = hface.halfedges().end(); he_it != he_end; ++he_it) {
662 incidentHalfedges.insert(*he_it);
667 if(incidentHalfedges.size() != (incidentEdges.size() * 2u)) {
669 std::cerr <<
"The specified halffaces are not connected!" << std::endl;
671 return InvalidCellHandle;
675 if(has_face_bottom_up_incidences()) {
677 for(std::vector<HalfFaceHandle>::const_iterator it = hfs.begin(),
678 end = hfs.end(); it != end; ++it) {
681 std::cerr <<
"Warning: One of the specified half-faces is already incident to another cell!" << std::endl;
683 return InvalidCellHandle;
696 std::vector<HalfFaceHandle> halffaces;
697 halffaces.push_back(add_halfface(_vh0, _vh1, _vh2));
698 halffaces.push_back(add_halfface(_vh0, _vh2, _vh3));
699 halffaces.push_back(add_halfface(_vh0, _vh3, _vh1));
700 halffaces.push_back(add_halfface(_vh1, _vh3, _vh2));
701 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.
std::vector< VertexHandle > get_cell_vertices(CellHandle ch) const
FaceHandle add_face(std::vector< HalfEdgeHandle > _halfedges, bool _topologyCheck=false) override
Add face via incident edges.
HalfFaceHandle vertex_opposite_halfface(CellHandle ch, VertexHandle vh) const
Get the first halfface of the tet ch that does not contain the vertex vh.
VertexHandle halfface_opposite_vertex(HalfFaceHandle hfh) const
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.
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.
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.
VertexHandle from_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge starts from.
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.
VertexHandle to_vertex_handle(HalfEdgeHandle _h) const
Get the vertex the halfedge points to.