[MOAB-dev] r2627 - MOAB/trunk
kraftche at mcs.anl.gov
kraftche at mcs.anl.gov
Tue Feb 3 15:48:55 CST 2009
Author: kraftche
Date: 2009-02-03 15:48:54 -0600 (Tue, 03 Feb 2009)
New Revision: 2627
Added:
MOAB/trunk/ReadTetGen.cpp
MOAB/trunk/ReadTetGen.hpp
Modified:
MOAB/trunk/Makefile.am
Log:
read tetget output files
Modified: MOAB/trunk/Makefile.am
===================================================================
--- MOAB/trunk/Makefile.am 2009-02-03 19:33:44 UTC (rev 2626)
+++ MOAB/trunk/Makefile.am 2009-02-03 21:48:54 UTC (rev 2627)
@@ -164,6 +164,8 @@
ReadVtk.hpp \
ReadIDEAS.cpp \
ReadIDEAS.hpp \
+ ReadTetGen.cpp \
+ ReadTetGen.hpp \
ScdElementData.cpp \
ScdElementData.hpp \
ScdVertexData.cpp \
Added: MOAB/trunk/ReadTetGen.cpp
===================================================================
--- MOAB/trunk/ReadTetGen.cpp (rev 0)
+++ MOAB/trunk/ReadTetGen.cpp 2009-02-03 21:48:54 UTC (rev 2627)
@@ -0,0 +1,471 @@
+#include "ReadTetGen.hpp"
+#include "MBInterface.hpp"
+#include "MBRange.hpp"
+#include "MBReadUtilIface.hpp"
+#include "FileOptions.hpp"
+#include "MBTagConventions.hpp"
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <ctype.h>
+#include <map>
+
+MBReaderIface* ReadTetGen::factory( MBInterface* moab )
+ { return new ReadTetGen(moab); }
+
+ReadTetGen::ReadTetGen( MBInterface* moab )
+ : mbIface(moab), readTool(0)
+{
+ void* tool_ptr = 0;
+ MBErrorCode rval = moab->query_interface( "MBReadUtilIface", &tool_ptr );
+ if (MB_SUCCESS == rval)
+ readTool = reinterpret_cast<MBReadUtilIface*>(tool_ptr);
+}
+
+ReadTetGen::~ReadTetGen()
+{
+ if (mbIface && readTool)
+ mbIface->release_interface( "MBReadUtilIface", readTool );
+}
+
+MBErrorCode ReadTetGen::open_file( const std::string& filename,
+ const std::string& basename,
+ const std::string& suffix,
+ const char* exp_suffix,
+ const char* opt_name,
+ const FileOptions& opts,
+ std::ifstream& file_stream,
+ bool file_required )
+{
+ std::string real_file_name;
+ MBErrorCode rval = opts.get_option( opt_name, real_file_name );
+ if (MB_ENTITY_NOT_FOUND == rval || real_file_name.empty()) {
+ if (MB_SUCCESS == rval)
+ file_required = true;
+ if (suffix == exp_suffix) {
+ real_file_name = filename;
+ }
+ else {
+ real_file_name = basename;
+ real_file_name += ".";
+ real_file_name += exp_suffix;
+ }
+ }
+
+ if (!real_file_name.empty())
+ file_stream.open( real_file_name.c_str(), std::ios::in );
+ if (file_required && !file_stream.is_open()) {
+ readTool->report_error( "%s: cannot read file.", real_file_name.c_str() );
+ return MB_FILE_DOES_NOT_EXIST;
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode ReadTetGen::load_file( const char* file_name_c,
+ MBEntityHandle& file_set,
+ const FileOptions& opts,
+ const int*, int )
+{
+ std::ifstream node_file, ele_file, face_file, edge_file;
+ MBErrorCode rval;
+
+ std::string suffix, base, filename(file_name_c);
+ size_t dot_idx = filename.find_last_of( '.' );
+ if (dot_idx == std::string::npos) {
+ base = filename;
+ }
+ else {
+ suffix = filename.substr( dot_idx+1 );
+ for (size_t i = 0; i < suffix.length(); ++i)
+ suffix[i] = tolower(suffix[i]);
+ if (suffix == "node" || suffix == "ele" || suffix == "face" || suffix == "edge") {
+ base = filename.substr( 0, dot_idx );
+ }
+ else {
+ base = filename;
+ suffix.clear();
+ }
+ }
+
+ rval = open_file( filename, base, suffix, "node", "NODE_FILE", opts, node_file, true );
+ if (MB_SUCCESS != rval)
+ return rval;
+ rval = open_file( filename, base, suffix, "ele", "ELE_FILE", opts, ele_file );
+ if (MB_SUCCESS != rval)
+ return rval;
+ rval = open_file( filename, base, suffix, "face", "FACE_FILE", opts, face_file );
+ if (MB_SUCCESS != rval)
+ return rval;
+ rval = open_file( filename, base, suffix, "edge", "EDGE_FILE", opts, edge_file );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ std::vector<MBTag> attr_tags[4];
+ std::vector<int> attr_idx[4];
+ const char* option_names[4] = { "NODE_ATTR_LIST", "EDGE_ATTR_LIST", "TRI_ATTR_LIST", "TET_ATTR_LIST" };
+ const char* group_names[4] = { 0, "CURVE_ID", "SURFACE_ID", "VOLUME_ID" };
+ for (int i = 0; i < 4; ++i) {
+ std::string opt_str;
+ rval = opts.get_str_option( option_names[i], opt_str );
+ if (MB_SUCCESS != rval)
+ continue;
+ rval = parse_attr_list( opt_str, attr_tags[i], attr_idx[i], group_names[i] );
+ if (MB_SUCCESS != rval) {
+ readTool->report_error( "%s: invalid option value.", option_names[i] );
+ return MB_TYPE_OUT_OF_RANGE;
+ }
+ }
+
+ MBRange tets, tris, edges;
+ std::vector<MBEntityHandle> nodes;
+ rval = read_node_file( node_file, &attr_tags[0][0], &attr_idx[0][0], attr_tags[0].size(), nodes );
+ if (MB_SUCCESS == rval && ele_file.is_open())
+ rval = read_elem_file( MBTET, ele_file, nodes, tets );
+ if (MB_SUCCESS == rval && face_file.is_open())
+ rval = read_elem_file( MBTRI, face_file, nodes, tris );
+ if (MB_SUCCESS == rval && edge_file.is_open())
+ rval = read_elem_file( MBEDGE, edge_file, nodes, edges );
+
+ file_set = 0;
+ if (MB_SUCCESS == rval)
+ rval = mbIface->create_meshset( MESHSET_SET, file_set );
+ if (MB_SUCCESS == rval)
+ rval = mbIface->add_entities( file_set, &nodes[0], nodes.size() );
+ if (MB_SUCCESS == rval)
+ rval = mbIface->add_entities( file_set, tets );
+ if (MB_SUCCESS == rval)
+ rval = mbIface->add_entities( file_set, tris );
+ if (MB_SUCCESS == rval)
+ rval = mbIface->add_entities( file_set, edges );
+
+ if (MB_SUCCESS != rval) {
+ if (file_set)
+ mbIface->delete_entities( &file_set, 1 );
+ mbIface->delete_entities( tets );
+ mbIface->delete_entities( tris );
+ mbIface->delete_entities( edges );
+ mbIface->delete_entities( &nodes[0], nodes.size() );
+ }
+
+ return rval;
+}
+
+MBErrorCode ReadTetGen::parse_attr_list( const std::string& option_str,
+ std::vector<MBTag>& tag_list,
+ std::vector<int>& index_list,
+ const char* group_designator )
+{
+ std::vector<std::string> name_list;
+ size_t prev_pos = 0;
+ while (prev_pos != std::string::npos) {
+ size_t pos = option_str.find_first_of( ',', prev_pos );
+ name_list.push_back( option_str.substr( prev_pos, pos ) );
+ prev_pos = pos+1;
+ }
+
+ index_list.resize( name_list.size() );
+ std::map<std::string,int> name_count;
+ for (size_t i = 0; i < name_list.size(); ++i)
+ index_list[i] = name_count[name_list[i]]++;
+
+ for (size_t i = 0; i < name_list.size(); ++i) {
+ if (group_designator && name_list[i] == group_designator) {
+ tag_list[i] = 0;
+ index_list[i] = -1;
+ }
+ else if (name_list.empty()) {
+ tag_list[i] = 0;
+ index_list[i] = 0;
+ }
+ else {
+ MBErrorCode rval = mbIface->tag_create( name_list[i].c_str(),
+ name_count[name_list[i]]*sizeof(double),
+ MB_TAG_DENSE,
+ MB_TYPE_DOUBLE,
+ tag_list[i],
+ 0,
+ true );
+ if (MB_SUCCESS != rval)
+ return rval;
+ }
+ }
+
+ return MB_SUCCESS;
+}
+
+MBErrorCode ReadTetGen::read_line( std::istream& file,
+ std::string& line,
+ int& lineno )
+{
+ // loop until we find a non-empty line
+ do {
+ // read a line
+ line.clear();
+ if (!getline( file, line ))
+ return MB_FILE_WRITE_ERROR;
+ ++lineno;
+ // strip comments from line
+ size_t pos = line.find_first_of( '#' );
+ if (pos != std::string::npos)
+ line = line.substr( 0, pos );
+ // strip leading whitespace from line
+ for (pos = 0; pos < line.length() && isspace(line[pos]); ++pos);
+ if (pos == line.length())
+ line.clear();
+ else if (pos != 0)
+ line = line.substr( pos );
+ } while (line.empty());
+
+ return MB_SUCCESS;
+}
+
+MBErrorCode ReadTetGen::read_line( std::istream& file,
+ double* values_out,
+ int num_values,
+ int& lineno )
+{
+ // get a line of text
+ std::string line;
+ MBErrorCode rval = read_line( file, line, lineno );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ // tokenize line as doubles
+ std::stringstream str(line);
+ for (int i = 0; i < num_values; ++i) {
+ double v;
+ if (!(str >> v)) {
+ readTool->report_error( "Error reading node data at line %d.", lineno );
+ return MB_FAILURE;
+ }
+ values_out[i] = v;
+ }
+
+ // check that we're at the end of the line
+ int junk;
+ if ((str >> junk) || !str.eof()) {
+ readTool->report_error( "Unexpected trailing data for line %d of node data", lineno );
+ return MB_FAILURE;
+ }
+
+ return MB_SUCCESS;
+}
+
+MBErrorCode ReadTetGen::read_node_file( std::istream& file,
+ const MBTag* attr_tag_list,
+ const int* attr_tag_index,
+ int attr_tag_list_len,
+ std::vector<MBEntityHandle>& nodes )
+{
+ int lineno = 0;
+ std::string line;
+ MBErrorCode rval;
+
+ double header_vals[4];
+ rval = read_line( file, header_vals, 4, lineno );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ const int num_vtx = (int)header_vals[0];
+ const int dim = (int)header_vals[1];
+ const int num_attr = (int)header_vals[2];
+ const int bdry_flag = (int)header_vals[3];
+ if (num_vtx < 1 || dim < 2 || dim > 3 || num_attr < 0 || bdry_flag < 0 || bdry_flag > 1) {
+ readTool->report_error( "Invalid header line for node data." );
+ return MB_FAILURE;
+ }
+ if (attr_tag_list_len > num_attr)
+ attr_tag_list_len = num_attr;
+
+ // allocate space for tag data
+ std::map< MBTag, int > tag_size;
+ std::map< MBTag, std::vector<double> > tag_data;
+ for (int i = 0; i < attr_tag_list_len; ++i) {
+ if (!attr_tag_list[i] || attr_tag_index[i] < 0)
+ continue;
+ std::vector<double>& data = tag_data[attr_tag_list[i]];
+ // increase tag size by one value per vertex for each time
+ // we encounter it in the list.
+ data.resize( data.size() + num_vtx );
+ ++tag_size[attr_tag_list[i]];
+ }
+ std::vector<double*> attr_data( attr_tag_list_len );
+ std::vector<int> attr_size( attr_tag_list_len );
+ for (int i = 0; i < attr_tag_list_len; ++i) {
+ if (!attr_tag_list[i] || attr_tag_index[i] < 0) {
+ attr_data[i] = 0;
+ attr_size[i] = 0;
+ }
+ else {
+ attr_data[i] = &(tag_data[attr_tag_list[i]])[0];
+ attr_size[i] = tag_size[attr_tag_list[i]];
+ }
+ }
+
+ // allocate vertices
+ std::vector<double*> coords;
+ MBEntityHandle start_handle;
+ rval = readTool->get_node_arrays( dim, num_vtx, 1, start_handle, coords );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ // read data line for each node
+ nodes.reserve( num_vtx );
+ std::vector<double> data( 1 + dim + num_attr + bdry_flag );
+ std::vector<int> ids(num_vtx);
+ for (int i = 0; i < num_vtx; ++i) {
+ rval = read_line( file, &data[0], data.size(), lineno );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ // get ID
+ ids[i] = (int)data[0];
+ if (ids[i] >= (int)nodes.size())
+ nodes.resize( ids[i] + 1 );
+ nodes[ids[i]] = start_handle + i;
+
+ // get coordiantes
+ for (int j = 0; j < dim; ++j)
+ coords[j][i] = data[j+1];
+
+ // get attribute data
+ for (int j = 0; j < attr_tag_list_len; ++j)
+ if (attr_data[j])
+ attr_data[j][i*attr_size[j]+attr_tag_index[j]] = data[j+1+dim];
+
+ // disgard boundary bit
+ }
+
+ // store tag data
+ MBRange node_range;
+ node_range.insert( start_handle, start_handle + num_vtx - 1 );
+ for (std::map< MBTag, std::vector<double> >::iterator i = tag_data.begin();
+ i != tag_data.end(); ++i) {
+ rval = mbIface->tag_set_data( i->first, node_range, &i->second[0] );
+ if (MB_SUCCESS != rval)
+ return rval;
+ }
+ MBTag idtag;
+ rval = mbIface->tag_get_handle( GLOBAL_ID_TAG_NAME, idtag );
+ if (MB_SUCCESS == rval) {
+ rval = mbIface->tag_set_data( idtag, node_range, &ids[0] );
+ if (MB_SUCCESS != rval)
+ return rval;
+ }
+
+ return MB_SUCCESS;
+}
+
+
+MBErrorCode ReadTetGen::read_elem_file( MBEntityType type,
+ std::istream& file,
+ const std::vector<MBEntityHandle>& nodes,
+ MBRange& elems )
+{
+ int lineno = 0;
+ std::string line;
+ MBErrorCode rval;
+
+ int node_per_elem, have_group_id, dim;
+ double header_vals[3];
+ switch (type) {
+ case MBTET:
+ rval = read_line( file, header_vals, 3, lineno );
+ node_per_elem = (int)header_vals[1];
+ have_group_id = (int)header_vals[2];
+ dim = 3;
+ break;
+ case MBTRI:
+ rval = read_line( file, header_vals, 2, lineno );
+ node_per_elem = 3;
+ have_group_id = (int)header_vals[1];
+ dim = 2;
+ break;
+ case MBEDGE:
+ rval = read_line( file, header_vals, 1, lineno );
+ node_per_elem = 2;
+ have_group_id = 0;
+ dim = 1;
+ break;
+ default:
+ rval = MB_FAILURE;
+ break;
+ }
+ if (MB_SUCCESS != rval)
+ return rval;
+ const int num_elem = (int)header_vals[0];
+ if (num_elem < 1 || node_per_elem < 2 || have_group_id < 0 || have_group_id > 1) {
+ readTool->report_error( "Invalid header line for element data." );
+ return MB_FAILURE;
+ }
+
+ // create group map
+ std::map<double,MBEntityHandle> groups;
+ MBTag dim_tag, id_tag;
+ rval = mbIface->tag_get_handle( GLOBAL_ID_TAG_NAME, id_tag );
+ if (MB_SUCCESS != rval)
+ return rval;
+ rval = mbIface->tag_create( GEOM_DIMENSION_TAG_NAME, sizeof(int),
+ MB_TAG_SPARSE, MB_TYPE_INTEGER, dim_tag,
+ 0, true );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+
+ // allocate elements
+ MBEntityHandle start_handle, *conn_array;
+ rval = readTool->get_element_array( num_elem, node_per_elem, type, 1, start_handle, conn_array );
+ if (MB_SUCCESS != rval)
+ return rval;
+ elems.insert( start_handle, start_handle + num_elem - 1 );
+
+ // read data line for each node
+ std::vector<double> data( 1 + node_per_elem + have_group_id );
+ std::vector<int> ids(num_elem);
+ for (int i = 0; i < num_elem; ++i) {
+ rval = read_line( file, &data[0], data.size(), lineno );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ // get ID
+ ids[i] = (int)data[0];
+
+ // get connectivity
+ for (int j = 0; j < node_per_elem; ++j)
+ conn_array[node_per_elem*i+j] = nodes[data[j+1]];
+
+ // grouping
+ if (have_group_id && 0.0 != data[node_per_elem+1]) {
+ double id = data[node_per_elem+1];
+ MBEntityHandle grp = groups[id];
+ if (0 == grp) {
+ rval = mbIface->create_meshset( MESHSET_SET, grp );
+ if (MB_SUCCESS != rval)
+ return rval;
+ elems.insert( grp );
+ rval = mbIface->tag_set_data( dim_tag, &grp, 1, &dim );
+ if (MB_SUCCESS != rval)
+ return rval;
+ int iid = (int)id;
+ rval = mbIface->tag_set_data( id_tag, &grp, 1, &iid );
+ if (MB_SUCCESS != rval)
+ return rval;
+ groups[id] = grp;
+ }
+ MBEntityHandle handle = start_handle + i;
+ rval = mbIface->add_entities( grp, &handle, 1 );
+ if (MB_SUCCESS != rval)
+ return rval;
+ }
+ }
+
+ // store id data
+ MBRange elems2;
+ elems2.insert( start_handle, start_handle + num_elem - 1 );
+ rval = mbIface->tag_set_data( id_tag, elems2, &ids[0] );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ return MB_SUCCESS;
+}
+
Added: MOAB/trunk/ReadTetGen.hpp
===================================================================
--- MOAB/trunk/ReadTetGen.hpp (rev 0)
+++ MOAB/trunk/ReadTetGen.hpp 2009-02-03 21:48:54 UTC (rev 2627)
@@ -0,0 +1,129 @@
+#ifndef READ_TET_GEN_HPP
+#define READ_TET_GEN_HPP
+
+#include <iosfwd>
+#include "MBForward.hpp"
+#include "MBReaderIface.hpp"
+class MBReadUtilIface;
+
+/* TetGen mesh data is typically split into two or three files:
+ * name.node : node data
+ * name.ele : tet data
+ * name.face : tri data
+ * The reader will attempt to guess the correct file names from
+ * the single input file name unless explicit file names are
+ * specified using file options as described below.
+ *
+ * File options:
+ * NODE_FILE=filename : node file name
+ * ELE_FILE[=filename] : require tet file and optionally specify file name
+ * FACE_FILE[=filename] : reequire tri file and optionally specify file name
+ * EDGE_FILE[=filename] : reequire edge file and optionally specify file name
+ * NODE_ATTR_LIST=name[,name[,...]] : List of tag names in which to store
+ * attribute values. If the same name
+ * is repeated multiple times, multiple
+ * attribute values will be stored in the
+ * same tag as array values in the order
+ * they are read from the file. If a
+ * name is zero-length, the attribute data
+ * will be disgarded.
+ */
+class ReadTetGen : public MBReaderIface
+{
+
+public:
+
+ static MBReaderIface* factory( MBInterface* );
+
+ //! load a file
+ MBErrorCode load_file(const char *file_name,
+ MBEntityHandle& file_set,
+ const FileOptions&,
+ const int* material_set_list,
+ int num_material_sets );
+
+ //! Constructor
+ ReadTetGen(MBInterface* impl = NULL);
+
+ //! Destructor
+ virtual ~ReadTetGen();
+
+private:
+
+ MBInterface* mbIface;
+ MBReadUtilIface* readTool;
+
+ /**\brief Try to open one of several input files
+ *
+ *\param input_file_name The file name as passed in by the application
+ *\param input_name_base If the input file name ends with a known suffix,
+ * the portition of the input file without the suffix.
+ * Otherwise equal to input_file_name.
+ *\param input_file_suffix If the input file name ends with a known suffix,
+ * the suffix. Otherwise empty.
+ *\param file_type_suffix The suffix for the file type that is to be opened.
+ *\param file_name_option The FileOptions option name specifying the file
+ * name to open.
+ *\param opts Input options list.
+ *\param file_stream The stream to open for the file.
+ */
+ MBErrorCode open_file( const std::string& input_file_name,
+ const std::string& input_name_base,
+ const std::string& input_name_suffix,
+ const char* file_type_suffix,
+ const char* file_name_option,
+ const FileOptions& opts,
+ std::ifstream& file_stream,
+ bool file_required = false );
+
+ /**\brief Read a line from a file
+ *
+ * Read the next non-empty line. Strips comments.
+ *\param file The stream to read from
+ *\param line Output: the line read from the stream
+ *\param lineno Incremented for each real line read from the stream
+ * (including disgarded empty and comment lines.)
+ */
+ MBErrorCode read_line( std::istream& file, std::string& line, int& lineno );
+
+ /**\brief Read a line of double values from a file.
+ */
+ MBErrorCode read_line( std::istream& file,
+ double* values_out, int num_values,
+ int& lineno );
+
+ /**\brief Parse option string specifying mapping from
+ * attributes to tags.
+ *
+ * Given a file option string describing the mapping from tetgen
+ * attributes to MOAB tags, parse it and populate the passed vectors.
+ * \param option_str Input: The option string to parse.
+ * \param tag_list Output: A list tag handles, one for each attribute.
+ * Tag handle value will be zero if the attribute
+ * is to be interpreted as a group id.
+ * \param index_list Output: Which array index to store the attribute
+ * value at for a multi-valued tag. Zero for single-
+ * valued tags. -1 if the corresponding attribute value
+ * is to be interpreted as a group ID.
+ * \param group_designator Input: special tag name used to designate an
+ * attribute as the group (surface or volume) ID.
+ */
+ MBErrorCode parse_attr_list( const std::string& option_str,
+ std::vector<MBTag>& tag_list,
+ std::vector<int>& index_list,
+ const char* group_designator = 0 );
+
+ MBErrorCode read_node_file( std::istream& file,
+ const MBTag* attr_tag_list,
+ const int* attr_tag_index,
+ int attr_tag_list_len,
+ std::vector<MBEntityHandle>& nodes );
+
+ MBErrorCode read_elem_file( MBEntityType type,
+ std::istream& file,
+ const std::vector<MBEntityHandle>& nodes,
+ MBRange& elems );
+};
+
+
+#endif // defined(READ_TET_GEN_HPP)
More information about the moab-dev
mailing list