Revision d0b959f2e7ce723411a8ea7d62f1d872560fa786 authored by Dmitri Naumov on 01 March 2021, 13:45:13 UTC, committed by Dmitri Naumov on 01 March 2021, 22:05:39 UTC
1 parent 11f8aa7
LayeredVolume.cpp
/**
* \file
* \author Karsten Rink
* \date 2014-04-11
* \brief Implementation of the LayeredVolume class.
*
* \copyright
* Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include "LayeredVolume.h"
#include "GeoLib/Raster.h"
#include "MeshLib/Elements/Tri.h"
#include "MeshLib/Elements/Quad.h"
#include "MeshLib/Properties.h"
#include "MeshLib/MeshEditing/DuplicateMeshComponents.h"
#include "MeshLib/MeshEditing/RemoveMeshComponents.h"
#include "MeshLib/MeshGenerators/MeshLayerMapper.h"
#include "MeshLib/MeshSearch/ElementSearch.h"
bool LayeredVolume::createRasterLayers(const MeshLib::Mesh &mesh,
const std::vector<GeoLib::Raster const*> &rasters,
double minimum_thickness,
double noDataReplacementValue)
{
if (mesh.getDimension() != 2)
{
return false;
}
_elevation_epsilon = calcEpsilon(*rasters[0], *rasters.back());
if (_elevation_epsilon <= 0)
{
return false;
}
// remove line elements, only tri + quad remain
MeshLib::ElementSearch ex(mesh);
ex.searchByElementType(MeshLib::MeshElemType::LINE);
std::unique_ptr<MeshLib::Mesh> top(
removeElements(mesh, ex.getSearchedElementIDs(), "MeshLayer"));
if (top == nullptr)
{
top = std::make_unique<MeshLib::Mesh>(mesh);
}
if (!MeshLib::MeshLayerMapper::layerMapping(
*top, *rasters.back(), noDataReplacementValue))
{
return false;
}
std::unique_ptr<MeshLib::Mesh> bottom(new MeshLib::Mesh(*top));
if (!MeshLib::MeshLayerMapper::layerMapping(*bottom, *rasters[0], 0))
{
return false;
}
this->_minimum_thickness = minimum_thickness;
_nodes = MeshLib::copyNodeVector(bottom->getNodes());
_elements = MeshLib::copyElementVector(bottom->getElements(), _nodes);
if (!_materials.empty())
{
ERR("The materials vector is not empty.");
return false;
}
_materials.resize(_elements.size(), 0);
// map each layer and attach to subsurface mesh
const std::size_t nRasters (rasters.size());
for (std::size_t i = 1; i < nRasters; ++i)
{
this->addLayerToMesh(*top, i, *rasters[i]);
}
// close boundaries between layers
this->addLayerBoundaries(*top, nRasters);
this->removeCongruentElements(nRasters, top->getNumberOfElements());
return true;
}
void LayeredVolume::addLayerToMesh(const MeshLib::Mesh &dem_mesh, unsigned layer_id, GeoLib::Raster const& raster)
{
const std::size_t nNodes (dem_mesh.getNumberOfNodes());
const std::vector<MeshLib::Node*> &nodes (dem_mesh.getNodes());
const std::size_t node_id_offset (_nodes.size());
const std::size_t last_layer_node_offset (node_id_offset-nNodes);
for (std::size_t i = 0; i < nNodes; ++i)
{
_nodes.push_back(getNewLayerNode(*nodes[i],
*_nodes[last_layer_node_offset + i],
raster,
_nodes.size()));
}
const std::vector<MeshLib::Element*> &layer_elements (dem_mesh.getElements());
for (MeshLib::Element* elem : layer_elements)
{
if (elem->getGeomType() == MeshLib::MeshElemType::TRIANGLE)
{
std::array<MeshLib::Node*,3> tri_nodes = {{ _nodes[node_id_offset+elem->getNodeIndex(0)],
_nodes[node_id_offset+elem->getNodeIndex(1)],
_nodes[node_id_offset+elem->getNodeIndex(2)] }};
_elements.push_back(new MeshLib::Tri(tri_nodes));
_materials.push_back(layer_id);
}
else if (elem->getGeomType() == MeshLib::MeshElemType::QUAD)
{
std::array<MeshLib::Node*,4> quad_nodes = {{ _nodes[node_id_offset+elem->getNodeIndex(0)],
_nodes[node_id_offset+elem->getNodeIndex(1)],
_nodes[node_id_offset+elem->getNodeIndex(2)],
_nodes[node_id_offset+elem->getNodeIndex(3)] }};
_elements.push_back(new MeshLib::Quad(quad_nodes));
_materials.push_back(layer_id);
}
}
}
void LayeredVolume::addLayerBoundaries(const MeshLib::Mesh &layer, std::size_t nLayers)
{
const unsigned nLayerBoundaries (nLayers-1);
const std::size_t nNodes (layer.getNumberOfNodes());
const std::vector<MeshLib::Element*> &layer_elements (layer.getElements());
for (MeshLib::Element* elem : layer_elements)
{
const std::size_t nElemNodes (elem->getNumberOfBaseNodes());
for (unsigned i = 0; i < nElemNodes; ++i)
{
if (elem->getNeighbor(i) == nullptr)
{
for (unsigned j=0; j<nLayerBoundaries; ++j)
{
const std::size_t offset (j*nNodes);
MeshLib::Node* n0 = _nodes[offset + elem->getNodeIndex(i)];
MeshLib::Node* n1 = _nodes[offset + elem->getNodeIndex((i+1)%nElemNodes)];
MeshLib::Node* n2 = _nodes[offset + nNodes + elem->getNodeIndex((i+1)%nElemNodes)];
MeshLib::Node* n3 = _nodes[offset + nNodes + elem->getNodeIndex(i)];
auto const v0 =
Eigen::Map<Eigen::Vector3d const>(n0->getCoords());
auto const v1 =
Eigen::Map<Eigen::Vector3d const>(n1->getCoords());
auto const v2 =
Eigen::Map<Eigen::Vector3d const>(n2->getCoords());
auto const v3 =
Eigen::Map<Eigen::Vector3d const>(n3->getCoords());
double const eps = std::numeric_limits<double>::epsilon();
if ((v2 - v1).norm() > eps)
{
const std::array tri_nodes = {n0, n2, n1};
_elements.push_back(new MeshLib::Tri(tri_nodes));
_materials.push_back(nLayers+j);
}
if ((v3 - v0).norm() > eps)
{
const std::array tri_nodes = {n0, n3, n2};
_elements.push_back(new MeshLib::Tri(tri_nodes));
_materials.push_back(nLayers+j);
}
}
}
}
}
}
void LayeredVolume::removeCongruentElements(std::size_t nLayers, std::size_t nElementsPerLayer)
{
for (std::size_t i=nLayers-1; i>0; --i)
{
const std::size_t lower_offset ((i-1) * nElementsPerLayer);
const std::size_t upper_offset ( i * nElementsPerLayer);
for (std::size_t j=0; j<nElementsPerLayer; ++j)
{
MeshLib::Element const*const high (_elements[upper_offset+j]);
MeshLib::Element *const low (_elements[lower_offset+j]);
unsigned count(0);
const std::size_t nElemNodes (low->getNumberOfBaseNodes());
for (std::size_t k = 0; k < nElemNodes; ++k)
{
if (high->getNodeIndex(k) == low->getNodeIndex(k))
{
low->setNode(k, _nodes[high->getNodeIndex(k)]);
count++;
}
}
if (count == nElemNodes)
{
delete _elements[upper_offset+j];
// mark element and material entries for deletion
_elements[upper_offset+j] = nullptr;
_materials[upper_offset+j] = -1;
}
else
{
MeshLib::Node attr = MeshLib::getCenterOfGravity(*high);
_attribute_points.emplace_back(
attr[0],
attr[1],
(attr[2] + MeshLib::getCenterOfGravity(*low)[2]) / 2.0,
_materials[lower_offset + j]);
}
}
}
// delete marked entries
auto elem_vec_end = std::remove(_elements.begin(), _elements.end(), nullptr);
_elements.erase(elem_vec_end, _elements.end());
auto mat_vec_end = std::remove(_materials.begin(), _materials.end(), -1);
_materials.erase(mat_vec_end, _materials.end());
}
Computing file changes ...