32 MeshLib::Mesh const& mesh, std::vector<float>
const& layer_thickness_vector,
33 std::string
const& mesh_name)
35 std::vector<float> thickness;
36 for (std::size_t i = 0; i < layer_thickness_vector.size(); ++i)
38 if (layer_thickness_vector[i] > std::numeric_limits<float>::epsilon())
40 thickness.push_back(layer_thickness_vector[i]);
44 WARN(
"Ignoring layer {:d} with thickness {:f}.", i,
45 layer_thickness_vector[i]);
49 const std::size_t nLayers(thickness.size());
52 ERR(
"MeshLayerMapper::createStaticLayers(): A 2D mesh with nLayers > 0 "
53 "is required as input.");
59 const std::size_t nElems(
62 { return (elem->getDimension() == 2); }));
65 const std::vector<MeshLib::Node*>& nodes = mesh.
getNodes();
66 const std::vector<MeshLib::Element*>& elems = mesh.
getElements();
67 std::vector<MeshLib::Node*> new_nodes(nNodes + (nLayers * nNodes));
68 std::vector<MeshLib::Element*> new_elems;
69 new_elems.reserve(nElems * nLayers);
75 ERR(
"Could not create PropertyVector object 'MaterialIDs'.");
79 materials->reserve(nElems * nLayers);
82 for (
unsigned layer_id = 0; layer_id <= nLayers; ++layer_id)
85 unsigned node_offset(nNodes * layer_id);
88 z_offset += thickness[layer_id - 1];
91 std::transform(nodes.cbegin(), nodes.cend(),
92 new_nodes.begin() + node_offset,
94 return new MeshLib::Node((*node)[0], (*node)[1],
95 (*node)[2] - z_offset);
105 node_offset -= nNodes;
106 const unsigned mat_id(nLayers - layer_id);
108 for (
unsigned i = 0; i < nOrgElems; ++i)
119 for (
unsigned j = 0; j < nElemNodes; ++j)
121 const unsigned node_id =
123 e_nodes[j] = new_nodes[node_id + nNodes];
124 e_nodes[j + nElemNodes] = new_nodes[node_id];
138 OGS_FATAL(
"MeshLayerMapper: Unknown element type to extrude.");
140 materials->push_back(mat_id);
143 return new MeshLib::Mesh(mesh_name, new_nodes, new_elems, properties);
148 std::vector<GeoLib::Raster const*>
const& rasters,
149 double minimum_thickness,
150 double noDataReplacementValue)
152 const std::size_t nLayers(rasters.size());
155 ERR(
"MeshLayerMapper::createRasterLayers(): A 2D mesh and at least two "
156 "rasters required as input.");
160 auto top = std::make_unique<MeshLib::Mesh>(mesh);
161 if (!
layerMapping(*top, *rasters.back(), noDataReplacementValue))
166 auto bottom = std::make_unique<MeshLib::Mesh>(mesh);
174 _nodes.reserve(nLayers * nNodes);
177 std::size_t
const nElems(std::count_if(
180 { return (elem->getGeomType() == MeshLib::MeshElemType::TRIANGLE); }));
181 _elements.reserve(nElems * (nLayers - 1));
185 std::vector<MeshLib::Node*>
const& nodes = bottom->getNodes();
186 std::transform(nodes.begin(), nodes.end(), std::back_inserter(
_nodes),
187 [](
auto const* node) { return new MeshLib::Node(*node); });
190 for (std::size_t i = 0; i < nLayers - 1; ++i)
202 const unsigned pyramid_base[3][4] = {
209 std::vector<MeshLib::Node*>
const& top_nodes = dem_mesh.
getNodes();
210 int const last_layer_node_offset = layer_id * nNodes;
213 for (std::size_t i = 0; i < nNodes; ++i)
216 *
_nodes[last_layer_node_offset + i],
220 std::vector<MeshLib::Element*>
const& elems = dem_mesh.
getElements();
223 for (std::size_t i = 0; i < nElems; ++i)
230 unsigned node_counter(3);
231 unsigned missing_idx(0);
232 std::array<MeshLib::Node*, 6> new_elem_nodes{};
233 for (
unsigned j = 0; j < 3; ++j)
238 new_elem_nodes[node_counter] =
241 if (new_elem_nodes[j]->getID() !=
242 new_elem_nodes[node_counter]->getID())
252 switch (node_counter)
260 std::array<MeshLib::Node*, 5> pyramid_nodes{};
261 pyramid_nodes[0] = new_elem_nodes[pyramid_base[missing_idx][0]];
262 pyramid_nodes[1] = new_elem_nodes[pyramid_base[missing_idx][1]];
263 pyramid_nodes[2] = new_elem_nodes[pyramid_base[missing_idx][2]];
264 pyramid_nodes[3] = new_elem_nodes[pyramid_base[missing_idx][3]];
265 pyramid_nodes[4] = new_elem_nodes[missing_idx];
272 std::array<MeshLib::Node*, 4> tet_nodes{};
274 new_elem_nodes.begin() + node_counter,
288 double const nodata_replacement,
289 bool const ignore_nodata)
293 ERR(
"MshLayerMapper::layerMapping() - requires 2D mesh");
298 const double x0(header.
origin[0]);
299 const double y0(header.
origin[1]);
302 const std::pair<double, double> xDim(
303 x0, x0 + header.
n_cols * delta);
304 const std::pair<double, double> yDim(
305 y0, y0 + header.
n_rows * delta);
308 const std::vector<MeshLib::Node*>& nodes = mesh.
getNodes();
309 for (
unsigned i = 0; i < nNodes; ++i)
314 nodes[i]->updateCoordinates((*nodes[i])[0], (*nodes[i])[1],
320 constexpr
double eps = std::numeric_limits<double>::epsilon();
321 if (std::abs(elevation - header.
no_data) < eps)
327 elevation = nodata_replacement;
333 nodes[i]->updateCoordinates((*nodes[i])[0], (*nodes[i])[1], elevation);
344 ERR(
"MshLayerMapper::mapToStaticValue() - requires 2D mesh");
348 std::vector<MeshLib::Node*>
const& nodes(mesh.
getNodes());
351 node->updateCoordinates((*node)[0], (*node)[1], value);
Definition of the Hex class.
void ERR(char const *fmt, Args const &... args)
void WARN(char const *fmt, Args const &... args)
Definition of the MeshLayerMapper class.
Definition of the class Properties that implements a container of properties.
Definition of the Prism class.
Definition of the Pyramid class.
Definition of the GeoLib::Raster class.
Definition of the Tet class.
Class Raster is used for managing raster data.
double getValueAtPoint(const MathLib::Point3d &pnt) const
bool isPntOnRaster(MathLib::Point3d const &pnt) const
Checks if the given point is located within the (x,y)-extension of the raster.
double interpolateValueAtPoint(const MathLib::Point3d &pnt) const
Interpolates the elevation of the given point based on the 8-neighbourhood of the raster cell it is l...
RasterHeader const & getHeader() const
Returns the complete header information.
double _minimum_thickness
std::vector< int > _materials
MeshLib::Node * getNewLayerNode(MeshLib::Node const &dem_node, MeshLib::Node const &last_layer_node, GeoLib::Raster const &raster, std::size_t new_node_id) const
std::vector< MeshLib::Node * > _nodes
std::vector< MeshLib::Element * > _elements
std::size_t getID() const
virtual MeshElemType getGeomType() const =0
virtual const Node * getNode(unsigned idx) const =0
virtual unsigned getNumberOfBaseNodes() const =0
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.
void addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned layer_id, GeoLib::Raster const &raster) override
Adds another layer to a subsurface mesh.
static MeshLib::Mesh * createStaticLayers(MeshLib::Mesh const &mesh, std::vector< float > const &layer_thickness_vector, std::string const &mesh_name="SubsurfaceMesh")
static bool layerMapping(MeshLib::Mesh const &mesh, const GeoLib::Raster &raster, double nodata_replacement=0.0, bool const ignore_nodata=false)
static bool mapToStaticValue(MeshLib::Mesh const &mesh, double value)
Maps the elevation of all mesh nodes to the specified static value.
bool createRasterLayers(MeshLib::Mesh const &mesh, std::vector< GeoLib::Raster const * > const &rasters, double minimum_thickness, double noDataReplacementValue=0.0) override
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
unsigned getDimension() const
Returns the dimension of the mesh (determined by the maximum dimension over all elements).
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
std::size_t getNumberOfNodes() const
Get the number of nodes.
std::size_t getNumberOfElements() const
Get the number of elements.
Property manager on mesh items. Class Properties manages scalar, vector or matrix properties....
PropertyVector< T > * createNewPropertyVector(std::string const &name, MeshItemType mesh_item_type, std::size_t n_components=1)
void copy(PETScVector const &x, PETScVector &y)
std::size_t getNodeIndex(Element const &element, unsigned const idx)