From 0881e4b10e2b9d8803ebf16fc02a3414214eacfc Mon Sep 17 00:00:00 2001 From: Karsten Rink <karsten.rink@ufz.de> Date: Thu, 13 Sep 2012 15:40:40 +0200 Subject: [PATCH] getSurfaceMesh is working now; getSurfaceNodes is working now; meshes are now tested for unused nodes (such nodes are removed upon loading) --- FileIO/Legacy/MeshIO.cpp | 2 +- FileIO/XmlIO/VTKInterface.cpp | 35 ++++- FileIO/XmlIO/VTKInterface.h | 2 + Gui/DataView/DirectConditionGenerator.cpp | 3 +- Gui/DataView/MshEditDialog.cpp | 2 +- Gui/DataView/MshLayerMapper.cpp | 3 +- Gui/mainwindow.cpp | 11 +- MeshLib/Elements/Element.h | 4 +- MeshLib/Mesh.cpp | 79 ++++++---- MeshLib/Mesh.h | 3 + MeshLib/MshEditor.cpp | 172 +++++++++++++--------- MeshLib/MshEditor.h | 13 +- MeshLib/Node.h | 5 +- 13 files changed, 219 insertions(+), 115 deletions(-) diff --git a/FileIO/Legacy/MeshIO.cpp b/FileIO/Legacy/MeshIO.cpp index 85f8acc206c..082182c6771 100644 --- a/FileIO/Legacy/MeshIO.cpp +++ b/FileIO/Legacy/MeshIO.cpp @@ -36,7 +36,7 @@ MeshIO::MeshIO() MeshLib::Mesh* MeshIO::loadMeshFromFile(const std::string& file_name) { - std::cout << "Reading OGS legacy mesh ... "; + std::cout << "Reading OGS legacy mesh ... " << std::endl; std::ifstream in (file_name.c_str(),std::ios::in); if (!in.is_open()) diff --git a/FileIO/XmlIO/VTKInterface.cpp b/FileIO/XmlIO/VTKInterface.cpp index d706be51d0f..5a02297e5b7 100644 --- a/FileIO/XmlIO/VTKInterface.cpp +++ b/FileIO/XmlIO/VTKInterface.cpp @@ -67,8 +67,22 @@ MeshLib::Mesh* VTKInterface::readVTUFile(const std::string &file_name) rapidxml::xml_node<>* root_node (doc.first_node()); if (isVTKUnstructuredGrid(root_node)) { + bool is_compressed(false); //check if content is compressed const rapidxml::xml_attribute<>* compressor (root_node->first_attribute("compressor")); + if (compressor ) + { + if (std::string(compressor->value()).compare("vtkZLibDataCompressor") == 0) + { + is_compressed = true; + uncompressData(root_node); + } + else + { + std::cout << "VTKInterface::readVTUFile() - Unknown compression method." << std::endl; + return NULL; + } + } //skip to <Piece>-tag and start parsing content const rapidxml::xml_node<>* piece_node (doc.first_node()->first_node()->first_node("Piece")); @@ -132,7 +146,14 @@ MeshLib::Mesh* VTKInterface::readVTUFile(const std::string &file_name) if (connectivity_node && celltype_node) { - if (std::string(celltype_node->first_attribute("format")->value()).compare("ascii") == 0) + const std::string format = std::string(celltype_node->first_attribute("format")->value()); + if (format.compare("ascii") == 0) + { + std::stringstream iss (celltype_node->value()); + for(unsigned i=0; i<nElems; i++) + iss >> cell_types[i]; + } + else if (format.compare("appended") == 0) { std::stringstream iss (celltype_node->value()); for(unsigned i=0; i<nElems; i++) @@ -242,6 +263,18 @@ bool VTKInterface::isVTKUnstructuredGrid(const rapidxml::xml_node<>* vtk_root) return false; } +unsigned char* VTKInterface::uncompressData(const rapidxml::xml_node<>* node) +{ + rapidxml::xml_node<>* data_node = node->first_node("AppendedData"); + char* compressed_data (NULL); + if (data_node) + compressed_data = data_node->value(); + + return NULL; +} + + + int VTKInterface::write(std::ostream& stream) { //if (this->_export_name.empty()) diff --git a/FileIO/XmlIO/VTKInterface.h b/FileIO/XmlIO/VTKInterface.h index 1228d5791f9..6127937d165 100644 --- a/FileIO/XmlIO/VTKInterface.h +++ b/FileIO/XmlIO/VTKInterface.h @@ -76,6 +76,8 @@ private: /// Construct an Element-object from the data given to the method and the data at the current stream position. static MeshLib::Element* readElement(std::stringstream &iss, const std::vector<MeshLib::Node*> &nodes, unsigned material, unsigned type); + static unsigned char* uncompressData(const rapidxml::xml_node<>* node); + bool _use_compressor; }; } diff --git a/Gui/DataView/DirectConditionGenerator.cpp b/Gui/DataView/DirectConditionGenerator.cpp index 59116f8fcba..5f3c217b2b0 100644 --- a/Gui/DataView/DirectConditionGenerator.cpp +++ b/Gui/DataView/DirectConditionGenerator.cpp @@ -33,7 +33,8 @@ const std::vector< std::pair<size_t,double> >& DirectConditionGenerator::directT return _direct_values; } - const std::vector<GeoLib::PointWithID*> surface_nodes ( MeshLib::MshEditor::getSurfaceNodes(mesh) ); + const double dir[3] = {0,0,1}; + const std::vector<GeoLib::PointWithID*> surface_nodes ( MeshLib::MshEditor::getSurfaceNodes(mesh, dir) ); //std::vector<MeshLib::CNode*> nodes = mesh.nod_vector; const size_t nNodes(surface_nodes.size()); _direct_values.reserve(nNodes); diff --git a/Gui/DataView/MshEditDialog.cpp b/Gui/DataView/MshEditDialog.cpp index 6cfcaae958b..bbbfe882122 100644 --- a/Gui/DataView/MshEditDialog.cpp +++ b/Gui/DataView/MshEditDialog.cpp @@ -115,7 +115,7 @@ void MshEditDialog::accept() all_paths_set = false; else { - for (unsigned i=1; i<_labels.size(); i++) + for (int i=1; i<_labels.size(); i++) if (_edits[i]->text().length()==0) all_paths_set = false; } diff --git a/Gui/DataView/MshLayerMapper.cpp b/Gui/DataView/MshLayerMapper.cpp index 6716b972e47..ba67a7a6466 100644 --- a/Gui/DataView/MshLayerMapper.cpp +++ b/Gui/DataView/MshLayerMapper.cpp @@ -187,8 +187,7 @@ int MshLayerMapper::LayerMapping(MeshLib::Mesh* new_mesh, const std::string &ras { std::cout << "Warning: Removing " << noData_nodes.size() << " mesh nodes at NoData values ... " << std::endl; - MeshLib::MshEditor msh_editor; - MeshLib::Mesh* red_mesh = msh_editor.removeMeshNodes(new_mesh, noData_nodes); + MeshLib::Mesh* red_mesh = MeshLib::MshEditor::removeMeshNodes(new_mesh, noData_nodes); if (new_mesh->getNElements() == 0) { delete new_mesh; diff --git a/Gui/mainwindow.cpp b/Gui/mainwindow.cpp index d2aae515435..78a96fa40b3 100644 --- a/Gui/mainwindow.cpp +++ b/Gui/mainwindow.cpp @@ -1111,7 +1111,16 @@ void MainWindow::showVisalizationPrefsDialog() void MainWindow::FEMTestStart() { - //std::string name ("Test"); + const double dir[3] = {0, 0, 1}; + const MeshLib::Mesh* mesh = this->_project.getMesh("Ammer-Homogen100m-Final"); + //_meshModels->addMesh( MeshLib::MshEditor::getMeshSurface(*mesh, dir) ); + std::vector<GeoLib::PointWithID*> pnts (MeshLib::MshEditor::getSurfaceNodes(*mesh, dir)); + std::vector<GeoLib::Point*> *sfcpnts = new std::vector<GeoLib::Point*>(pnts.size()); + for (unsigned i=0; i<pnts.size(); ++i) + (*sfcpnts)[i] = pnts[i]; + std::string name("SurfacePoints"); + this->_geoModels->addPointVec(sfcpnts, name); + //std::string name ("test"); //_meshModels->addMesh(MshEditor::getMeshSurface(*_project.getMesh("Ammer-Homogen100m-Final")), name); /* diff --git a/MeshLib/Elements/Element.h b/MeshLib/Elements/Element.h index 2a6b0fbce2a..7ac7218b746 100644 --- a/MeshLib/Elements/Element.h +++ b/MeshLib/Elements/Element.h @@ -26,10 +26,8 @@ class Node; */ class Element { - /* friend functions: */ + /* friend classes */ friend class Mesh;//void Mesh::setElementInformationForNodes(); - //friend void Mesh::addElement(Element*); - public: /// Compute the minimum and maximum squared edge length for this element diff --git a/MeshLib/Mesh.cpp b/MeshLib/Mesh.cpp index 94533bbc4ed..10b6c3532a3 100644 --- a/MeshLib/Mesh.cpp +++ b/MeshLib/Mesh.cpp @@ -39,6 +39,7 @@ Mesh::Mesh(const std::string &name, const std::vector<Node*> &nodes, const std:: //this->setNodesConnectedByEdges(); //this->setNodesConnectedByElements(); this->setElementsConnectedToElements(); + this->removeUnusedMeshNodes(); } Mesh::Mesh(const Mesh &mesh) @@ -46,16 +47,16 @@ Mesh::Mesh(const Mesh &mesh) { const std::vector<Node*> nodes (mesh.getNodes()); const size_t nNodes (nodes.size()); - for (unsigned i=0; i<nNodes; i++) + for (unsigned i=0; i<nNodes; ++i) _nodes[i] = new Node(*nodes[i]); const std::vector<Element*> elements (mesh.getElements()); const size_t nElements (elements.size()); - for (unsigned i=0; i<nElements; i++) + for (unsigned i=0; i<nElements; ++i) { const size_t nElemNodes = elements[i]->getNNodes(); _elements[i] = elements[i]->clone(); - for (unsigned j=0; j<nElemNodes; j++) + for (unsigned j=0; j<nElemNodes; ++j) _elements[i]->_nodes[j] = _nodes[elements[i]->getNode(j)->getID()]; } @@ -69,11 +70,11 @@ Mesh::Mesh(const Mesh &mesh) Mesh::~Mesh() { const size_t nElements (_elements.size()); - for (size_t i=0; i<nElements; i++) + for (size_t i=0; i<nElements; ++i) delete _elements[i]; const size_t nNodes (_nodes.size()); - for (size_t i=0; i<nNodes; i++) + for (size_t i=0; i<nNodes; ++i) delete _nodes[i]; } @@ -84,10 +85,10 @@ void Mesh::makeNodesUnique() //replace node pointers in elements unsigned nElements (_elements.size()); - for (unsigned i=0; i<nElements; i++) + for (unsigned i=0; i<nElements; ++i) { unsigned nNodes (_elements[i]->getNNodes()); - for (unsigned j=0; j<nNodes; j++) + for (unsigned j=0; j<nNodes; ++j) _elements[i]->getNodeIndex(j); } @@ -106,21 +107,21 @@ void Mesh::addElement(Element* elem) // add element information to nodes unsigned nNodes (elem->getNNodes()); - for (unsigned i=0; i<nNodes; i++) + for (unsigned i=0; i<nNodes; ++i) elem->_nodes[i]->addElement(elem); } void Mesh::resetNodeIDs() { const size_t nNodes (this->_nodes.size()); - for (unsigned i=0; i<nNodes; i++) + for (unsigned i=0; i<nNodes; ++i) _nodes[i]->setID(i); } void Mesh::setDimension() { const size_t nElements (_elements.size()); - for (unsigned i=0; i<nElements; i++) + for (unsigned i=0; i<nElements; ++i) if (_elements[i]->getDimension() > _mesh_dimension) _mesh_dimension = _elements[i]->getDimension(); } @@ -128,19 +129,25 @@ void Mesh::setDimension() void Mesh::setElementsConnectedToNodes() { const size_t nElements (_elements.size()); - for (unsigned i=0; i<nElements; i++) + for (unsigned i=0; i<nElements; ++i) { MeshLib::Element* element = _elements[i]; const unsigned nNodes (element->getNNodes()); - for (unsigned j=0; j<nNodes; j++) + for (unsigned j=0; j<nNodes; ++j) element->_nodes[j]->addElement(element); } -#ifdef NDEBUG +#ifndef NDEBUG // search for nodes that are not part of any element + unsigned count(0); const size_t nNodes (_nodes.size()); - for (unsigned i=0; i<nNodes; i++) + for (unsigned i=0; i<nNodes; ++i) if (_nodes[i]->getNElements() == 0) - WARN ("Warning: Node %d is not part of any element.", i); + { + WARN ("Node %d is not part of any element.", i); + ++count; + } + if (count) + WARN ("%d unused mesh nodes found.", count); #endif } @@ -164,7 +171,7 @@ void Mesh::setElementsConnectedToElements() #else unsigned m(0); #endif - for (m=0; m<nElements; m++) + for (m=0; m<nElements; ++m) { // create vector with all elements connected to current element (includes lots of doubles!) std::vector<Element*> neighbors; @@ -172,7 +179,7 @@ void Mesh::setElementsConnectedToElements() if (element->getType() != MshElemType::EDGE) { const size_t nNodes (element->getNNodes()); - for (unsigned n(0); n<nNodes; n++) + for (unsigned n(0); n<nNodes; ++n) { std::vector<Element*> const& conn_elems ((element->getNode(n)->getElements())); neighbors.insert(neighbors.end(), conn_elems.begin(), conn_elems.end()); @@ -180,7 +187,7 @@ void Mesh::setElementsConnectedToElements() const unsigned nNeighbors ( neighbors.size() ); - for (unsigned i(0); i<nNeighbors; i++) + for (unsigned i(0); i<nNeighbors; ++i) { if (element->addNeighbor(neighbors[i]) && neighbors[i]->getType() != MshElemType::EDGE) { @@ -194,21 +201,21 @@ void Mesh::setElementsConnectedToElements() void Mesh::setNodesConnectedByEdges() { const size_t nNodes (this->_nodes.size()); - for (unsigned i=0; i<nNodes; i++) + for (unsigned i=0; i<nNodes; ++i) { MeshLib::Node* node (_nodes[i]); std::vector<MeshLib::Node*> conn_set; const std::vector<MeshLib::Element*> &conn_elems (node->getElements()); const size_t nConnElems (conn_elems.size()); - for (unsigned j=0; j<nConnElems; j++) + for (unsigned j=0; j<nConnElems; ++j) { const unsigned idx (conn_elems[j]->getNodeIDinElement(node)); const unsigned nElemNodes (conn_elems[j]->getNNodes()); - for (unsigned k(0); k<nElemNodes; k++) + for (unsigned k(0); k<nElemNodes; ++k) { bool is_in_vector (false); const size_t nConnNodes (conn_set.size()); - for (unsigned l(0); l<nConnNodes; l++) + for (unsigned l(0); l<nConnNodes; ++l) if (conn_elems[j]->getNode(k) == conn_set[l]) is_in_vector = true; if (is_in_vector) continue; @@ -223,22 +230,22 @@ void Mesh::setNodesConnectedByEdges() void Mesh::setNodesConnectedByElements() { const size_t nNodes (this->_nodes.size()); - for (unsigned i=0; i<nNodes; i++) + for (unsigned i=0; i<nNodes; ++i) { MeshLib::Node* node (_nodes[i]); std::vector<MeshLib::Node*> conn_vec; const std::vector<MeshLib::Element*> &conn_elems (node->getElements()); const size_t nConnElems (conn_elems.size()); - for (unsigned j=0; j<nConnElems; j++) + for (unsigned j=0; j<nConnElems; ++j) { const unsigned nElemNodes (conn_elems[j]->getNNodes()); - for (unsigned k(0); k<nElemNodes; k++) + for (unsigned k(0); k<nElemNodes; ++k) { bool is_in_vector (false); const MeshLib::Node* c_node (conn_elems[j]->getNode(k)); if (c_node == node) continue; const size_t nConnNodes (conn_vec.size()); - for (unsigned l(0); l<nConnNodes; l++) + for (unsigned l(0); l<nConnNodes; ++l) if (c_node == conn_vec[l]) is_in_vector = true; if (!is_in_vector) @@ -249,5 +256,25 @@ void Mesh::setNodesConnectedByElements() } } +void Mesh::removeUnusedMeshNodes() +{ + unsigned count(0); + std::vector<MeshLib::Node*>::iterator it (this->_nodes.begin()); + for (it; it != this->_nodes.end();) + { + if ((*it)->getNElements() == 0) + { + it = this->_nodes.erase(it); + ++count; + } + else ++it; + } + if (count) + { + std::cout << "Removed " << count << " unused mesh nodes." << std::endl; + this->resetNodeIDs(); + } +} + } diff --git a/MeshLib/Mesh.h b/MeshLib/Mesh.h index 179884d7b77..c499bf8aa3f 100644 --- a/MeshLib/Mesh.h +++ b/MeshLib/Mesh.h @@ -97,6 +97,9 @@ protected: /// Checks the coordinates of all mesh nodes and removes identical nodes. Elements are adapted accordingly. void makeNodesUnique(); + /// Removes nodes that are not part of any element. + void removeUnusedMeshNodes(); + /// Sets the dimension of the mesh. void setDimension(); diff --git a/MeshLib/MshEditor.cpp b/MeshLib/MshEditor.cpp index 6e56aaafd7b..9e91048d7d5 100644 --- a/MeshLib/MshEditor.cpp +++ b/MeshLib/MshEditor.cpp @@ -34,14 +34,14 @@ void MshEditor::getSurfaceAreaForNodes(const MeshLib::Mesh* mesh, std::vector<do // for each node, a vector containing all the element idget every element std::vector<MeshLib::Node*> nodes = mesh->getNodes(); const size_t nNodes ( mesh->getNNodes() ); - for (size_t n=0; n<nNodes; n++) + for (size_t n=0; n<nNodes; ++n) { double node_area (0); std::vector<MeshLib::Element*> conn_elems = nodes[n]->getElements(); const size_t nConnElems (conn_elems.size()); - for (size_t i=0; i<nConnElems;i++) + for (size_t i=0; i<nConnElems; ++i) { const MeshLib::Element* elem (conn_elems[i]); const unsigned nElemParts = (elem->getType() == MshElemType::TRIANGLE) ? 3 : 4; @@ -67,12 +67,12 @@ MeshLib::Mesh* MshEditor::removeMeshNodes(MeshLib::Mesh* mesh, // delete nodes and their connected elements and replace them with null pointers const size_t delNodes = nodes.size(); std::vector<MeshLib::Node*> mesh_nodes = new_mesh->getNodes(); - for (size_t i = 0; i < delNodes; i++) + for (size_t i = 0; i < delNodes; ++i) { const MeshLib::Node* node = new_mesh->getNode(i); std::vector<MeshLib::Element*> conn_elems = node->getElements(); - for (size_t j = 0; j < conn_elems.size(); j++) + for (size_t j = 0; j < conn_elems.size(); ++j) { delete conn_elems[j]; conn_elems[j] = NULL; @@ -85,7 +85,7 @@ MeshLib::Mesh* MshEditor::removeMeshNodes(MeshLib::Mesh* mesh, const size_t nNodes = new_mesh->getNNodes(); std::vector<int> id_map(nNodes, -1); size_t count(0); - for (size_t i = 0; i < nNodes; i++) + for (size_t i = 0; i < nNodes; ++i) { if (mesh_nodes[i]) { @@ -115,81 +115,79 @@ MeshLib::Mesh* MshEditor::removeMeshNodes(MeshLib::Mesh* mesh, return new_mesh; } -std::vector<GeoLib::PointWithID*> MshEditor::getSurfaceNodes(const MeshLib::Mesh &mesh) +MeshLib::Mesh* MshEditor::getMeshSurface(const MeshLib::Mesh &mesh, const double* dir) { - /* TODO6 - INFO ("Extracting surface nodes..."); - // Sort points lexicographically - size_t nNodes (mesh.nod_vector.size()); - std::vector<GeoLib::PointWithID*> nodes; - std::vector<size_t> perm; - for (size_t j(0); j<nNodes; j++) - { - nodes.push_back(new GeoLib::PointWithID(mesh.nod_vector[j]->getData(), j)); - perm.push_back(j); - } - Quicksort<GeoLib::PointWithID*> (nodes, 0, nodes.size(), perm); - - // Extract surface points - double eps (std::numeric_limits<double>::epsilon()); - */ - std::vector<GeoLib::PointWithID*> surface_pnts; - /* TODO6 - for (size_t k(1); k < nNodes; k++) + INFO ("Extracting mesh surface..."); + const std::vector<MeshLib::Element*> all_elements (mesh.getElements()); + const std::vector<MeshLib::Node*> all_nodes (mesh.getNodes()); + + std::vector<MeshLib::Element*> sfc_elements; + get2DSurfaceElements(all_elements, sfc_elements, dir, mesh.getDimension()); + + std::vector<MeshLib::Node*> sfc_nodes; + std::vector<unsigned> node_id_map(mesh.getNNodes()); + get2DSurfaceNodes(all_nodes, sfc_nodes, sfc_elements, node_id_map); + + // create new elements vector with newly created nodes + const size_t nNewElements (sfc_elements.size()); + std::vector<MeshLib::Element*> new_elements(sfc_elements.size()); + for (unsigned i=0; i<nNewElements; ++i) { - const GeoLib::PointWithID& p0 (*(nodes[k - 1])); - const GeoLib::PointWithID& p1 (*(nodes[k])); - if (fabs (p0[0] - p1[0]) > eps || fabs (p0[1] - p1[1]) > eps) - surface_pnts.push_back (nodes[k - 1]); + MeshLib::Element* elem (sfc_elements[i]); + if (elem->getType() == MshElemType::TRIANGLE) + new_elements[i] = new MeshLib::Tri(sfc_nodes[node_id_map[elem->getNode(0)->getID()]], + sfc_nodes[node_id_map[elem->getNode(1)->getID()]], + sfc_nodes[node_id_map[elem->getNode(2)->getID()]]); + else + new_elements[i] = new MeshLib::Quad(sfc_nodes[node_id_map[elem->getNode(0)->getID()]], + sfc_nodes[node_id_map[elem->getNode(1)->getID()]], + sfc_nodes[node_id_map[elem->getNode(2)->getID()]], + sfc_nodes[node_id_map[elem->getNode(3)->getID()]]); + delete sfc_elements[i]; } - // Add last point - surface_pnts.push_back (nodes[nNodes - 1]); - */ - return surface_pnts; + return new Mesh("SurfaceMesh", sfc_nodes, new_elements); } -MeshLib::Mesh* MshEditor::getMeshSurface(const MeshLib::Mesh &mesh, const double* dir) +void MshEditor::get2DSurfaceElements(const std::vector<MeshLib::Element*> &all_elements, std::vector<MeshLib::Element*> &sfc_elements, const double* dir, unsigned mesh_dimension) { - INFO ("Extracting mesh surface..."); + bool complete_surface (true); + if (dir) + complete_surface = ((dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]) == 0) ? true : false; - const std::vector<MeshLib::Element*> elements = mesh.getElements(); - std::vector<MeshLib::Element*> new_elements; - const size_t nElements (mesh.getNElements()); + const size_t nElements (all_elements.size()); - bool complete_surface = ((dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]) == 0) ? true : false; - - // 2D meshes - if (mesh.getDimension() == 2 ) + if (mesh_dimension == 2 ) { - if (complete_surface) return new MeshLib::Mesh(mesh); // simply copy the mesh - else // check only surface normal directions of all elements + for (unsigned i=0; i<nElements; ++i) { - for (unsigned i=0; i<nElements; i++) + if (complete_surface) + sfc_elements.push_back(all_elements[i]); + else { - MeshLib::Face* face = dynamic_cast<MeshLib::Face*>(elements[i]); + MeshLib::Face* face = dynamic_cast<MeshLib::Face*>(all_elements[i]); double normal[3]; face->getSurfaceNormal(normal); if (MathLib::scpr(normal, dir, 3) > 0) - new_elements.push_back(static_cast<MeshLib::Element*>(face)); + sfc_elements.push_back(static_cast<MeshLib::Element*>(face)); } } } - // 3D meshes - else if (mesh.getDimension() == 3) // + else if (mesh_dimension == 3) { - for (unsigned i=0; i<nElements; i++) + for (unsigned i=0; i<nElements; ++i) { - if (const MeshLib::Cell* cell = dynamic_cast<MeshLib::Cell*>(elements[i])) + if (all_elements[i]->getDimension()==3) { + const MeshLib::Cell* cell = static_cast<MeshLib::Cell*>(all_elements[i]); if (cell->isOnSurface()) { const unsigned nFaces (cell->getNFaces()); - for (unsigned j=0; j<nFaces; j++) + for (unsigned j=0; j<nFaces; ++j) { - if (cell->getNeighbor(i) == NULL) + if (cell->getNeighbor(j) == NULL) { - const MeshLib::Face* face = static_cast<const MeshLib::Face*>(cell->getFace(i)); + const MeshLib::Face* face = static_cast<const MeshLib::Face*>(cell->getFace(j)); if (!complete_surface) { double normal[3]; @@ -199,35 +197,67 @@ MeshLib::Mesh* MshEditor::getMeshSurface(const MeshLib::Mesh &mesh, const double } if (face->getType() == MshElemType::TRIANGLE) - new_elements.push_back(new MeshLib::Tri(*static_cast<const MeshLib::Tri*>(face))); + sfc_elements.push_back(new MeshLib::Tri(*static_cast<const MeshLib::Tri*>(face))); else - new_elements.push_back(new MeshLib::Quad(*static_cast<const MeshLib::Quad*>(face))); + sfc_elements.push_back(new MeshLib::Quad(*static_cast<const MeshLib::Quad*>(face))); } } } } } + } +} - // now copy nodes - const size_t nNewElements (new_elements.size()); - std::vector<const MeshLib::Node*> tmp_nodes(mesh.getNNodes(), NULL); - const size_t nNodes (tmp_nodes.size()); - for (unsigned i=0; i<nNewElements; i++) +void MshEditor::get2DSurfaceNodes(const std::vector<MeshLib::Node*> &all_nodes, std::vector<MeshLib::Node*> &sfc_nodes, const std::vector<MeshLib::Element*> &sfc_elements, std::vector<unsigned> &node_id_map) +{ + const size_t nNewElements (sfc_elements.size()); + std::vector<const MeshLib::Node*> tmp_nodes(all_nodes.size(), NULL); + const size_t nNodes (tmp_nodes.size()); + for (unsigned i=0; i<nNewElements; ++i) + { + const MeshLib::Element* elem (sfc_elements[i]); + for (unsigned j=0; j<elem->getNNodes(); ++j) { - const MeshLib::Element* elem (new_elements[i]); - for (unsigned j=0; j<elem->getNNodes(); j++) - { - const MeshLib::Node* node (elem->getNode(i)); - tmp_nodes[node->getID()] = node; - } + const MeshLib::Node* node (elem->getNode(j)); + tmp_nodes[node->getID()] = node; + } + } + for (unsigned i=0; i<nNodes; ++i) + { + if (tmp_nodes[i]) + { + node_id_map[i] = sfc_nodes.size(); + sfc_nodes.push_back(new MeshLib::Node(tmp_nodes[i]->getCoords(), tmp_nodes[i]->getID())); } - std::vector<MeshLib::Node*> new_nodes; - for (unsigned i=0; i<nNodes; i++) - if (tmp_nodes[i]) - new_nodes.push_back(new MeshLib::Node(tmp_nodes[i]->getCoords())); } +} +std::vector<GeoLib::PointWithID*> MshEditor::getSurfaceNodes(const MeshLib::Mesh &mesh, const double *dir) +{ + INFO ("Extracting surface nodes..."); + const std::vector<MeshLib::Element*> all_elements (mesh.getElements()); + const std::vector<MeshLib::Node*> all_nodes (mesh.getNodes()); + + std::vector<MeshLib::Element*> sfc_elements; + get2DSurfaceElements(all_elements, sfc_elements, dir, mesh.getDimension()); + + std::vector<MeshLib::Node*> sfc_nodes; + std::vector<unsigned> node_id_map(mesh.getNNodes()); + get2DSurfaceNodes(all_nodes, sfc_nodes, sfc_elements, node_id_map); + + const unsigned nElements (sfc_elements.size()); + for (unsigned i=0; i<nElements; ++i) + delete sfc_elements[i]; + const size_t nNodes (sfc_nodes.size()); + std::vector<GeoLib::PointWithID*> surface_pnts(nNodes); + for (unsigned i=0; i<nNodes; ++i) + { + surface_pnts[i] = new GeoLib::PointWithID(sfc_nodes[i]->getCoords(), sfc_nodes[i]->getID()); + delete sfc_nodes[i]; + } + return surface_pnts; } + } // end namespace MeshLib diff --git a/MeshLib/MshEditor.h b/MeshLib/MshEditor.h index 787593abd2f..c373feca762 100644 --- a/MeshLib/MshEditor.h +++ b/MeshLib/MshEditor.h @@ -25,6 +25,7 @@ namespace MeshLib { // forward declarations class Mesh; class Element; +class Node; /** * \brief A set of tools for manipulating existing meshes @@ -32,9 +33,6 @@ class Element; class MshEditor { public: - MshEditor() {} - ~MshEditor() {} - /// Returns the area assigned to each node on a surface mesh. static void getSurfaceAreaForNodes(const MeshLib::Mesh* mesh, std::vector<double> &node_area_vec); @@ -42,12 +40,17 @@ public: static MeshLib::Mesh* removeMeshNodes(MeshLib::Mesh* mesh, const std::vector<std::size_t> &nodes); /// Returns the surface nodes of a layered mesh. - static std::vector<GeoLib::PointWithID*> getSurfaceNodes(const MeshLib::Mesh &mesh); + static std::vector<GeoLib::PointWithID*> getSurfaceNodes(const MeshLib::Mesh &mesh, const double* dir = NULL); /// Returns the 2d-element mesh representing the surface of the given layered mesh. - static MeshLib::Mesh* getMeshSurface(const MeshLib::Mesh &mesh, const double* dir); + static MeshLib::Mesh* getMeshSurface(const MeshLib::Mesh &mesh, const double* dir = NULL); private: + /// Functionality needed for getSurfaceNodes() and getMeshSurface() + static void get2DSurfaceElements(const std::vector<MeshLib::Element*> &all_elements, std::vector<MeshLib::Element*> &sfc_elements, const double* dir, unsigned mesh_dimension); + + /// Functionality needed for getSurfaceNodes() and getMeshSurface() + static void get2DSurfaceNodes(const std::vector<MeshLib::Node*> &all_nodes, std::vector<MeshLib::Node*> &sfc_nodes, const std::vector<MeshLib::Element*> &sfc_elements, std::vector<unsigned> &node_id_map); }; } // end namespace MeshLib diff --git a/MeshLib/Node.h b/MeshLib/Node.h index e329d61fb28..fb9009b74ad 100644 --- a/MeshLib/Node.h +++ b/MeshLib/Node.h @@ -34,9 +34,8 @@ class Node : public GeoLib::PointWithID { /* friend functions: */ friend MeshLib::Mesh* MshEditor::removeMeshNodes(MeshLib::Mesh* mesh, const std::vector<std::size_t> &nodes); - friend int MshLayerMapper::LayerMapping(MeshLib::Mesh* msh, const std::string &rasterfile, - const std::size_t nLayers, const std::size_t layer_id, - bool removeNoDataValues); + friend int MshLayerMapper::LayerMapping(MeshLib::Mesh* msh, const std::string &rasterfile, const std::size_t nLayers, + const std::size_t layer_id, bool removeNoDataValues); /* friend classes: */ friend class Mesh; friend class MeshCoarsener; -- GitLab