From 44f4222f2bf8f14d8c2824b198d39b14055aa7f3 Mon Sep 17 00:00:00 2001 From: Karsten Rink <karsten.rink@ufz.de> Date: Wed, 9 Apr 2014 18:37:04 +0200 Subject: [PATCH] removed class variables for nodes and elements and did some small optimisations --- FileIO/TetGenInterface.cpp | 103 +++++++++++++++++++++---------------- FileIO/TetGenInterface.h | 47 +++++++++++------ Gui/mainwindow.cpp | 10 ++-- 3 files changed, 92 insertions(+), 68 deletions(-) diff --git a/FileIO/TetGenInterface.cpp b/FileIO/TetGenInterface.cpp index d58a986c129..908bb9a3ab7 100644 --- a/FileIO/TetGenInterface.cpp +++ b/FileIO/TetGenInterface.cpp @@ -16,6 +16,7 @@ #include <string> // BaseLib +#include "FileTools.h" #include "StringTools.h" // ThirdParty/logog @@ -33,7 +34,7 @@ namespace FileIO { TetGenInterface::TetGenInterface() : - _nodes(), _elements(), _zero_based_idx (false) + _zero_based_idx (false) { } @@ -53,33 +54,37 @@ MeshLib::Mesh* TetGenInterface::readTetGenMesh (std::string const& nodes_fname, ERR ("TetGenInterface::readTetGenMesh failed to open %s", nodes_fname.c_str()); if (!ins_ele) ERR ("TetGenInterface::readTetGenMesh failed to open %s", ele_fname.c_str()); - return NULL; + return nullptr; } - if (!readNodesFromStream (ins_nodes)) { + std::vector<MeshLib::Node*> nodes; + if (!readNodesFromStream (ins_nodes, nodes)) { // remove nodes read until now - for (std::size_t k(0); k<_nodes.size(); k++) { - delete _nodes[k]; + for (std::size_t k(0); k<nodes.size(); k++) { + delete nodes[k]; } - return NULL; + return nullptr; } - if (!readElementsFromStream (ins_ele)) { + std::vector<MeshLib::Element*> elements; + if (!readElementsFromStream (ins_ele, elements, nodes)) { // remove elements read until now - for (std::size_t k(0); k<_elements.size(); k++) { - delete _elements[k]; + for (std::size_t k(0); k<elements.size(); k++) { + delete elements[k]; } // remove nodes - for (std::size_t k(0); k<_nodes.size(); k++) { - delete _nodes[k]; + for (std::size_t k(0); k<nodes.size(); k++) { + delete nodes[k]; } - return NULL; + return nullptr; } - return new MeshLib::Mesh(nodes_fname, _nodes, _elements); + const std::string mesh_name (BaseLib::extractBaseNameWithoutExtension(nodes_fname)); + return new MeshLib::Mesh(mesh_name, nodes, elements); } -bool TetGenInterface::readNodesFromStream (std::ifstream &ins) +bool TetGenInterface::readNodesFromStream (std::ifstream &ins, + std::vector<MeshLib::Node*> &nodes) { std::string line; getline (ins, line); @@ -101,15 +106,18 @@ bool TetGenInterface::readNodesFromStream (std::ifstream &ins) bool header_okay = parseNodesFileHeader(line, n_nodes, dim, n_attributes, boundary_markers); if (!header_okay) return false; - if (!parseNodes(ins, n_nodes, dim)) + if (!parseNodes(ins, nodes, n_nodes, dim)) return false; return true; } return false; } -bool TetGenInterface::parseNodesFileHeader(std::string &line, size_t& n_nodes, size_t& dim, - size_t& n_attributes, bool& boundary_markers) const +bool TetGenInterface::parseNodesFileHeader(std::string &line, + size_t &n_nodes, + size_t &dim, + size_t &n_attributes, + bool &boundary_markers) const { size_t pos_beg, pos_end; @@ -120,7 +128,7 @@ bool TetGenInterface::parseNodesFileHeader(std::string &line, size_t& n_nodes, s n_nodes = BaseLib::str2number<size_t> (line.substr(pos_beg, pos_end - pos_beg)); else { - ERR("TetGenInterface::parseNodesFileHeader(): could not correct read TetGen mesh header - number of nodes"); + ERR("TetGenInterface::parseNodesFileHeader(): could not number of nodes specified in header."); return false; } // dimension @@ -144,17 +152,21 @@ bool TetGenInterface::parseNodesFileHeader(std::string &line, size_t& n_nodes, s return true; } -bool TetGenInterface::parseNodes(std::ifstream& ins, size_t n_nodes, size_t dim) +bool TetGenInterface::parseNodes(std::ifstream &ins, + std::vector<MeshLib::Node*> &nodes, + size_t n_nodes, + size_t dim) { std::size_t pos_beg, pos_end; std::string line; double* coordinates (static_cast<double*> (alloca (sizeof(double) * dim))); + nodes.reserve(n_nodes); for (std::size_t k(0); k < n_nodes && !ins.fail(); k++) { getline(ins, line); if (ins.fail()) { - ERR("TetGenInterface::parseNodes(): error reading node %d, stream error", k); + ERR("TetGenInterface::parseNodes(): Error reading node %d.", k); return false; } if (line.empty()) @@ -170,32 +182,33 @@ bool TetGenInterface::parseNodes(std::ifstream& ins, size_t n_nodes, size_t dim) if (k == 0 && id == 0) _zero_based_idx = true; } else { - ERR("TetGenInterface::parseNodes(): error reading id of node %d", k); + ERR("TetGenInterface::parseNodes(): Error reading ID of node %d.", k); return false; } // read coordinates + const unsigned offset = (_zero_based_idx) ? 0 : 1; for (size_t i(0); i < dim; i++) { pos_beg = line.find_first_not_of(" ", pos_end); pos_end = line.find_first_of(" \n", pos_beg); if (pos_end == std::string::npos) pos_end = line.size(); if (pos_beg != std::string::npos) - coordinates[i] = BaseLib::str2number<double> ( - line.substr(pos_beg, pos_end - pos_beg)); + coordinates[i] = BaseLib::str2number<double>(line.substr(pos_beg, pos_end-pos_beg)); else { - ERR("TetGenInterface::parseNodes(): error reading coordinate %d of node %d", i, k); + ERR("TetGenInterface::parseNodes(): error reading coordinate %d of node %d.", i, k); return false; } } - if (!_zero_based_idx) id--; - // since CFEMesh is our friend we can access private data of mesh - _nodes.push_back(new MeshLib::Node(coordinates, id)); + + nodes.push_back(new MeshLib::Node(coordinates, id-offset)); // read attributes and boundary markers ... - at the moment we do not use this information } return true; } -bool TetGenInterface::readElementsFromStream(std::ifstream &ins) +bool TetGenInterface::readElementsFromStream(std::ifstream &ins, + std::vector<MeshLib::Element*> &elements, + const std::vector<MeshLib::Node*> &nodes) { std::string line; getline (ins, line); @@ -218,7 +231,7 @@ bool TetGenInterface::readElementsFromStream(std::ifstream &ins) bool header_okay = parseElementsFileHeader(line, n_tets, n_nodes_per_tet, region_attributes); if (!header_okay) return false; - if (!parseElements(ins, n_tets, n_nodes_per_tet, region_attributes)) + if (!parseElements(ins, elements, nodes, n_tets, n_nodes_per_tet, region_attributes)) return false; return true; } @@ -238,7 +251,7 @@ bool TetGenInterface::parseElementsFileHeader(std::string &line, if (pos_beg != std::string::npos && pos_end != std::string::npos) n_tets = BaseLib::str2number<size_t> (line.substr(pos_beg, pos_end - pos_beg)); else { - ERR("TetGenInterface::parseElementsFileHeader(): could not correct read TetGen mesh header - number of tetrahedras"); + ERR("TetGenInterface::parseElementsFileHeader(): Could not read number of tetrahedra specified in header."); return false; } // nodes per tet - either 4 or 10 @@ -258,19 +271,25 @@ bool TetGenInterface::parseElementsFileHeader(std::string &line, return true; } -bool TetGenInterface::parseElements(std::ifstream& ins, size_t n_tets, size_t n_nodes_per_tet, +bool TetGenInterface::parseElements(std::ifstream& ins, + std::vector<MeshLib::Element*> &elements, + const std::vector<MeshLib::Node*> &nodes, + size_t n_tets, + size_t n_nodes_per_tet, bool region_attribute) { size_t pos_beg, pos_end; std::string line; size_t* ids (static_cast<size_t*>(alloca (sizeof (size_t) * n_nodes_per_tet))); + elements.reserve(n_tets); + const unsigned offset = (_zero_based_idx) ? 0 : 1; for (size_t k(0); k < n_tets && !ins.fail(); k++) { getline (ins, line); if (ins.fail()) { - ERR("TetGenInterface::parseElements(): error reading node %d", k); + ERR("TetGenInterface::parseElements(): Error reading node %d.", k); return false; } if (line.empty()) @@ -284,7 +303,7 @@ bool TetGenInterface::parseElements(std::ifstream& ins, size_t n_tets, size_t n_ if (pos_beg != std::string::npos && pos_end != std::string::npos) id = BaseLib::str2number<size_t>(line.substr(pos_beg, pos_end - pos_beg)); else { - ERR("TetGenInterface::parseElements(): error reading id of tetrahedra %d", k); + ERR("TetGenInterface::parseElements(): Error reading id of tetrahedron %d.", k); return false; } // read node ids @@ -294,20 +313,14 @@ bool TetGenInterface::parseElements(std::ifstream& ins, size_t n_tets, size_t n_ pos_end = line.find_first_of(" ", pos_beg); if (pos_end == std::string::npos) pos_end = line.size(); - if (pos_beg != std::string::npos && pos_end != - std::string::npos) - ids[i] = BaseLib::str2number<std::size_t>(line.substr(pos_beg, pos_end - pos_beg)); + if (pos_beg != std::string::npos && pos_end != std::string::npos) + ids[i] = BaseLib::str2number<std::size_t>(line.substr(pos_beg, pos_end - pos_beg)) - offset; else { - ERR("TetGenInterface::parseElements(): error reading node %d of tetrahedra %d", i, k); + ERR("TetGenInterface::parseElements(): Error reading node %d of tetrahedron %d.", i, k); return false; } } - if (!_zero_based_idx) { - id--; - for (size_t i(0); i < n_nodes_per_tet; i++) - ids[i]--; - } // read region attribute - this is something like material group unsigned region (0); @@ -318,16 +331,16 @@ bool TetGenInterface::parseElements(std::ifstream& ins, size_t n_tets, size_t n_ if (pos_beg != std::string::npos && pos_end != std::string::npos) region = BaseLib::str2number<unsigned> (line.substr(pos_beg, pos_end - pos_beg)); else { - ERR("TetGenInterface::parseElements(): error reading region attribute of tetrahedra %d", k); + ERR("TetGenInterface::parseElements(): Error reading region attribute of tetrahedron %d.", k); return false; } } // insert new element into vector MeshLib::Node** tet_nodes = new MeshLib::Node*[4]; for (unsigned k(0); k<4; k++) { - tet_nodes[k] = _nodes[ids[k]]; + tet_nodes[k] = nodes[ids[k]]; } - _elements.push_back (new MeshLib::Tet(tet_nodes, region)); + elements.push_back (new MeshLib::Tet(tet_nodes, region)); } return true; } diff --git a/FileIO/TetGenInterface.h b/FileIO/TetGenInterface.h index 4535d956c2b..20186e7f173 100644 --- a/FileIO/TetGenInterface.h +++ b/FileIO/TetGenInterface.h @@ -57,7 +57,9 @@ private: * @param input the input stream * @return true, if all information is read, false if the method detects an error */ - bool readNodesFromStream(std::ifstream &input); + bool readNodesFromStream(std::ifstream &input, + std::vector<MeshLib::Node*> &nodes); + /** * Method parses the header of the nodes file created by TetGen * @param line the header is in this string (input) @@ -67,24 +69,35 @@ private: * @param boundary_markers have the nodes boundary information (output) * @return true, if the file header is read, false if the method detects an error */ - bool parseNodesFileHeader(std::string &line, std::size_t& n_nodes, std::size_t& dim, - std::size_t& n_attributes, bool& boundary_markers) const; + bool parseNodesFileHeader(std::string &line, + std::size_t &n_nodes, + std::size_t &dim, + std::size_t &n_attributes, + bool &boundary_markers) const; /** * method parses the lines reading the nodes from TetGen nodes file * @param ins the input stream (input) + * @param nodes the nodes vector to be filled (input) * @param n_nodes the number of nodes to read (input) * @param dim the spatial dimension of the node (input) * @return true, if the nodes are read, false if the method detects an error */ - bool parseNodes(std::ifstream& ins, std::size_t n_nodes, std::size_t dim); + bool parseNodes(std::ifstream &ins, + std::vector<MeshLib::Node*> &nodes, + std::size_t n_nodes, + std::size_t dim); /** * Method reads the elements from stream and stores them in the element vector of the mesh class. * For this purpose it uses methods parseElementsFileHeader() and parseElements(). - * @param input the input stream + * @param the input stream + * @param the elements vector to be filled + * @param the node information needed for creating elements * @return true, if all information is read, false if the method detects an error */ - bool readElementsFromStream(std::ifstream &input); + bool readElementsFromStream(std::ifstream &input, + std::vector<MeshLib::Element*> &elements, + const std::vector<MeshLib::Node*> &nodes); /** * Method parses the header of the elements file created by TetGen * @param line @@ -93,27 +106,27 @@ private: * @param region_attribute is on output true, if there * @return */ - bool parseElementsFileHeader(std::string &line, std::size_t& n_tets, std::size_t& n_nodes_per_tet, - bool& region_attribute) const; + bool parseElementsFileHeader(std::string &line, + std::size_t &n_tets, + std::size_t &n_nodes_per_tet, + bool ®ion_attribute) const; /** * Method parses the tetrahedras and put them in the element vector of the mesh class. * @param ins the input stream + * @param the elements vector to be filled + * @param the node information needed for creating elements * @param n_tets the number of tetrahedras that should be read * @param n_nodes_per_tet the number of nodes per tetrahedron * @param region_attribute if region attribute is true, region information is read * @return true, if the tetrahedras are read, false if the method detects an error */ - bool parseElements(std::ifstream& ins, std::size_t n_tets, std::size_t n_nodes_per_tet, + bool parseElements(std::ifstream& ins, + std::vector<MeshLib::Element*> &elements, + const std::vector<MeshLib::Node*> &nodes, + std::size_t n_tets, + std::size_t n_nodes_per_tet, bool region_attribute); - /** - * the nodes later on handed over to the mesh are stored in this vector - */ - std::vector<MeshLib::Node*> _nodes; - /** - * the elements (tetrahedrons) later on handed over to the mesh are stored in this vector - */ - std::vector<MeshLib::Element*> _elements; /** * the value is true if the indexing is zero based, else false */ diff --git a/Gui/mainwindow.cpp b/Gui/mainwindow.cpp index 686db0be5e9..c7ee9f45873 100644 --- a/Gui/mainwindow.cpp +++ b/Gui/mainwindow.cpp @@ -694,12 +694,10 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName) if (!fileName.isEmpty() && !element_fname.isEmpty()) { FileIO::TetGenInterface tetgen; - MeshLib::Mesh* msh (tetgen.readTetGenMesh(fileName.toStdString(), element_fname.toStdString())); - if (msh) { - std::string name(fileName.toStdString()); - msh->setName(name); - _meshModels->addMesh(msh); - } else + MeshLib::Mesh* mesh (tetgen.readTetGenMesh(fileName.toStdString(), element_fname.toStdString())); + if (mesh) + _meshModels->addMesh(mesh); + else OGSError::box("Failed to load a TetGen mesh."); } } -- GitLab