Skip to content
Snippets Groups Projects
Commit 70c8263a authored by Lars Bilke's avatar Lars Bilke
Browse files

Merge pull request #394 from rinkk/TetGenReaderExtension

TetGen geometry import/export
parents 769e5a9b eb2e3b57
No related branches found
No related tags found
No related merge requests found
......@@ -60,6 +60,15 @@ void trim(std::string &str, char ch)
str.erase(str.begin(), str.end());
}
void simplify(std::string &str)
{
trim (str);
str.erase(
std::unique(str.begin(), str.end(), [](char a, char b) { return a == ' ' && b == ' '; }),
str.end()
);
}
std::string stringToUpper(std::string const& str)
{
std::string s = str;
......
......@@ -69,9 +69,16 @@ template<typename T> T str2number (const std::string &str)
/**
* Strip whitespace (or other characters) from the beginning and end of a string.
* Equivalent functionality to Qt::QString::trim().
*/
void trim(std::string &str, char ch=' ');
/**
* Removes multiple whitespaces (or other characters) from within a string.
* Equivalent functionality to Qt::QString::simplify().
*/
void simplify(std::string &str);
/**
* Returns same string with all characters in upper case.
*
......
......@@ -84,7 +84,7 @@ public:
else if (t==ImportFileType::SHAPE)
return "ESRI Shape files (*.shp)";
else if (t==ImportFileType::TETGEN)
return "TetGen node files (*.node)";
return "TetGen node files (*.node *.poly)";
else if (t==ImportFileType::VTK)
return "VTK files (*.vtk *.vti *.vtr *.vts *.vtp *.vtu)";
else return "All files (*.*)";
......
This diff is collapsed.
......@@ -17,6 +17,8 @@
#include <vector>
#include "GEOObjects.h"
// forward declaration of class Node and Element
namespace MeshLib
{
......@@ -28,7 +30,11 @@ namespace MeshLib
namespace FileIO
{
/**
* class TetGenInterface is used to read meshes created by <a href="http://tetgen.berlios.de/">TetGen</a>
* class TetGenInterface is used to read file formats used by <a href="http://tetgen.berlios.de/">TetGen</a>.
* Currently supported formats are:
* poly - Geometric point and surface definition
* node - mesh node / geometric point definition
* ele - mesh element definition
*/
class TetGenInterface
{
......@@ -38,82 +44,124 @@ public:
/**
* Method reads the TetGen mesh from node file and element file.
* @param nodes_fname file name of the nodes file
* @param ele_fname file name of the elements file
* @return on success the method returns a (pointer to a) CFEMesh, else the method returns NULL
* @param poly_fname file name of the poly file
* @param geo_objects where the geometry is written to
* @return on success the method returns true, otherwise it returns false
*/
bool readTetGenPoly (std::string const& poly_fname,
GeoLib::GEOObjects &geo_objects);
/**
* Method reads the TetGen mesh from node file and element file.
* @param nodes_fname file name of the nodes file
* @param ele_fname file name of the elements file
* @return on success the method returns a (pointer to a) CFEMesh, else the method returns nullptr
*/
MeshLib::Mesh* readTetGenMesh (std::string const& nodes_fname,
std::string const& ele_fname);
/** in order to have a direct access to the
* data structures for nodes and elements we make
* class TetGenInterface a friend of the mesh class
/**
* Writes the geometry of a given name to TetGen poly-file.
* @param file_name file name of the new poly file
* @param geo_objects the container for the geometry.
* @param geo_name the name for the geometry.
* @return returns true on success and false otherwise.
*/
friend class MeshLib::Mesh;
bool writeTetGenPoly(const std::string &file_name,
const GeoLib::GEOObjects &geo_objects,
const std::string &geo_name) const;
private:
/// Returns the declared number of facets in the poly file.
std::size_t getNFacets(std::ifstream &input) const;
/**
* Method reads the nodes from stream and stores them in the node vector of the mesh class.
* Method parses the lines reading the facets from TetGen poly file
* @param input the input stream (input)
* @param surfaces the vector of surfaces to be filled (output)
* @param points the point vector needed for creating surfaces (input)
* @return true, if the facets have been read correctly, false if the method detects an error
*/
bool parseFacets(std::ifstream &input,
std::vector<GeoLib::Surface*> &surfaces,
std::vector<GeoLib::Point*> &points) const;
/**
* Method reads the nodes from stream and stores them in a node vector.
* For this purpose it uses methods parseNodesFileHeader() and parseNodes().
* @param input the input stream
* @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)
* @param n_nodes number of nodes in the file (output)
* @param dim the spatial dimension of the node (output)
* @param n_attributes the number of attributes for each node (output)
* @param boundary_markers have the nodes boundary information (output)
* @param line the header is in this string (input)
* @param n_nodes number of nodes in the file (output)
* @param dim the spatial dimension of the node (output)
* @param n_attributes the number of attributes for each node (output)
* @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 n_nodes the number of nodes to read (input)
* @param dim the spatial dimension of the node (input)
* @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.
* Method reads the elements from stream and stores them in an element vector.
* For this purpose it uses methods parseElementsFileHeader() and parseElements().
* @param input the input stream
* @param input the input stream
* @param elements the elements vector to be filled
* @param nodes 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) const;
/**
* Method parses the header of the elements file created by TetGen
* @param line
* @param n_tets
* @param n_nodes_per_tet
* @param region_attribute is on output true, if there
* @param line the header is in this string (input)
* @param n_tets the number of tets to read (input)
* @param n_nodes_per_tet the number of nodes per tets (input)
* @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 &region_attribute) const;
/**
* Method parses the tetrahedras and put them in the element vector of the mesh class.
* @param ins the input stream
* @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
* @param elements the elements vector to be filled
* @param nodes 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 region_attribute);
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) const;
/**
* 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
*/
......
......@@ -446,8 +446,7 @@ void MainWindow::open(int file_type)
QSettings settings;
ImportFileType::type t = static_cast<ImportFileType::type>(file_type);
QString type_str = QString::fromStdString((ImportFileType::convertImportFileTypeToString(t)));
QString fileName = QFileDialog::getOpenFileName(this,
"Select " + type_str + " file to import",
QString fileName = QFileDialog::getOpenFileName(this, "Select " + type_str + " file to import",
settings.value("lastOpenedFileDirectory").toString(),
QString::fromStdString(ImportFileType::getFileSuffixString(t)));
if (!fileName.isEmpty())
......@@ -688,20 +687,25 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName)
}
else if (t == ImportFileType::TETGEN)
{
QString element_fname = QFileDialog::getOpenFileName(this, "Select TetGen element file",
settings.value("lastOpenedTetgenFileDirectory").toString(),
"TetGen element files (*.ele);;");
if (!fileName.isEmpty() && !element_fname.isEmpty()) {
if (fi.suffix().toLower().compare("poly") == 0)
{
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
OGSError::box("Failed to load a TetGen mesh.");
settings.setValue("lastOpenedFileDirectory", QDir(fileName).absolutePath());
tetgen.readTetGenPoly(fileName.toStdString(), *(_project.getGEOObjects()));
}
else {
settings.setValue("lastOpenedTetgenFileDirectory", QFileInfo(fileName).absolutePath());
QString element_fname = QFileDialog::getOpenFileName(this, "Select TetGen element file",
settings.value("lastOpenedTetgenFileDirectory").toString(),
"TetGen element files (*.ele);;");
if (!fileName.isEmpty() && !element_fname.isEmpty()) {
FileIO::TetGenInterface tetgen;
MeshLib::Mesh* mesh (tetgen.readTetGenMesh(fileName.toStdString(), element_fname.toStdString()));
if (mesh)
_meshModels->addMesh(mesh);
else
OGSError::box("Failed to load a TetGen mesh.");
}
}
}
else if (t == ImportFileType::VTK)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment