OGS
BoundaryElementsAlongPolyline.cpp
Go to the documentation of this file.
1 
11 
12 #include <algorithm>
13 #include <typeinfo>
14 
15 #include "BaseLib/quicksort.h"
16 #include "GeoLib/Polyline.h"
19 #include "MeshLib/Elements/Line.h"
20 #include "MeshLib/Mesh.h"
22 #include "MeshLib/Node.h"
23 
24 namespace MeshGeoToolsLib
25 {
27  MeshLib::Mesh const& mesh, MeshNodeSearcher const& mshNodeSearcher,
28  GeoLib::Polyline const& ply)
29  : _mesh(mesh), _ply(ply)
30 {
31  // search nodes and elements located along the polyline
32  auto node_ids_on_poly = mshNodeSearcher.getMeshNodeIDs(ply);
34  es.searchByNodeIDs(node_ids_on_poly);
35  auto const& ele_ids_near_ply = es.getSearchedElementIDs();
36 
37  // check all edges of the elements near the polyline
38  for (auto ele_id : ele_ids_near_ply)
39  {
40  auto* e = _mesh.getElement(ele_id);
41  // skip line elements
42  if (e->getDimension() == 1)
43  {
44  continue;
45  }
46  // skip internal elements
47  if (!e->isBoundaryElement())
48  {
49  continue;
50  }
51  // find edges on the polyline
52  for (unsigned i = 0; i < e->getNumberOfEdges(); i++)
53  {
54  auto* edge = e->getEdge(i);
55  // check if all edge nodes are along the polyline (if yes, store a
56  // distance)
57  std::vector<std::size_t> edge_node_distances_along_ply;
58  if (includesAllEdgeNodeIDs(node_ids_on_poly, *edge,
59  edge_node_distances_along_ply))
60  {
61  auto* new_edge = modifyEdgeNodeOrdering(
62  *edge, ply, edge_node_distances_along_ply,
63  node_ids_on_poly);
64  if (edge != new_edge)
65  {
66  delete edge;
67  }
68  _boundary_elements.push_back(new_edge);
69  }
70  else
71  {
72  delete edge;
73  }
74  }
75  }
76 
77  // The sort was necessary in OGS-5 for some reason. I'm not sure if it is
78  // needed anymore in OGS-6.
79  // sort picked edges according to a distance of their first node along the
80  // polyline
81  std::sort(begin(_boundary_elements), end(_boundary_elements),
83  {
84  std::size_t dist1 = std::distance(
85  node_ids_on_poly.begin(),
86  std::find(node_ids_on_poly.begin(),
87  node_ids_on_poly.end(), getNodeIndex(*e1, 0)));
88  std::size_t dist2 = std::distance(
89  node_ids_on_poly.begin(),
90  std::find(node_ids_on_poly.begin(),
91  node_ids_on_poly.end(), getNodeIndex(*e2, 0)));
92  return (dist1 < dist2);
93  });
94 }
95 
97 {
98  for (auto p : _boundary_elements)
99  {
100  delete p;
101  }
102 }
103 
105  const std::vector<std::size_t>& vec_node_ids, const MeshLib::Element& edge,
106  std::vector<std::size_t>& edge_node_distances)
107 {
108  unsigned j = 0;
109  for (; j < edge.getNumberOfBaseNodes(); j++)
110  {
111  auto itr = std::find(vec_node_ids.begin(), vec_node_ids.end(),
112  getNodeIndex(edge, j));
113  if (itr != vec_node_ids.end())
114  {
115  edge_node_distances.push_back(
116  std::distance(vec_node_ids.begin(), itr));
117  }
118  else
119  {
120  break;
121  }
122  }
123  return (j == edge.getNumberOfBaseNodes());
124 }
125 
127  const MeshLib::Element& edge, const GeoLib::Polyline& ply,
128  const std::vector<std::size_t>& edge_node_distances_along_ply,
129  const std::vector<std::size_t>& node_ids_on_poly) const
130 {
131  // The first node of the edge should be always closer to the beginning of
132  // the polyline than other nodes.
133  if (edge_node_distances_along_ply.front() >
134  edge_node_distances_along_ply.back() ||
135  (ply.isClosed() &&
136  edge_node_distances_along_ply.back() == node_ids_on_poly.size() - 1))
137  { // Create a new element with reversed local node index
138  if (auto const* e = dynamic_cast<MeshLib::Line const*>(&edge))
139  {
140  std::array nodes = {const_cast<MeshLib::Node*>(e->getNode(1)),
141  const_cast<MeshLib::Node*>(e->getNode(0))};
142  return new MeshLib::Line(nodes);
143  }
144  else if (auto const* e = dynamic_cast<MeshLib::Line3 const*>(&edge))
145  {
146  std::array nodes = {const_cast<MeshLib::Node*>(e->getNode(1)),
147  const_cast<MeshLib::Node*>(e->getNode(0)),
148  const_cast<MeshLib::Node*>(e->getNode(2))};
149  return new MeshLib::Line3(nodes);
150  }
151  else
152  {
153  OGS_FATAL("Not implemented for element type {:s}",
154  typeid(edge).name());
155  }
156  }
157 
158  // Return the original edge otherwise.
159  return const_cast<MeshLib::Element*>(&edge);
160 }
161 } // end namespace MeshGeoToolsLib
Definition of the Element class.
#define OGS_FATAL(...)
Definition: Error.h:26
Definition of the Line class.
Definition of the Mesh class.
Definition of the Node class.
Definition of the PolyLine class.
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition: Polyline.h:51
bool isClosed() const
Definition: Polyline.cpp:109
MeshLib::Element * modifyEdgeNodeOrdering(const MeshLib::Element &edge, const GeoLib::Polyline &ply, const std::vector< std::size_t > &edge_node_distances_along_ply, const std::vector< std::size_t > &node_ids_on_poly) const
BoundaryElementsAlongPolyline(MeshLib::Mesh const &mesh, MeshNodeSearcher const &mshNodeSearcher, GeoLib::Polyline const &ply)
static bool includesAllEdgeNodeIDs(const std::vector< std::size_t > &vec_node_ids, const MeshLib::Element &edge, std::vector< std::size_t > &edge_node_distances)
std::vector< std::size_t > getMeshNodeIDs(GeoLib::GeoObject const &geoObj) const
Element search class.
Definition: ElementSearch.h:28
std::size_t searchByNodeIDs(const std::vector< std::size_t > &nodes)
Marks all elements connecting to any of the given nodes.
const std::vector< std::size_t > & getSearchedElementIDs() const
return marked elements
Definition: ElementSearch.h:33
virtual unsigned getNumberOfBaseNodes() const =0
virtual const Element * getEdge(unsigned i) const =0
Returns the i-th edge of the element.
const Element * getElement(std::size_t idx) const
Get the element with the given index.
Definition: Mesh.h:77
TemplateElement< MeshLib::LineRule2 > Line
Definition: Line.h:25
TemplateElement< MeshLib::LineRule3 > Line3
Definition: Line.h:26
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition: Element.cpp:225
Definition of the quicksort function.