diff --git a/MeshLib/MeshSearch/NodeSearch.cpp b/MeshLib/MeshSearch/NodeSearch.cpp index 4b185b47742d8e075113f330c498d796d7a334b8..5bffe4d8cbb36af174cbd2d81e9bebef2720278b 100644 --- a/MeshLib/MeshSearch/NodeSearch.cpp +++ b/MeshLib/MeshSearch/NodeSearch.cpp @@ -69,6 +69,63 @@ std::size_t NodeSearch::searchUnused() return del_node_idx.size(); } +std::size_t NodeSearch::searchBoundaryNodes() +{ + std::vector<std::size_t> vec_boundary_nodes; + if (_mesh.getDimension() == 1) + { + for (MeshLib::Node const* n : _mesh.getNodes()) + if (n->getElements().size() == 1) + vec_boundary_nodes.push_back(n->getID()); + } + else if (_mesh.getDimension() == 2) + { + for (MeshLib::Element const* elem : _mesh.getElements()) + { + if (elem->getDimension() < _mesh.getDimension()) + continue; + if (!elem->isBoundaryElement()) + continue; + + std::size_t const n_edges (elem->getNumberOfEdges()); + for (std::size_t i=0; i<n_edges; ++i) + { + if (elem->getNeighbor(i) != nullptr) + continue; + std::unique_ptr<MeshLib::Element const> edge(elem->getEdge(i)); + for (unsigned j=0; j<edge->getNumberOfNodes(); j++) + vec_boundary_nodes.push_back(edge->getNode(j)->getID()); + } + } + } + else + { + for (MeshLib::Element const* elem : _mesh.getElements()) + { + if (elem->getDimension() < _mesh.getDimension()) + continue; + if (!elem->isBoundaryElement()) + continue; + + std::size_t const n_faces (elem->getNumberOfFaces()); + for (std::size_t i=0; i<n_faces; ++i) + { + if (elem->getNeighbor(i) != nullptr) + continue; + std::unique_ptr<MeshLib::Element const> face(elem->getFace(i)); + for (unsigned j=0; j<face->getNumberOfNodes(); j++) + vec_boundary_nodes.push_back(face->getNode(j)->getID()); + } + } + } + std::sort(vec_boundary_nodes.begin(), vec_boundary_nodes.end()); + vec_boundary_nodes.erase(std::unique(vec_boundary_nodes.begin(), vec_boundary_nodes.end()), vec_boundary_nodes.end()); + + + this->updateUnion(vec_boundary_nodes); + return vec_boundary_nodes.size(); +} + void NodeSearch::updateUnion(const std::vector<std::size_t> &vec) { std::vector<std::size_t> vec_temp(vec.size() + _marked_nodes.size()); diff --git a/MeshLib/MeshSearch/NodeSearch.h b/MeshLib/MeshSearch/NodeSearch.h index dfc2d38c6553039b86d51c391807689aba09edee..1392b5fa99ab58103783f1d0dac30c52e4bb2a86 100644 --- a/MeshLib/MeshSearch/NodeSearch.h +++ b/MeshLib/MeshSearch/NodeSearch.h @@ -36,6 +36,9 @@ public: /// Marks all unused nodes std::size_t searchUnused(); + /// Marks all boundary nodes + std::size_t searchBoundaryNodes(); + private: /// Updates the vector of marked items with values from vec. void updateUnion(const std::vector<std::size_t> &vec); diff --git a/Tests/MeshLib/TestNodeSearch.cpp b/Tests/MeshLib/TestNodeSearch.cpp index 631f393c6d36ff90f85e0cc642a30df37c2b7b9d..1efc228e7b39c08d57c236e992ada6dc4e012a30 100644 --- a/Tests/MeshLib/TestNodeSearch.cpp +++ b/Tests/MeshLib/TestNodeSearch.cpp @@ -15,6 +15,7 @@ #include "MeshLib/Elements/Element.h" #include "MeshLib/MeshSearch/NodeSearch.h" #include "MeshLib/MeshGenerators/RasterToMesh.h" +#include "MeshLib/MeshGenerators/MeshGenerator.h" #include "MeshLib/MeshEditing/DuplicateMeshComponents.h" #include "GeoLib/Raster.h" @@ -45,4 +46,61 @@ TEST(NodeSearch, UnusedNodes) } +TEST(NodeSearch, BoundaryNodes1D) +{ + std::unique_ptr<MeshLib::Mesh> mesh (MeshLib::MeshGenerator::generateLineMesh(5, 1.0)); + MeshLib::NodeSearch ns(*mesh); + ns.searchBoundaryNodes(); + std::vector<std::size_t> searched_nodes = ns.getSearchedNodeIDs(); + ASSERT_EQ(2, searched_nodes.size()); + ASSERT_EQ(0u, searched_nodes[0]); + ASSERT_EQ(5u, searched_nodes[1]); +} + +TEST(NodeSearch, BoundaryNodes2D) +{ + std::unique_ptr<MeshLib::Mesh> mesh (MeshLib::MeshGenerator::generateRegularQuadMesh(5, 5, 1.0, 1.0)); + MeshLib::NodeSearch ns(*mesh); + ns.searchBoundaryNodes(); + std::vector<std::size_t> searched_nodes = ns.getSearchedNodeIDs(); + ASSERT_EQ(20, searched_nodes.size()); + for (auto nodeid : searched_nodes) + { + auto &node = *mesh->getNode(nodeid); + bool isOnBnd = false; + for (unsigned i=0; i<mesh->getDimension(); i++) + { + if (node[i]==0.0 || node[i]==5.0) + { + isOnBnd = true; + break; + } + } + ASSERT_TRUE(isOnBnd); + } +} + +TEST(NodeSearch, BoundaryNodes3D) +{ + std::unique_ptr<MeshLib::Mesh> mesh (MeshLib::MeshGenerator::generateRegularHexMesh(5, 5, 5, 1.0, 1.0, 1.0)); + MeshLib::NodeSearch ns(*mesh); + ns.searchBoundaryNodes(); + std::vector<std::size_t> searched_nodes = ns.getSearchedNodeIDs(); + ASSERT_EQ(152u, searched_nodes.size()); + for (auto nodeid : searched_nodes) + { + auto &node = *mesh->getNode(nodeid); + bool isOnBnd = false; + for (unsigned i=0; i<mesh->getDimension(); i++) + { + if (node[i]==0.0 || node[i]==5.0) + { + isOnBnd = true; + break; + } + } + + ASSERT_TRUE(isOnBnd); + } +}