diff --git a/MeshLib/MeshEditing/MeshRevision.cpp b/MeshLib/MeshEditing/MeshRevision.cpp index b6d720f0f0c3ab3d80f09c941d515d249e8e7c93..69a7575d568c9860fb11394f06f58f058e13a0f6 100644 --- a/MeshLib/MeshEditing/MeshRevision.cpp +++ b/MeshLib/MeshEditing/MeshRevision.cpp @@ -48,7 +48,7 @@ MeshLib::Mesh* MeshRevision::collapseNodes(const std::string &new_mesh_name, dou std::vector<MeshLib::Node*> new_nodes (this->constructNewNodesArray(this->collapseNodeIndices(eps))); std::vector<MeshLib::Element*> new_elements (MeshLib::copyElementVector(_mesh.getElements(), new_nodes)); this->resetNodeIDs(); - return new MeshLib::Mesh(new_mesh_name, new_nodes, new_elements); + return new MeshLib::Mesh(new_mesh_name, new_nodes, new_elements, _mesh.getProperties()); } unsigned MeshRevision::getNCollapsableNodes(double eps) const @@ -62,44 +62,73 @@ unsigned MeshRevision::getNCollapsableNodes(double eps) const return count; } -MeshLib::Mesh* MeshRevision::simplifyMesh(const std::string &new_mesh_name, double eps, unsigned min_elem_dim) +MeshLib::Mesh* MeshRevision::simplifyMesh(const std::string &new_mesh_name, + double eps, unsigned min_elem_dim) { if (this->_mesh.getNElements() == 0) return nullptr; + // original data + std::vector<MeshLib::Element*> const& elements(this->_mesh.getElements()); + MeshLib::Properties const& properties(_mesh.getProperties()); + boost::optional<MeshLib::PropertyVector<int> const&> material_vec( + properties.getPropertyVector<int>("MaterialIDs")); + + // data structures for the new mesh std::vector<MeshLib::Node*> new_nodes = this->constructNewNodesArray(this->collapseNodeIndices(eps)); std::vector<MeshLib::Element*> new_elements; + MeshLib::Properties new_properties; + boost::optional<PropertyVector<int> &> new_material_vec; + if (material_vec) { + new_properties.createNewPropertyVector<int>( + "MaterialIDs", MeshItemType::Cell, 1); + } - const std::vector<MeshLib::Element*> &elements(this->_mesh.getElements()); - for (auto elem = elements.begin(); elem != elements.end(); ++elem) - { - unsigned n_unique_nodes(this->getNUniqueNodes(*elem)); - if (n_unique_nodes == (*elem)->getNBaseNodes() && (*elem)->getDimension() >= min_elem_dim) + for (std::size_t k(0); k<elements.size(); ++k) { + MeshLib::Element const*const elem(elements[k]); + unsigned n_unique_nodes(this->getNUniqueNodes(elem)); + if (n_unique_nodes == elem->getNBaseNodes() + && elem->getDimension() >= min_elem_dim) { - ElementErrorCode e((*elem)->validate()); + ElementErrorCode e(elem->validate()); if (e[ElementErrorFlag::NonCoplanar]) { - if (!this->subdivideElement(*elem, new_nodes, new_elements)) + std::size_t const n_new_elements( + subdivideElement(elem, new_nodes, new_elements)); + if (n_new_elements == 0) { - ERR("Error: Element %d has unknown element type.", std::distance(elements.begin(), elem)); + ERR("Error: Element %d has unknown element type.", k); this->resetNodeIDs(); this->cleanUp(new_nodes, new_elements); return nullptr; } + if (!material_vec) + continue; + new_material_vec->insert(new_material_vec->end(), + n_new_elements, (*material_vec)[k]); + } else { + new_elements.push_back(MeshLib::copyElement(elem, new_nodes)); + // copy material values + if (material_vec) + new_material_vec->push_back((*material_vec)[k]); } - else - new_elements.push_back(MeshLib::copyElement(*elem, new_nodes)); } - else if (n_unique_nodes < (*elem)->getNBaseNodes() && n_unique_nodes>1) - reduceElement(*elem, n_unique_nodes, new_nodes, new_elements, min_elem_dim); - else + else if (n_unique_nodes < elem->getNBaseNodes() && n_unique_nodes>1) { + std::size_t const n_new_elements(reduceElement( + elem, n_unique_nodes, new_nodes, new_elements, min_elem_dim) + ); + if (!material_vec) + continue; + new_material_vec->insert(new_material_vec->end(), + n_new_elements, (*material_vec)[k]); + } else ERR ("Something is wrong, more unique nodes than actual nodes"); - } this->resetNodeIDs(); if (!new_elements.empty()) - return new MeshLib::Mesh(new_mesh_name, new_nodes, new_elements); + return new MeshLib::Mesh( + new_mesh_name, new_nodes, new_elements, new_properties); this->cleanUp(new_nodes, new_elements); return nullptr; @@ -110,28 +139,52 @@ MeshLib::Mesh* MeshRevision::subdivideMesh(const std::string &new_mesh_name) con if (this->_mesh.getNElements() == 0) return nullptr; + // original data + std::vector<MeshLib::Element*> const& elements(this->_mesh.getElements()); + MeshLib::Properties const& properties(_mesh.getProperties()); + boost::optional<MeshLib::PropertyVector<int> const&> material_vec( + properties.getPropertyVector<int>("MaterialIDs")); + + // data structures for the new mesh std::vector<MeshLib::Node*> new_nodes = MeshLib::copyNodeVector(_mesh.getNodes()); std::vector<MeshLib::Element*> new_elements; + MeshLib::Properties new_properties; + boost::optional<PropertyVector<int> &> new_material_vec; + if (material_vec) { + new_material_vec = new_properties.createNewPropertyVector<int>( + "MaterialIDs", MeshItemType::Cell, 1 + ); + } - const std::vector<MeshLib::Element*> &elements(this->_mesh.getElements()); - for (auto elem = elements.begin(); elem != elements.end(); ++elem) - { - ElementErrorCode e((*elem)->validate()); - if (e[ElementErrorFlag::NonCoplanar]) + for (std::size_t k(0); k<elements.size(); ++k) { + MeshLib::Element const*const elem(elements[k]); + ElementErrorCode error_code(elem->validate()); + if (error_code[ElementErrorFlag::NonCoplanar]) { - if (!this->subdivideElement(*elem, new_nodes, new_elements)) + std::size_t const n_new_elements( + subdivideElement(elem, new_nodes, new_elements)); + if (n_new_elements == 0) { - ERR("Error: Element %d has unknown element type.", std::distance(elements.begin(), elem)); + ERR("Error: Element %d has unknown element type.", k); this->cleanUp(new_nodes, new_elements); return nullptr; } + // copy material values + if (!material_vec) + continue; + new_material_vec->insert(new_material_vec->end(), n_new_elements, + (*material_vec)[k]); + } else { + new_elements.push_back(MeshLib::copyElement(elem, new_nodes)); + // copy material values + if (material_vec) + new_material_vec->push_back((*material_vec)[k]); } - else - new_elements.push_back(MeshLib::copyElement(*elem, new_nodes)); } if (!new_elements.empty()) - return new MeshLib::Mesh(new_mesh_name, new_nodes, new_elements); + return new MeshLib::Mesh( + new_mesh_name, new_nodes, new_elements, new_properties); this->cleanUp(new_nodes, new_elements); return nullptr; @@ -227,24 +280,23 @@ void MeshRevision::resetNodeIDs() nodes[i]->setID(i); } -bool MeshRevision::subdivideElement( +std::size_t MeshRevision::subdivideElement( MeshLib::Element const*const element, std::vector<MeshLib::Node*> const& nodes, std::vector<MeshLib::Element*> & elements) const { - unsigned n_new_elems (0); if (element->getGeomType() == MeshElemType::QUAD) - n_new_elems = this->subdivideQuad(element, nodes, elements); + return this->subdivideQuad(element, nodes, elements); else if (element->getGeomType() == MeshElemType::HEXAHEDRON) - n_new_elems = this->subdivideHex(element, nodes, elements); + return this->subdivideHex(element, nodes, elements); else if (element->getGeomType() == MeshElemType::PYRAMID) - n_new_elems = this->subdividePyramid(element, nodes, elements); + return this->subdividePyramid(element, nodes, elements); else if (element->getGeomType() == MeshElemType::PRISM) - n_new_elems = this->subdividePrism(element, nodes, elements); - return (n_new_elems > 0); + return this->subdividePrism(element, nodes, elements); + return 0; } -void MeshRevision::reduceElement(MeshLib::Element const*const element, +std::size_t MeshRevision::reduceElement(MeshLib::Element const*const element, unsigned n_unique_nodes, std::vector<MeshLib::Node*> const& nodes, std::vector<MeshLib::Element*> & elements, @@ -254,23 +306,30 @@ void MeshRevision::reduceElement(MeshLib::Element const*const element, * TODO: modify neighbouring elements if one elements has been subdivided ***************/ if (element->getGeomType() == MeshElemType::TRIANGLE && min_elem_dim == 1) + { elements.push_back (this->constructLine(element, nodes)); - else if ((element->getGeomType() == MeshElemType::QUAD) || - (element->getGeomType() == MeshElemType::TETRAHEDRON)) + return 1; + } else + if ((element->getGeomType() == MeshElemType::QUAD) || + (element->getGeomType() == MeshElemType::TETRAHEDRON)) { if (n_unique_nodes == 3 && min_elem_dim < 3) elements.push_back (this->constructTri(element, nodes)); else if (min_elem_dim == 1) elements.push_back (this->constructLine(element, nodes)); + return 1; } - else if (element->getGeomType() == MeshElemType::HEXAHEDRON) - this->reduceHex(element, n_unique_nodes, nodes, elements, min_elem_dim); - else if (element->getGeomType() == MeshElemType::PYRAMID) + else if (element->getGeomType() == MeshElemType::HEXAHEDRON) { + return reduceHex(element, n_unique_nodes, nodes, elements, min_elem_dim); + } else if (element->getGeomType() == MeshElemType::PYRAMID) { this->reducePyramid(element, n_unique_nodes, nodes, elements, min_elem_dim); - else if (element->getGeomType() == MeshElemType::PRISM) - this->reducePrism(element, n_unique_nodes, nodes, elements, min_elem_dim); - else - ERR ("Error: Unknown element type."); + return 1; + } else if (element->getGeomType() == MeshElemType::PRISM) { + return reducePrism(element, n_unique_nodes, nodes, elements, min_elem_dim); + } + + ERR ("Error: Unknown element type."); + return 0; } unsigned MeshRevision::subdivideQuad(MeshLib::Element const*const quad, @@ -281,13 +340,13 @@ unsigned MeshRevision::subdivideQuad(MeshLib::Element const*const quad, tri1_nodes[0] = nodes[quad->getNode(0)->getID()]; tri1_nodes[1] = nodes[quad->getNode(1)->getID()]; tri1_nodes[2] = nodes[quad->getNode(2)->getID()]; - new_elements.push_back(new MeshLib::Tri(tri1_nodes, quad->getValue())); + new_elements.push_back(new MeshLib::Tri(tri1_nodes)); MeshLib::Node** tri2_nodes = new MeshLib::Node*[3]; tri2_nodes[0] = nodes[quad->getNode(0)->getID()]; tri2_nodes[1] = nodes[quad->getNode(2)->getID()]; tri2_nodes[2] = nodes[quad->getNode(3)->getID()]; - new_elements.push_back(new MeshLib::Tri(tri2_nodes, quad->getValue())); + new_elements.push_back(new MeshLib::Tri(tri2_nodes)); return 2; } @@ -303,7 +362,7 @@ unsigned MeshRevision::subdivideHex(MeshLib::Element const*const hex, prism1_nodes[3] = nodes[hex->getNode(4)->getID()]; prism1_nodes[4] = nodes[hex->getNode(6)->getID()]; prism1_nodes[5] = nodes[hex->getNode(5)->getID()]; - MeshLib::Prism* prism1 (new MeshLib::Prism(prism1_nodes, hex->getValue())); + MeshLib::Prism* prism1 (new MeshLib::Prism(prism1_nodes)); this->subdividePrism(prism1, nodes, new_elements); delete prism1; @@ -314,7 +373,7 @@ unsigned MeshRevision::subdivideHex(MeshLib::Element const*const hex, prism2_nodes[3] = nodes[hex->getNode(0)->getID()]; prism2_nodes[4] = nodes[hex->getNode(2)->getID()]; prism2_nodes[5] = nodes[hex->getNode(3)->getID()]; - MeshLib::Prism* prism2 (new MeshLib::Prism(prism2_nodes, hex->getValue())); + MeshLib::Prism* prism2 (new MeshLib::Prism(prism2_nodes)); this->subdividePrism(prism2, nodes, new_elements); delete prism2; @@ -330,14 +389,14 @@ unsigned MeshRevision::subdividePyramid(MeshLib::Element const*const pyramid, tet1_nodes[1] = nodes[pyramid->getNode(1)->getID()]; tet1_nodes[2] = nodes[pyramid->getNode(2)->getID()]; tet1_nodes[3] = nodes[pyramid->getNode(4)->getID()]; - new_elements.push_back(new MeshLib::Tet(tet1_nodes, pyramid->getValue())); + new_elements.push_back(new MeshLib::Tet(tet1_nodes)); MeshLib::Node** tet2_nodes = new MeshLib::Node*[4]; tet2_nodes[0] = nodes[pyramid->getNode(0)->getID()]; tet2_nodes[1] = nodes[pyramid->getNode(2)->getID()]; tet2_nodes[2] = nodes[pyramid->getNode(3)->getID()]; tet2_nodes[3] = nodes[pyramid->getNode(4)->getID()]; - new_elements.push_back(new MeshLib::Tet(tet2_nodes, pyramid->getValue())); + new_elements.push_back(new MeshLib::Tet(tet2_nodes)); return 2; } @@ -351,21 +410,21 @@ unsigned MeshRevision::subdividePrism(MeshLib::Element const*const prism, tet1_nodes[1] = nodes[prism->getNode(1)->getID()]; tet1_nodes[2] = nodes[prism->getNode(2)->getID()]; tet1_nodes[3] = nodes[prism->getNode(3)->getID()]; - new_elements.push_back(new MeshLib::Tet(tet1_nodes, prism->getValue())); + new_elements.push_back(new MeshLib::Tet(tet1_nodes)); MeshLib::Node** tet2_nodes = new MeshLib::Node*[4]; tet2_nodes[0] = nodes[prism->getNode(3)->getID()]; tet2_nodes[1] = nodes[prism->getNode(2)->getID()]; tet2_nodes[2] = nodes[prism->getNode(4)->getID()]; tet2_nodes[3] = nodes[prism->getNode(5)->getID()]; - new_elements.push_back(new MeshLib::Tet(tet2_nodes, prism->getValue())); + new_elements.push_back(new MeshLib::Tet(tet2_nodes)); MeshLib::Node** tet3_nodes = new MeshLib::Node*[4]; tet3_nodes[0] = nodes[prism->getNode(2)->getID()]; tet3_nodes[1] = nodes[prism->getNode(1)->getID()]; tet3_nodes[2] = nodes[prism->getNode(3)->getID()]; tet3_nodes[3] = nodes[prism->getNode(4)->getID()]; - new_elements.push_back(new MeshLib::Tet(tet3_nodes, prism->getValue())); + new_elements.push_back(new MeshLib::Tet(tet3_nodes)); return 3; } @@ -394,7 +453,7 @@ unsigned MeshRevision::reduceHex(MeshLib::Element const*const org_elem, pyr_nodes[2] = nodes[org_elem->getNode(base_nodes[2])->getID()]; pyr_nodes[3] = nodes[org_elem->getNode(base_nodes[3])->getID()]; pyr_nodes[4] = nodes[org_elem->getNode(i)->getID()]; - new_elements.push_back (new MeshLib::Pyramid(pyr_nodes, org_elem->getValue())); + new_elements.push_back (new MeshLib::Pyramid(pyr_nodes)); if (i<4 && j>=4) std::swap(i,j); MeshLib::Node** prism_nodes = new MeshLib::Node*[6]; @@ -404,7 +463,7 @@ unsigned MeshRevision::reduceHex(MeshLib::Element const*const org_elem, prism_nodes[3] = nodes[org_elem->getNode(base_nodes[1])->getID()]; prism_nodes[4] = nodes[org_elem->getNode(base_nodes[2])->getID()]; prism_nodes[5] = nodes[org_elem->getNode(this->lutHexDiametralNode(i))->getID()]; - new_elements.push_back (new MeshLib::Prism(prism_nodes, org_elem->getValue())); + new_elements.push_back (new MeshLib::Prism(prism_nodes)); return 2; } } @@ -423,7 +482,7 @@ unsigned MeshRevision::reduceHex(MeshLib::Element const*const org_elem, prism_nodes[3] = nodes[org_elem->getNode(this->lutHexDiametralNode(org_elem->getNodeIDinElement(face->getNode(2))))->getID()]; prism_nodes[4] = nodes[org_elem->getNode(this->lutHexDiametralNode(org_elem->getNodeIDinElement(face->getNode(3))))->getID()]; prism_nodes[5] = nodes[org_elem->getNode(org_elem->getNodeIDinElement(face->getNode(0)))->getID()]; - new_elements.push_back (new MeshLib::Prism(prism_nodes, org_elem->getValue())); + new_elements.push_back (new MeshLib::Prism(prism_nodes)); delete face; return 1; } @@ -466,7 +525,7 @@ unsigned MeshRevision::reduceHex(MeshLib::Element const*const org_elem, pris1_nodes[3] = const_cast<MeshLib::Node*>(org_elem->getNode(back.second)); pris1_nodes[4] = const_cast<MeshLib::Node*>(org_elem->getNode(cutting_plane[1])); pris1_nodes[5] = const_cast<MeshLib::Node*>(org_elem->getNode(cutting_plane[2])); - MeshLib::Prism* prism1 (new MeshLib::Prism(pris1_nodes, org_elem->getValue())); + MeshLib::Prism* prism1 (new MeshLib::Prism(pris1_nodes)); unsigned nNewElements = this->reducePrism(prism1, 5, nodes, new_elements, min_elem_dim); delete prism1; @@ -477,7 +536,7 @@ unsigned MeshRevision::reduceHex(MeshLib::Element const*const org_elem, pris2_nodes[3] = const_cast<MeshLib::Node*>(org_elem->getNode(this->lutHexDiametralNode(back.second))); pris2_nodes[4] = const_cast<MeshLib::Node*>(org_elem->getNode(cutting_plane[1])); pris2_nodes[5] = const_cast<MeshLib::Node*>(org_elem->getNode(cutting_plane[2])); - MeshLib::Prism* prism2 (new MeshLib::Prism(pris2_nodes, org_elem->getValue())); + MeshLib::Prism* prism2 (new MeshLib::Prism(pris2_nodes)); nNewElements += this->reducePrism(prism2, 5, nodes, new_elements, min_elem_dim); delete prism2; return nNewElements; @@ -500,7 +559,7 @@ unsigned MeshRevision::reduceHex(MeshLib::Element const*const org_elem, tet1_nodes[1] = nodes[first_four_nodes[1]]; tet1_nodes[2] = nodes[first_four_nodes[2]]; tet1_nodes[3] = nodes[org_elem->getNode(fifth_node)->getID()]; - new_elements.push_back(new MeshLib::Tet(tet1_nodes, org_elem->getValue())); + new_elements.push_back(new MeshLib::Tet(tet1_nodes)); } else new_elements.push_back(tet1); @@ -510,7 +569,7 @@ unsigned MeshRevision::reduceHex(MeshLib::Element const*const org_elem, tet2_nodes[1] = nodes[first_four_nodes[2]]; tet2_nodes[2] = nodes[first_four_nodes[3]]; tet2_nodes[3] = nodes[org_elem->getNode(fifth_node)->getID()]; - new_elements.push_back(new MeshLib::Tet(tet2_nodes, org_elem->getValue())); + new_elements.push_back(new MeshLib::Tet(tet2_nodes)); return 2; } else if (n_unique_nodes == 4) @@ -579,14 +638,14 @@ unsigned MeshRevision::reducePrism(MeshLib::Element const*const org_elem, tet1_nodes[1] = nodes[org_elem->getNode((i+2)%3)->getID()]; tet1_nodes[2] = nodes[org_elem->getNode(i)->getID()]; tet1_nodes[3] = nodes[org_elem->getNode((i+1)%3+3)->getID()]; - new_elements.push_back (new MeshLib::Tet(tet1_nodes, org_elem->getValue())); + new_elements.push_back (new MeshLib::Tet(tet1_nodes)); MeshLib::Node** tet2_nodes = new MeshLib::Node*[4]; tet2_nodes[0] = nodes[org_elem->getNode((i+1)%3+3)->getID()]; tet2_nodes[1] = nodes[org_elem->getNode((i+2)%3)->getID()]; tet2_nodes[2] = nodes[org_elem->getNode(i)->getID()]; tet2_nodes[3] = nodes[org_elem->getNode((i+2)%3+3)->getID()]; - new_elements.push_back (new MeshLib::Tet(tet2_nodes, org_elem->getValue())); + new_elements.push_back (new MeshLib::Tet(tet2_nodes)); return 2; } @@ -603,7 +662,7 @@ unsigned MeshRevision::reducePrism(MeshLib::Element const*const org_elem, tet1_nodes[1] = nodes[org_elem->getNode(j+offset)->getID()]; tet1_nodes[2] = nodes[org_elem->getNode(k+offset)->getID()]; tet1_nodes[3] = nodes[org_elem->getNode(i)->getID()]; - new_elements.push_back (new MeshLib::Tet(tet1_nodes, org_elem->getValue())); + new_elements.push_back (new MeshLib::Tet(tet1_nodes)); unsigned l = (GeoLib::isCoplanar(*org_elem->getNode(i+offset), *org_elem->getNode(k+offset), *org_elem->getNode(i), *org_elem->getNode(k))) ? j : i; MeshLib::Node** tet2_nodes = new MeshLib::Node*[4]; @@ -611,7 +670,7 @@ unsigned MeshRevision::reducePrism(MeshLib::Element const*const org_elem, tet2_nodes[1] = nodes[org_elem->getNode(k+offset)->getID()]; tet2_nodes[2] = nodes[org_elem->getNode(i)->getID()]; tet2_nodes[3] = nodes[org_elem->getNode(k)->getID()]; - new_elements.push_back (new MeshLib::Tet(tet2_nodes, org_elem->getValue())); + new_elements.push_back (new MeshLib::Tet(tet2_nodes)); return 2; } } @@ -643,7 +702,7 @@ MeshLib::Element* MeshRevision::constructLine(MeshLib::Element const*const eleme } } assert(line_nodes[1] != nullptr); - return new MeshLib::Line(line_nodes, element->getValue()); + return new MeshLib::Line(line_nodes); } MeshLib::Element* MeshRevision::constructTri(MeshLib::Element const*const element, @@ -672,7 +731,7 @@ MeshLib::Element* MeshRevision::constructTri(MeshLib::Element const*const elemen } } assert(tri_nodes[2] != nullptr); - return new MeshLib::Tri(tri_nodes, element->getValue()); + return new MeshLib::Tri(tri_nodes); } MeshLib::Element* MeshRevision::constructFourNodeElement( @@ -704,7 +763,7 @@ MeshLib::Element* MeshRevision::constructFourNodeElement( const bool isQuad (GeoLib::isCoplanar(*new_nodes[0], *new_nodes[1], *new_nodes[2], *new_nodes[3])); if (isQuad && min_elem_dim < 3) { - MeshLib::Element* elem (new MeshLib::Quad(new_nodes, element->getValue())); + MeshLib::Element* elem (new MeshLib::Quad(new_nodes)); for (unsigned i=1; i<3; ++i) { if (elem->validate().none()) @@ -720,7 +779,7 @@ MeshLib::Element* MeshRevision::constructFourNodeElement( return elem; } else if (!isQuad) - return new MeshLib::Tet(new_nodes, element->getValue()); + return new MeshLib::Tet(new_nodes); else // is quad but min elem dim == 3 return nullptr; } diff --git a/MeshLib/MeshEditing/MeshRevision.h b/MeshLib/MeshEditing/MeshRevision.h index 7c9b3ceb3defc91fac4add0bff8966f8aedfc5d2..92a8e9ab0495b440e9a96cd2f3aae362e2752d7c 100644 --- a/MeshLib/MeshEditing/MeshRevision.h +++ b/MeshLib/MeshEditing/MeshRevision.h @@ -66,7 +66,8 @@ public: * @param min_elem_dim Minimum dimension of elements to be inserted into new mesh (i.e. * min_elem_dim=3 will prevent the new mesh to contain 2D elements) */ - MeshLib::Mesh* simplifyMesh(const std::string &new_mesh_name, double eps, unsigned min_elem_dim = 1); + MeshLib::Mesh* simplifyMesh(const std::string &new_mesh_name, double eps, + unsigned min_elem_dim = 1); /** * Create a new mesh where all elements with nonplanar faces are subdivided into simpler @@ -76,7 +77,8 @@ public: private: /// Constructs a new node vector for the resulting mesh by removing all nodes whose ID indicates they need to be merged/removed. - std::vector<MeshLib::Node*> constructNewNodesArray(const std::vector<std::size_t> &id_map) const; + std::vector<MeshLib::Node*> constructNewNodesArray( + const std::vector<std::size_t> &id_map) const; /// Calculates the number of unique nodes in an element (i.e. uncollapsed nodes) unsigned getNUniqueNodes(MeshLib::Element const*const element) const; @@ -85,52 +87,74 @@ private: void resetNodeIDs(); /// Subdivides an element if it has a face that is not coplanar - bool subdivideElement(MeshLib::Element const*const element, const std::vector<MeshLib::Node*> &nodes, std::vector<MeshLib::Element*> &elements) const; + /// @param element the element that will be subdivided + /// @param nodes vector containing the nodes the elements originated by the + /// subdivision are based on + /// @param elements vector of MeshLib::Elements; the elements originated by + /// the subdivision will be inserted into elements + /// @return the number of elements originated by the subdivision + std::size_t subdivideElement(MeshLib::Element const*const element, + std::vector<MeshLib::Node*> const& nodes, + std::vector<MeshLib::Element*> & elements) const; // Revises an element by removing collapsed nodes, using the nodes vector from the result mesh. - void reduceElement(MeshLib::Element const*const element, - unsigned n_unique_nodes, - const std::vector<MeshLib::Node*> &nodes, - std::vector<MeshLib::Element*> &elements, - unsigned min_elem_dim) const; + std::size_t reduceElement(MeshLib::Element const*const element, + unsigned n_unique_nodes, + const std::vector<MeshLib::Node*> &nodes, + std::vector<MeshLib::Element*> &elements, + unsigned min_elem_dim) const; /// Cleans up all nodes and elements if something went wrong - void cleanUp(std::vector<MeshLib::Node*> &nodes, std::vector<MeshLib::Element*> &new_elements) const; + void cleanUp(std::vector<MeshLib::Node*> &nodes, + std::vector<MeshLib::Element*> &new_elements) const; /// Subdivides a nonplanar quad into two triangles - unsigned subdivideQuad(MeshLib::Element const*const quad, const std::vector<MeshLib::Node*> &nodes, std::vector<MeshLib::Element*> &new_elements) const; + unsigned subdivideQuad(MeshLib::Element const*const quad, + const std::vector<MeshLib::Node*> &nodes, + std::vector<MeshLib::Element*> &new_elements) const; /// Subdivides a Hex with nonplanar faces into tets - unsigned subdivideHex(MeshLib::Element const*const hex, const std::vector<MeshLib::Node*> &nodes, std::vector<MeshLib::Element*> &new_elements) const; + unsigned subdivideHex(MeshLib::Element const*const hex, + const std::vector<MeshLib::Node*> &nodes, + std::vector<MeshLib::Element*> &new_elements) const; /// Subdivides a pyramid with a nonplanar base into two tets - unsigned subdividePyramid(MeshLib::Element const*const pyramid, const std::vector<MeshLib::Node*> &nodes, std::vector<MeshLib::Element*> &new_elements) const; + unsigned subdividePyramid(MeshLib::Element const*const pyramid, + const std::vector<MeshLib::Node*> &nodes, + std::vector<MeshLib::Element*> &new_elements) const; /// Subdivides a prism with nonplanar quad faces into two tets - unsigned subdividePrism(MeshLib::Element const*const prism, const std::vector<MeshLib::Node*> &nodes, std::vector<MeshLib::Element*> &new_elements) const; + unsigned subdividePrism(MeshLib::Element const*const prism, + const std::vector<MeshLib::Node*> &nodes, + std::vector<MeshLib::Element*> &new_elements) const; /// Creates a line element from the first two unique nodes found in the element (element *should* have exactly two unique nodes!) - MeshLib::Element* constructLine(MeshLib::Element const*const element, const std::vector<MeshLib::Node*> &nodes) const; + MeshLib::Element* constructLine(MeshLib::Element const*const element, + const std::vector<MeshLib::Node*> &nodes) const; /// Creates a triangle element from the first three unique nodes found in the element (element *should* have exactly three unique nodes!) - MeshLib::Element* constructTri(MeshLib::Element const*const element, const std::vector<MeshLib::Node*> &nodes) const; + MeshLib::Element* constructTri(MeshLib::Element const*const element, + const std::vector<MeshLib::Node*> &nodes) const; /// Creates a quad or a tet, depending if the four nodes being coplanar or not (element *should* have exactly four unique nodes!) - MeshLib::Element* constructFourNodeElement(MeshLib::Element const*const element, const std::vector<MeshLib::Node*> &nodes, unsigned min_elem_dim = 1) const; + MeshLib::Element* constructFourNodeElement( + MeshLib::Element const*const element, + const std::vector<MeshLib::Node*> &nodes, + unsigned min_elem_dim = 1) const; /** * Reduces a hexahedron element by removing collapsed nodes and constructing one or more new elements from the remaining nodes. * @return The number of newly created elements */ unsigned reduceHex(MeshLib::Element const*const hex, - unsigned n_unique_nodes, - const std::vector<MeshLib::Node*> &nodes, - std::vector<MeshLib::Element*> &new_elements, - unsigned min_elem_dim) const; + unsigned n_unique_nodes, + const std::vector<MeshLib::Node*> &nodes, + std::vector<MeshLib::Element*> &new_elements, + unsigned min_elem_dim) const; /// Reduces a pyramid element by removing collapsed nodes and constructing a new elements from the remaining nodes. void reducePyramid(MeshLib::Element const*const pyramid, - unsigned n_unique_nodes, - const std::vector<MeshLib::Node*> &nodes, - std::vector<MeshLib::Element*> &new_elements, - unsigned min_elem_dim) const; + unsigned n_unique_nodes, + const std::vector<MeshLib::Node*> &nodes, + std::vector<MeshLib::Element*> &new_elements, + unsigned min_elem_dim) const; /** * Reduces a prism element by removing collapsed nodes and constructing one or two new elements from the remaining nodes. * @return The number of newly created elements @@ -152,7 +176,8 @@ private: const std::array<unsigned,4> lutHexCuttingQuadNodes(unsigned id1, unsigned id2) const; /// When a hex is subdivided into two prisms, this returns the nodes of the hex edge that will serve as the back of one of the prisms. - const std::pair<unsigned, unsigned> lutHexBackNodes(unsigned i, unsigned j, unsigned k, unsigned l) const; + const std::pair<unsigned, unsigned> lutHexBackNodes( + unsigned i, unsigned j, unsigned k, unsigned l) const; /// Lookup-table for returning the third node of bottom or top triangle given the other two unsigned lutPrismThirdNode(unsigned id1, unsigned id2) const;