OGS
MeshToolsLib::MeshRevision Class Reference

Detailed Description

Collapses nodes with a distance smaller min_distance and reduces elements accordingly.

Definition at line 24 of file MeshRevision.h.

#include <MeshRevision.h>

Collaboration diagram for MeshToolsLib::MeshRevision:
[legend]

Public Member Functions

 MeshRevision (MeshLib::Mesh &mesh)
unsigned getNumberOfCollapsibleNodes (double eps=std::numeric_limits< double >::epsilon()) const
 Returns the number of potentially collapsible nodes.
std::vector< std::size_t > collapseNodeIndices (double eps) const
MeshLib::MeshsimplifyMesh (const std::string &new_mesh_name, double eps, unsigned min_elem_dim=1) const

Private Member Functions

std::vector< MeshLib::Node * > constructNewNodesArray (const std::vector< std::size_t > &id_map) const

Private Attributes

MeshLib::Mesh_mesh
 The original mesh used for constructing the class.

Constructor & Destructor Documentation

◆ MeshRevision()

MeshToolsLib::MeshRevision::MeshRevision ( MeshLib::Mesh & mesh)
explicit

Constructor

Parameters
meshThe mesh which is being revised. Note that node IDs in mesh are changed during computation but are reset after the algorithms implemented here are finished

Definition at line 996 of file MeshRevision.cpp.

996: _mesh(mesh) {}
MeshLib::Mesh & _mesh
The original mesh used for constructing the class.

References _mesh.

Member Function Documentation

◆ collapseNodeIndices()

std::vector< std::size_t > MeshToolsLib::MeshRevision::collapseNodeIndices ( double eps) const

Designates nodes to be collapsed by setting their ID to the index of the node they will get merged with.

Definition at line 1085 of file MeshRevision.cpp.

1087{
1088 const std::vector<MeshLib::Node*>& nodes(_mesh.getNodes());
1089 const std::size_t nNodes(_mesh.getNumberOfNodes());
1090 std::vector<std::size_t> id_map(nNodes);
1091 const double half_eps(eps / 2.0);
1092 const double sqr_eps(eps * eps);
1093 std::iota(id_map.begin(), id_map.end(), 0);
1094
1095 GeoLib::Grid<MeshLib::Node> const grid(nodes.begin(), nodes.end(), 64);
1096
1097 for (std::size_t k = 0; k < nNodes; ++k)
1098 {
1099 MeshLib::Node const* const node(nodes[k]);
1100 if (node->getID() != k)
1101 {
1102 continue;
1103 }
1104 std::vector<std::vector<MeshLib::Node*> const*> const node_vectors(
1105 grid.getPntVecsOfGridCellsIntersectingCube(*node, half_eps));
1106
1107 const std::size_t nVectors(node_vectors.size());
1108 for (std::size_t i = 0; i < nVectors; ++i)
1109 {
1110 const std::vector<MeshLib::Node*>& cell_vector(*node_vectors[i]);
1111 const std::size_t nGridCellNodes(cell_vector.size());
1112 for (std::size_t j = 0; j < nGridCellNodes; ++j)
1113 {
1114 MeshLib::Node const* const test_node(cell_vector[j]);
1115 // are node indices already identical (i.e. nodes will be
1116 // collapsed)
1117 if (id_map[node->getID()] == id_map[test_node->getID()])
1118 {
1119 continue;
1120 }
1121
1122 // if test_node has already been collapsed to another node x,
1123 // ignore it (if the current node would need to be collapsed
1124 // with x it would already have happened when x was tested)
1125 if (test_node->getID() != id_map[test_node->getID()])
1126 {
1127 continue;
1128 }
1129
1130 // calc distance
1131 if (MathLib::sqrDist(*node, *test_node) < sqr_eps)
1132 {
1133 id_map[test_node->getID()] = node->getID();
1134 }
1135 }
1136 }
1137 }
1138 return id_map;
1139}
double sqrDist(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
Definition Point3d.cpp:19

References _mesh, MathLib::Point3dWithID::getID(), GeoLib::Grid< POINT >::getPntVecsOfGridCellsIntersectingCube(), and MathLib::sqrDist().

Referenced by getNumberOfCollapsibleNodes(), MeshAnalysisDialog::on_startButton_pressed(), and simplifyMesh().

◆ constructNewNodesArray()

std::vector< MeshLib::Node * > MeshToolsLib::MeshRevision::constructNewNodesArray ( const std::vector< std::size_t > & id_map) const
private

Constructs a new node vector for the resulting mesh by removing all nodes whose ID indicates they need to be merged/removed.

Definition at line 1141 of file MeshRevision.cpp.

1143{
1144 const std::vector<MeshLib::Node*>& nodes(_mesh.getNodes());
1145 const std::size_t nNodes(nodes.size());
1146 std::vector<MeshLib::Node*> new_nodes;
1147 new_nodes.reserve(nNodes);
1148 for (std::size_t k = 0; k < nNodes; ++k)
1149 {
1150 // all nodes that have not been collapsed with other nodes are copied
1151 // into new array
1152 if (nodes[k]->getID() == id_map[k])
1153 {
1154 std::size_t const id(new_nodes.size());
1155 new_nodes.push_back(new MeshLib::Node(
1156 (*nodes[k])[0], (*nodes[k])[1], (*nodes[k])[2], id));
1157 nodes[k]->setID(id); // the node in the old array gets the index of
1158 // the same node in the new array
1159 }
1160 // the other nodes are not copied and get the index of the nodes they
1161 // will have been collapsed with
1162 else
1163 {
1164 nodes[k]->setID(nodes[id_map[k]]->getID());
1165 }
1166 }
1167 return new_nodes;
1168}

References _mesh.

Referenced by simplifyMesh().

◆ getNumberOfCollapsibleNodes()

unsigned MeshToolsLib::MeshRevision::getNumberOfCollapsibleNodes ( double eps = std::numeric_limits<double>::epsilon()) const

Returns the number of potentially collapsible nodes.

Definition at line 998 of file MeshRevision.cpp.

999{
1000 std::vector<std::size_t> const id_map = collapseNodeIndices(eps);
1001 std::size_t const nNodes = id_map.size();
1002 unsigned count(0);
1003 for (std::size_t i = 0; i < nNodes; ++i)
1004 {
1005 if (i != id_map[i])
1006 {
1007 count++;
1008 }
1009 }
1010 return count;
1011}
std::vector< std::size_t > collapseNodeIndices(double eps) const

References collapseNodeIndices().

Referenced by MeshToolsLib::MeshValidation::existCollapsibleNodes().

◆ simplifyMesh()

MeshLib::Mesh * MeshToolsLib::MeshRevision::simplifyMesh ( const std::string & new_mesh_name,
double eps,
unsigned min_elem_dim = 1 ) const

Create a new mesh where all nodes with a distance < eps from each other are collapsed. Elements are adjusted accordingly and elements with nonplanar faces are subdivided into geometrically correct elements.

Parameters
new_mesh_nameNew name.
epsMinimum distance for nodes not to be collapsed
min_elem_dimMinimum dimension of elements to be inserted into new mesh (i.e. min_elem_dim=3 will prevent the new mesh to contain 2D elements)

Definition at line 1013 of file MeshRevision.cpp.

1016{
1017 if (this->_mesh.getNumberOfElements() == 0)
1018 {
1019 return nullptr;
1020 }
1021
1022 std::vector<MeshLib::Element*> const& elements(this->_mesh.getElements());
1023 auto const node_ids = collapseNodeIndices(eps);
1024 std::vector<MeshLib::Node*> new_nodes =
1025 this->constructNewNodesArray(node_ids);
1026 std::vector<MeshLib::Element*> new_elements;
1027 std::vector<std::size_t> element_ids;
1028
1029 for (std::size_t k(0); k < elements.size(); ++k)
1030 {
1031 MeshLib::Element const* const elem(elements[k]);
1032 unsigned const n_unique_nodes(getNumberOfUniqueNodes(elem));
1033 if (n_unique_nodes == elem->getNumberOfBaseNodes() &&
1034 elem->getDimension() >= min_elem_dim)
1035 {
1036 ElementErrorCode const e = elem->validate();
1038 {
1039 std::size_t const n_new_elements(
1040 subdivideElement(elem, new_nodes, new_elements));
1041 if (n_new_elements == 0)
1042 {
1043 ERR("Element {:d} has unknown element type.", k);
1044 _mesh.resetNodeIDs();
1045 BaseLib::cleanupVectorElements(new_nodes, new_elements);
1046 return nullptr;
1047 }
1048 element_ids.insert(element_ids.end(), n_new_elements, k);
1049 }
1050 else
1051 {
1052 new_elements.push_back(MeshLib::copyElement(elem, new_nodes));
1053 element_ids.push_back(k);
1054 }
1055 }
1056 else if (n_unique_nodes < elem->getNumberOfBaseNodes() &&
1057 n_unique_nodes > 1)
1058 {
1059 std::size_t const n_new_elements(reduceElement(
1060 elem, n_unique_nodes, new_nodes, new_elements, min_elem_dim));
1061 element_ids.insert(element_ids.end(), n_new_elements, k);
1062 }
1063 else
1064 {
1065 ERR("Something is wrong, more unique nodes than actual nodes");
1066 }
1067 }
1068
1069 auto const& props = _mesh.getProperties();
1070 MeshLib::Properties const new_properties =
1071 copyProperties(props, node_ids, element_ids);
1072
1073 _mesh.resetNodeIDs();
1074 if (!new_elements.empty())
1075 {
1076 return new MeshLib::Mesh(new_mesh_name, new_nodes, new_elements,
1077 true /* compute_element_neighbors */,
1078 new_properties);
1079 }
1080
1081 BaseLib::cleanupVectorElements(new_nodes, new_elements);
1082 return nullptr;
1083}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
std::vector< MeshLib::Node * > constructNewNodesArray(const std::vector< std::size_t > &id_map) const
void cleanupVectorElements(std::vector< T * > &items)
Definition Algorithm.h:249
Element * copyElement(Element const *const element, const std::vector< Node * > &nodes, std::vector< std::size_t > const *const id_map)
std::size_t reduceElement(MeshLib::Element const *const element, unsigned const n_unique_nodes, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elements, unsigned const min_elem_dim)
unsigned getNumberOfUniqueNodes(MeshLib::Element const *const element)
std::size_t subdivideElement(MeshLib::Element const *const element, std::vector< MeshLib::Node * > const &nodes, std::vector< MeshLib::Element * > &elements)
MeshLib::Properties copyProperties(MeshLib::Properties const &props, std::vector< std::size_t > const &node_ids, std::vector< std::size_t > const &elem_ids)

References _mesh, BaseLib::cleanupVectorElements(), collapseNodeIndices(), constructNewNodesArray(), MeshLib::copyElement(), ERR(), MeshLib::Element::getDimension(), MeshLib::Element::getNumberOfBaseNodes(), NonCoplanar, and MeshLib::Element::validate().

Referenced by MeshToolsLib::convertSurfaceToMesh(), and main().

Member Data Documentation

◆ _mesh

MeshLib::Mesh& MeshToolsLib::MeshRevision::_mesh
private

The original mesh used for constructing the class.

Definition at line 64 of file MeshRevision.h.

Referenced by MeshRevision(), collapseNodeIndices(), constructNewNodesArray(), and simplifyMesh().


The documentation for this class was generated from the following files: