diff --git a/MeshLib/MeshEditing/RemoveMeshComponents.cpp b/MeshLib/MeshEditing/RemoveMeshComponents.cpp index 2409dc14474e42315035b1bf6502790dbf94ffbe..98cc70bf8940b44866220ba5872cd076a5a8d048 100644 --- a/MeshLib/MeshEditing/RemoveMeshComponents.cpp +++ b/MeshLib/MeshEditing/RemoveMeshComponents.cpp @@ -63,7 +63,7 @@ MeshLib::Mesh* removeElements(const MeshLib::Mesh& mesh, const std::vector<std:: // delete unused nodes NodeSearch ns(mesh); - ns.searchByElementIDs(removed_element_ids, true); + ns.searchNodesConnectedToOnlyGivenElements(removed_element_ids); auto &removed_node_ids(ns.getSearchedNodeIDs()); INFO("Removing total %d nodes...", removed_node_ids.size()); for (auto nodeid : removed_node_ids) diff --git a/MeshLib/MeshSearch/ElementSearch.cpp b/MeshLib/MeshSearch/ElementSearch.cpp index a8d165ef08749c064b5ab2176075e85da7c23131..e31d1eb6c8565717c62f853bb675b50ab79cea64 100644 --- a/MeshLib/MeshSearch/ElementSearch.cpp +++ b/MeshLib/MeshSearch/ElementSearch.cpp @@ -42,30 +42,33 @@ std::size_t ElementSearch::searchByMaterialID(int const matID) return matchedIDs.size(); } -std::size_t ElementSearch::searchByElementType(MeshElemType eleType) +template <typename Container, typename Predicate> +std::vector<std::size_t> filter(Container const& container, Predicate const& p) { - const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements()); std::vector<std::size_t> matchedIDs; std::size_t i = 0; - for (MeshLib::Element* ele : ele_vec) { - if (ele->getGeomType()==eleType) + for (auto value : container) { + if (p(value)) matchedIDs.push_back(i); i++; } + return matchedIDs; +} + +std::size_t ElementSearch::searchByElementType(MeshElemType eleType) +{ + auto matchedIDs = filter(_mesh.getElements(), + [&](MeshLib::Element* e) { return e->getGeomType()==eleType; }); + this->updateUnion(matchedIDs); return matchedIDs.size(); } std::size_t ElementSearch::searchByContent(double eps) { - const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements()); - std::vector<std::size_t> matchedIDs; - std::size_t i = 0; - for (MeshLib::Element* ele : ele_vec) { - if (ele->getContent() < eps) - matchedIDs.push_back(i); - i++; - } + auto matchedIDs = filter(_mesh.getElements(), + [&eps](MeshLib::Element* e) { return e->getContent() < eps; }); + this->updateUnion(matchedIDs); return matchedIDs.size(); } @@ -73,20 +76,15 @@ std::size_t ElementSearch::searchByContent(double eps) std::size_t ElementSearch::searchByBoundingBox( GeoLib::AABB<MathLib::Point3d> const& aabb) { - const std::vector<MeshLib::Element*> &ele_vec (this->_mesh.getElements()); + auto matchedIDs = filter(_mesh.getElements(), + [&aabb](MeshLib::Element* e) { + std::size_t const nElemNodes (e->getNBaseNodes()); + for (std::size_t n=0; n < nElemNodes; ++n) + if (aabb.containsPoint(*e->getNode(n))) + return true; // any node of element is in aabb. + return false; // no nodes of element are in aabb. + }); - std::vector<std::size_t> matchedIDs; - const std::size_t n_elems(ele_vec.size()); - for (std::size_t i = 0; i<n_elems; i++) - { - std::size_t nElemNodes (ele_vec[i]->getNBaseNodes()); - for (std::size_t j=0; j<nElemNodes; ++j) - if (!aabb.containsPoint(*ele_vec[i]->getNode(j))) - { - matchedIDs.push_back(i); - break; - } - } this->updateUnion(matchedIDs); return matchedIDs.size(); } @@ -94,16 +92,16 @@ std::size_t ElementSearch::searchByBoundingBox( std::size_t ElementSearch::searchByNodeIDs(const std::vector<std::size_t> &nodes) { std::vector<std::size_t> connected_elements; - std::for_each(nodes.begin(), nodes.end(), - [&](std::size_t node_id) - { - for (auto* e : _mesh.getNode(node_id)->getElements()) { - connected_elements.push_back(e->getID()); - } - }); + for (std::size_t node_id : nodes) + { + for (auto* e : _mesh.getNode(node_id)->getElements()) { + connected_elements.push_back(e->getID()); + } + } std::sort(connected_elements.begin(), connected_elements.end()); auto it = std::unique(connected_elements.begin(), connected_elements.end()); connected_elements.resize(std::distance(connected_elements.begin(),it)); + this->updateUnion(connected_elements); return connected_elements.size(); } diff --git a/MeshLib/MeshSearch/NodeSearch.cpp b/MeshLib/MeshSearch/NodeSearch.cpp index 81efa477843fe4a1fecdb72297ed2b8fedae32dc..cd5587d0531c028732f0d52306c8f0e9d81f0d9d 100644 --- a/MeshLib/MeshSearch/NodeSearch.cpp +++ b/MeshLib/MeshSearch/NodeSearch.cpp @@ -24,38 +24,33 @@ NodeSearch::NodeSearch(const MeshLib::Mesh &mesh) { } -std::size_t NodeSearch::searchByElementIDs(const std::vector<std::size_t> &elements, bool only_match_all_connected_elements) +std::size_t NodeSearch::searchNodesConnectedToOnlyGivenElements( + const std::vector<std::size_t> &elements) { - std::vector<std::size_t> connected_nodes; - if (only_match_all_connected_elements) + // Find out by how many elements a node would be removed. + // + // Note: If there are only few elements to be removed, using a different + // algorithm might be more memory efficient. + std::vector<std::size_t> node_marked_counts(_mesh.getNNodes(), 0); + + for(std::size_t eid : elements) { - std::vector<std::size_t> node_marked_counts(_mesh.getNNodes(), 0); //this approach is not optimum for memory size - std::for_each(elements.begin(), elements.end(), - [&](std::size_t eid) - { - auto* e = _mesh.getElement(eid); - for (unsigned i=0; i<e->getNBaseNodes(); i++) { - node_marked_counts[e->getNodeIndex(i)]++; - } - }); - for (std::size_t i=0; i<node_marked_counts.size(); i++) - { - if (node_marked_counts[i] == _mesh.getNode(i)->getElements().size()) - connected_nodes.push_back(i); + auto* e = _mesh.getElement(eid); + for (unsigned i=0; i<e->getNBaseNodes(); i++) { + node_marked_counts[e->getNodeIndex(i)]++; } - } else { - std::for_each(elements.begin(), elements.end(), - [&](std::size_t eid) - { - auto* e = _mesh.getElement(eid); - for (unsigned i=0; i<e->getNBaseNodes(); i++) { - connected_nodes.push_back(e->getNodeIndex(i)); - } - }); - std::sort(connected_nodes.begin(), connected_nodes.end()); - auto it = std::unique(connected_nodes.begin(), connected_nodes.end()); - connected_nodes.resize(std::distance(connected_nodes.begin(),it)); } + + + // Push back nodes which counts are equal to number of connected elements to + // that node. + std::vector<std::size_t> connected_nodes; + for (std::size_t i=0; i<node_marked_counts.size(); i++) + { + if (node_marked_counts[i] == _mesh.getNode(i)->getElements().size()) + connected_nodes.push_back(i); + } + this->updateUnion(connected_nodes); return connected_nodes.size(); } diff --git a/MeshLib/MeshSearch/NodeSearch.h b/MeshLib/MeshSearch/NodeSearch.h index 8a8df377faf2451ba521535ec333c3d7539b65fc..ad2b36a6b1565f7147b0ea96ad8112957a3b32d0 100644 --- a/MeshLib/MeshSearch/NodeSearch.h +++ b/MeshLib/MeshSearch/NodeSearch.h @@ -29,8 +29,9 @@ public: /// return marked node IDs const std::vector<std::size_t>& getSearchedNodeIDs() const {return _marked_nodes; } - /// Marks all nodes connecting to any of the given elements - std::size_t searchByElementIDs(const std::vector<std::size_t> &element_ids, bool only_match_all_connected_elements = false); + /// Marks all nodes connected to any of the given elements ids. + /// \return number of connected nodes. + std::size_t searchNodesConnectedToOnlyGivenElements(const std::vector<std::size_t> &element_ids); /// Marks all unused nodes std::size_t searchUnused();