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 
21 namespace MeshLib
22 {
23 std::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  for (auto const& n : start_element_nodes)
50  {
51  if (MathLib::sqrDist(*test_node, n) <= radius_squared)
52  {
53  return true;
54  }
55  }
56  return false;
57  };
58 
59  // Returns true if any of the test element's nodes is inside the start
60  // element's radius.
61  auto element_in_radius = [&node_inside_radius](Element const& element)
62  {
63  auto const n_nodes = element.getNumberOfNodes();
64  for (unsigned i = 0; i < n_nodes; ++i)
65  {
66  if (node_inside_radius(element.getNode(i)))
67  {
68  return true;
69  }
70  }
71  return false;
72  };
73 
74  std::set<std::size_t> found_elements;
75  std::vector<Element const*> neighbors_to_visit;
76  std::unordered_set<std::size_t> visited_elements;
77 
78  auto mark_visited_and_add_neighbors =
79  [&found_elements, &neighbors_to_visit, &visited_elements](
80  Element const& element)
81  {
82  found_elements.insert(element.getID());
83  visited_elements.insert(element.getID());
84  auto const n_neighbors = element.getNumberOfNeighbors();
85  for (unsigned n = 0; n < n_neighbors; ++n)
86  {
87  auto neighbor = element.getNeighbor(n);
88  if (neighbor == nullptr)
89  {
90  continue;
91  }
92  auto x = visited_elements.find(neighbor->getID());
93  if (x != visited_elements.end())
94  {
95  continue;
96  }
97 
98  neighbors_to_visit.push_back(neighbor);
99 
100  visited_elements.insert(neighbor->getID());
101  }
102  };
103 
104  // The result always contains the starting element.
105  mark_visited_and_add_neighbors(start_element);
106 
107  while (!neighbors_to_visit.empty())
108  {
109  auto const& current_element = *neighbors_to_visit.back();
110  neighbors_to_visit.pop_back();
111 
112  // If any node is inside the radius, all neighbors are visited.
113  if (element_in_radius(current_element))
114  {
115  mark_visited_and_add_neighbors(current_element);
116  }
117  }
118 
119  return {std::begin(found_elements), std::end(found_elements)};
120 }
121 } // namespace MeshLib
Definition of the Element class.
Definition of the Node class.
virtual const Node * getNode(unsigned idx) const =0
virtual unsigned getNumberOfNodes() const =0
virtual std::size_t getID() const final
Returns the ID of the element.
Definition: Element.h:82
double sqrDist(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
Definition: Point3d.h:48
std::vector< std::size_t > findElementsWithinRadius(Element const &start_element, double const radius_squared)