OGS
findElementsWithinRadius.cpp
Go to the documentation of this file.
1
12
13#include <set>
14#include <unordered_set>
15#include <vector>
16
17#include "Elements/Element.h"
18#include "MathLib/MathTools.h"
19#include "Node.h"
20
21namespace MeshLib
22{
23std::vector<std::size_t> findElementsWithinRadius(Element const& start_element,
24 double const radius_squared)
25{
26 // Special case for 0 radius. All other radii will include at least one
27 // neighbor of the start element.
28 if (radius_squared == 0.)
29 {
30 return {start_element.getID()};
31 }
32
33 // Collect start element node coordinates into local contigiuos memory.
34 std::vector<MathLib::Point3d> start_element_nodes;
35 {
36 auto const start_element_n_nodes = start_element.getNumberOfNodes();
37 start_element_nodes.reserve(start_element_n_nodes);
38 for (unsigned n = 0; n < start_element_n_nodes; ++n)
39 {
40 start_element_nodes.push_back(*start_element.getNode(n));
41 }
42 }
43
44 // Returns true if the test node is inside the radius of any of the
45 // element's nodes.
46 auto node_inside_radius =
47 [&start_element_nodes, radius_squared](Node const* test_node)
48 {
49 return std::any_of(
50 start_element_nodes.begin(), start_element_nodes.end(),
51 [test_node, &radius_squared](auto const node)
52 { return MathLib::sqrDist(*test_node, node) <= radius_squared; });
53 };
54
55 // Returns true if any of the test element's nodes is inside the start
56 // element's radius.
57 auto element_in_radius = [&node_inside_radius](Element const& element)
58 {
59 auto const n_nodes = element.getNumberOfNodes();
60 for (unsigned i = 0; i < n_nodes; ++i)
61 {
62 if (node_inside_radius(element.getNode(i)))
63 {
64 return true;
65 }
66 }
67 return false;
68 };
69
70 std::set<std::size_t> found_elements;
71 std::vector<Element const*> neighbors_to_visit;
72 std::unordered_set<std::size_t> visited_elements;
73
74 auto mark_visited_and_add_neighbors =
75 [&found_elements, &neighbors_to_visit, &visited_elements](
76 Element const& element)
77 {
78 found_elements.insert(element.getID());
79 visited_elements.insert(element.getID());
80 auto const n_neighbors = element.getNumberOfNeighbors();
81 for (unsigned n = 0; n < n_neighbors; ++n)
82 {
83 auto neighbor = element.getNeighbor(n);
84 if (neighbor == nullptr)
85 {
86 continue;
87 }
88 auto x = visited_elements.find(neighbor->getID());
89 if (x != visited_elements.end())
90 {
91 continue;
92 }
93
94 neighbors_to_visit.push_back(neighbor);
95
96 visited_elements.insert(neighbor->getID());
97 }
98 };
99
100 // The result always contains the starting element.
101 mark_visited_and_add_neighbors(start_element);
102
103 while (!neighbors_to_visit.empty())
104 {
105 auto const& current_element = *neighbors_to_visit.back();
106 neighbors_to_visit.pop_back();
107
108 // If any node is inside the radius, all neighbors are visited.
109 if (element_in_radius(current_element))
110 {
111 mark_visited_and_add_neighbors(current_element);
112 }
113 }
114
115 return {std::begin(found_elements), std::end(found_elements)};
116}
117} // namespace MeshLib
Definition of the Element class.
Definition of the Node class.
virtual unsigned getNumberOfNodes() const =0
virtual const Node * getNode(unsigned idx) const =0
std::size_t getID() const
Returns the ID of the element.
Definition Element.h:89
std::vector< std::size_t > findElementsWithinRadius(Element const &start_element, double const radius_squared)