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