MOAB: Mesh Oriented datABase  (version 5.2.1)
ReadSmf.cpp
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 /**
00017  * \class ReadSmf
00018  * \brief SMF reader from QSLIM
00019  * \author Michael Garland
00020  */
00021 
00022 #ifdef _WIN32              /* windows */
00023 #define _USE_MATH_DEFINES  // For M_PI
00024 #endif
00025 
00026 #include <cassert>
00027 #include <cstdlib>
00028 #include <iostream>
00029 
00030 #include "ReadSmf.hpp"
00031 #include "moab/Range.hpp"
00032 #include "Internals.hpp"
00033 #include "moab/Interface.hpp"
00034 #include "moab/ReadUtilIface.hpp"
00035 #include "moab/FileOptions.hpp"
00036 #include "AffineXform.hpp"
00037 
00038 static inline int streq( const char* a, const char* b )
00039 {
00040     return strcmp( a, b ) == 0;
00041 }
00042 
00043 namespace moab
00044 {
00045 
00046 ReadSmf::cmd_entry ReadSmf::read_cmds[] = { { "v", &ReadSmf::vertex },
00047                                             { ":vn", &ReadSmf::v_normal },
00048                                             { ":vc", &ReadSmf::v_color },
00049                                             { ":fc", &ReadSmf::f_color },
00050                                             { "t", &ReadSmf::face },
00051                                             { "f", &ReadSmf::face },
00052 
00053                                             { "begin", &ReadSmf::begin },
00054                                             { "end", &ReadSmf::end },
00055                                             { "set", &ReadSmf::set },
00056                                             { "inc", &ReadSmf::inc },
00057                                             { "dec", &ReadSmf::dec },
00058 
00059                                             { "mmult", &ReadSmf::mload },
00060                                             { "mload", &ReadSmf::mmult },
00061                                             { "trans", &ReadSmf::trans },
00062                                             { "scale", &ReadSmf::scale },
00063                                             { "rot", &ReadSmf::rot },
00064 
00065                                             { NULL, NULL } };
00066 
00067 ErrorCode ReadSmf::parse_mat( const std::vector< std::string >& argv, AffineXform& mat )
00068 {
00069     double values[12];
00070     ErrorCode err = parse_doubles( 12, argv, values );
00071     if( MB_SUCCESS != err ) return err;
00072 
00073     mat = AffineXform( values, values + 9 );
00074     return MB_SUCCESS;
00075 }
00076 
00077 void ReadSmf::bad_annotation( const char* cmd )
00078 {
00079     std::cerr << "SMF: Malformed annotation [" << cmd << "]" << std::endl;
00080 }
00081 
00082 ReaderIface* ReadSmf::factory( Interface* iface )
00083 {
00084     return new ReadSmf( iface );
00085 }
00086 
00087 ReadSmf::ReadSmf( Interface* impl )
00088     : mdbImpl( impl ), mCurrentMeshHandle( 0 ), lineNo( 0 ), commandNo( 0 ), versionMajor( 0 ), versionMinor( 0 )
00089 {
00090     mdbImpl->query_interface( readMeshIface );
00091     ivar.next_vertex = 0;
00092     ivar.next_face   = 0;
00093     _numNodes = _numFaces = 0;
00094     _numNodesInFile = _numElementsInFile = 0;
00095 }
00096 
00097 ReadSmf::~ReadSmf()
00098 {
00099     if( readMeshIface )
00100     {
00101         mdbImpl->release_interface( readMeshIface );
00102         readMeshIface = 0;
00103     }
00104 }
00105 
00106 ErrorCode ReadSmf::read_tag_values( const char* /* file_name */, const char* /* tag_name */,
00107                                     const FileOptions& /* opts */, std::vector< int >& /* tag_values_out */,
00108                                     const SubsetList* /* subset_list */ )
00109 {
00110     return MB_NOT_IMPLEMENTED;
00111 }
00112 
00113 ErrorCode ReadSmf::load_file( const char* filename, const EntityHandle* /* file_set */, const FileOptions& opts,
00114                               const ReaderIface::SubsetList* subset_list, const Tag* file_id_tag )
00115 {
00116     ErrorCode result;
00117     lineNo       = 0;
00118     commandNo    = 0;
00119     versionMajor = 0;
00120     versionMinor = 0;
00121 
00122     if( subset_list ) { MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for VTK" ); }
00123 
00124     // Does the caller want a field to be used for partitioning the entities?
00125     // If not, we'll assume any scalar integer field named MATERIAL_SET specifies partitions.
00126     std::string partition_tag_name;
00127     result = opts.get_option( "PARTITION", partition_tag_name );
00128     if( result == MB_SUCCESS ) mPartitionTagName = partition_tag_name;
00129 
00130     std::ifstream smfFile( filename );
00131     if( !smfFile ) return MB_FILE_DOES_NOT_EXIST;
00132 
00133     ivar.next_face   = 1;
00134     ivar.next_vertex = 1;
00135     state.push_back( SMF_State( ivar ) );
00136 
00137     while( smfFile.getline( line, SMF_MAXLINE, '\n' ).good() )
00138     {
00139         ++lineNo;
00140         result = parse_line( line );
00141         if( MB_SUCCESS != result ) return result;
00142     }
00143 
00144     if( !smfFile.eof() )
00145     {
00146         // Parsing terminated for a reason other than EOF: signal failure.
00147         return MB_FILE_WRITE_ERROR;
00148     }
00149 
00150     // At this point we have _numNodesInFile vertices and _numElementsInFile triangles
00151     // the coordinates are in _coords, and connectivities in _connec
00152     // std::vector<double> _coords; // 3*numNodes; we might not know the number of nodes
00153     // std::vector<int> _connec; // 3*num of elements; we might not know them;
00154 
00155     // Create vertices
00156     std::vector< double* > arrays;
00157     EntityHandle start_handle_out;
00158     start_handle_out = 0;
00159     result           = readMeshIface->get_node_coords( 3, _numNodesInFile, MB_START_ID, start_handle_out, arrays );
00160 
00161     if( MB_SUCCESS != result ) return result;
00162 
00163     // Fill the arrays with data from _coords
00164     // Cppcheck warning (false positive): variable arrays is assigned a value that is never used
00165     for( int i = 0; i < _numNodesInFile; i++ )
00166     {
00167         int i3       = 3 * i;
00168         arrays[0][i] = _coords[i3];
00169         arrays[1][i] = _coords[i3 + 1];
00170         arrays[2][i] = _coords[i3 + 2];
00171     }
00172     // Elements
00173 
00174     EntityHandle start_handle_elem_out;
00175     start_handle_elem_out = 0;
00176     EntityHandle* conn_array_out;
00177     result = readMeshIface->get_element_connect( _numElementsInFile, 3,
00178                                                  MBTRI,  // EntityType
00179                                                  MB_START_ID, start_handle_elem_out, conn_array_out );
00180     if( MB_SUCCESS != result ) return result;
00181     for( int j = 0; j < _numElementsInFile * 3; j++ )
00182         conn_array_out[j] = _connec[j];
00183 
00184     // Notify MOAB of the new elements
00185     result = readMeshIface->update_adjacencies( start_handle_elem_out, _numElementsInFile, 3, conn_array_out );
00186 
00187     if( MB_SUCCESS != result ) return result;
00188 
00189     if( file_id_tag )
00190     {
00191         Range nodes( start_handle_out, start_handle_out + _numNodesInFile - 1 );
00192         Range elems( start_handle_elem_out, start_handle_elem_out + _numElementsInFile - 1 );
00193         readMeshIface->assign_ids( *file_id_tag, nodes );
00194         readMeshIface->assign_ids( *file_id_tag, elems );
00195     }
00196 
00197     return MB_SUCCESS;
00198 }
00199 
00200 ErrorCode ReadSmf::annotation( char* cmd, std::vector< std::string >& argv )
00201 {
00202     // Skip over the '#$' prefix
00203     cmd += 2;
00204 
00205     if( streq( cmd, "SMF" ) )
00206     {
00207         // If SMF version is specified, it must be the first
00208         // thing specified in the file.
00209         if( commandNo > 1 ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "SMF file version specified at line " << lineNo ); }
00210 
00211         if( 2 == sscanf( argv[0].c_str(), "%d.%d", &versionMajor, &versionMinor ) )
00212         {
00213             if( versionMajor != 1 || versionMinor != 0 )
00214             {
00215                 MB_SET_ERR( MB_FILE_WRITE_ERROR,
00216                             "Unsupported SMF file version: " << versionMajor << "." << versionMinor );
00217             }
00218         }
00219         else
00220         {
00221             MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid SMF version annotation" );
00222         }
00223     }
00224     else if( streq( cmd, "vertices" ) )
00225     {
00226         if( argv.size() == 1 )
00227             _numNodes = atoi( argv[0].c_str() );
00228         else
00229             bad_annotation( cmd );
00230     }
00231     else if( streq( cmd, "faces" ) )
00232     {
00233         if( argv.size() == 1 )
00234             _numFaces = atoi( argv[0].c_str() );
00235         else
00236             bad_annotation( cmd );
00237     }
00238     else if( streq( cmd, "BBox" ) )
00239     {
00240     }
00241     else if( streq( cmd, "BSphere" ) )
00242     {
00243     }
00244     else if( streq( cmd, "PXform" ) )
00245     {
00246         if( argv.size() == 16 )
00247         {
00248             // parse_mat(argv);
00249         }
00250         else
00251             bad_annotation( cmd );
00252     }
00253     else if( streq( cmd, "MXform" ) )
00254     {
00255         if( argv.size() == 16 )
00256         {
00257             // parse_mat(argv);
00258         }
00259         else
00260             bad_annotation( cmd );
00261     }
00262 
00263     return MB_SUCCESS;
00264 }
00265 
00266 ErrorCode ReadSmf::parse_line( char* ln )
00267 {
00268     char *cmd, *s;
00269     std::vector< std::string > argv;
00270     ErrorCode err;
00271 
00272     while( *ln == ' ' || *ln == '\t' )
00273         ln++;  // Skip initial white space
00274 
00275     // Ignore empty lines
00276     if( ln[0] == '\n' || ln[0] == '\0' ) return MB_SUCCESS;
00277 
00278     // Ignore comments
00279     if( ln[0] == '#' && ln[1] != '$' ) return MB_SUCCESS;
00280 
00281     // First, split the line into tokens
00282     cmd = strtok( ln, " \t\n" );
00283 
00284     while( ( s = strtok( NULL, " \t\n" ) ) )
00285     {
00286         std::string stg( s );
00287         argv.push_back( stg );
00288     }
00289 
00290     // Figure out what command it is and execute it
00291     if( cmd[0] == '#' && cmd[1] == '$' )
00292     {
00293         err = annotation( cmd, argv );
00294         if( MB_SUCCESS != err ) return err;
00295     }
00296     else
00297     {
00298         cmd_entry* entry = &read_cmds[0];
00299         bool handled     = false;
00300 
00301         while( entry->name && !handled )
00302         {
00303             if( streq( entry->name, cmd ) )
00304             {
00305                 err = ( this->*( entry->cmd ) )( argv );
00306                 if( MB_SUCCESS != err ) return err;
00307                 handled = true;
00308                 ++commandNo;
00309             }
00310             else
00311                 entry++;
00312         }
00313 
00314         if( !handled )
00315         {
00316             // If the first command was invalid, this probably
00317             // wasn't an Smf file. Fail silently in this case.
00318             // If versionMajor is set, then we saw an initial #$SMF,
00319             // in which case it must be a SMF file.
00320             if( !versionMajor && !commandNo ) return MB_FILE_WRITE_ERROR;
00321 
00322             // Invalid command:
00323             MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Illegal SMF command at line " << lineNo << ": \"" << cmd << "\"" );
00324         }
00325     }
00326 
00327     return MB_SUCCESS;
00328 }
00329 
00330 ErrorCode ReadSmf::check_length( int count, const std::vector< std::string >& argv )
00331 {
00332     if( ( argv.size() < (unsigned)count ) || ( argv.size() > (unsigned)count && argv[count][0] != '#' ) )
00333     { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Expect " << count << " arguments at line " << lineNo ); }
00334 
00335     return MB_SUCCESS;
00336 }
00337 
00338 ErrorCode ReadSmf::parse_doubles( int count, const std::vector< std::string >& argv, double results[] )
00339 {
00340     ErrorCode rval = check_length( count, argv );
00341     if( MB_SUCCESS != rval ) return rval;
00342 
00343     char* endptr;
00344     for( int i = 0; i < count; i++ )
00345     {
00346         results[i] = strtod( argv[i].c_str(), &endptr );
00347         if( *endptr ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid vertex coordinates at line " << lineNo ); }
00348     }
00349 
00350     return MB_SUCCESS;
00351 }
00352 
00353 ErrorCode ReadSmf::vertex( std::vector< std::string >& argv )
00354 {
00355     double v[3];
00356     ErrorCode err = parse_doubles( 3, argv, v );
00357     if( MB_SUCCESS != err ) return err;
00358 
00359     state.back().vertex( v );
00360     ivar.next_vertex++;
00361     _numNodesInFile++;
00362     for( int j = 0; j < 3; j++ )
00363         _coords.push_back( v[j] );
00364     // model->in_Vertex(v);
00365     return MB_SUCCESS;
00366 }
00367 
00368 ErrorCode ReadSmf::v_normal( std::vector< std::string >& /*argv*/ )
00369 {
00370     return MB_SUCCESS;
00371 }
00372 
00373 ErrorCode ReadSmf::v_color( std::vector< std::string >& /*argv*/ )
00374 {
00375     return MB_SUCCESS;
00376 }
00377 
00378 ErrorCode ReadSmf::f_color( std::vector< std::string >& /*argv*/ )
00379 {
00380     return MB_SUCCESS;
00381 }
00382 
00383 ErrorCode ReadSmf::face( std::vector< std::string >& argv )
00384 {
00385     ErrorCode err = check_length( 3, argv );
00386     if( MB_SUCCESS != err ) return err;
00387 
00388     int vert[3] = {};
00389     char* endptr;
00390     for( unsigned int i = 0; i < argv.size(); i++ )
00391     {
00392         vert[i] = strtol( argv[i].c_str(), &endptr, 0 );
00393         if( *endptr ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid face spec at line " << lineNo ); }
00394     }
00395 
00396     state.back().face( vert, ivar );
00397     ivar.next_face++;
00398     for( int j = 0; j < 3; j++ )
00399         _connec.push_back( vert[j] );
00400     _numElementsInFile++;
00401 
00402     return MB_SUCCESS;
00403 }
00404 
00405 ErrorCode ReadSmf::begin( std::vector< std::string >& /*argv*/ )
00406 {
00407     state.push_back( SMF_State( ivar, &state.back() ) );
00408 
00409     return MB_SUCCESS;
00410 }
00411 
00412 ErrorCode ReadSmf::end( std::vector< std::string >& /*argv*/ )
00413 {
00414     // There must always be at least one state on the stack.
00415     // Don't let mismatched begin/end statements cause us
00416     // to read from an empty vector.
00417     if( state.size() == 1 ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "End w/out Begin at line " << lineNo ); }
00418 
00419     state.pop_back();
00420 
00421     return MB_SUCCESS;
00422 }
00423 
00424 ErrorCode ReadSmf::set( std::vector< std::string >& argv )
00425 {
00426     if( argv.size() < 2 || argv[0] != "vertex_coorection" ) return MB_SUCCESS;
00427 
00428     char* endptr;
00429     int val = strtol( argv[1].c_str(), &endptr, 0 );
00430     if( *endptr ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid value at line " << lineNo ); }
00431 
00432     state.back().set_vertex_correction( val );
00433 
00434     return MB_SUCCESS;
00435 }
00436 
00437 ErrorCode ReadSmf::inc( std::vector< std::string >& /*argv*/ )
00438 {
00439     // std::cerr << "SMF: INC not yet implemented." << std::endl;
00440     return MB_SUCCESS;
00441 }
00442 
00443 ErrorCode ReadSmf::dec( std::vector< std::string >& )
00444 {
00445     // std::cerr << "SMF: DEC not yet implemented." << std::endl;
00446     return MB_SUCCESS;
00447 }
00448 
00449 ErrorCode ReadSmf::trans( std::vector< std::string >& argv )
00450 {
00451     double v3[3];
00452     ErrorCode err = parse_doubles( 3, argv, v3 );
00453     if( MB_SUCCESS != err ) return err;
00454 
00455     AffineXform M = AffineXform::translation( v3 );
00456     // Mat4 M = Mat4::trans(atof(argv(0)), atof(argv(1)), atof(argv(2)));
00457     state.back().mmult( M );
00458 
00459     return MB_SUCCESS;
00460 }
00461 
00462 ErrorCode ReadSmf::scale( std::vector< std::string >& argv )
00463 {
00464     double v3[3];
00465     ErrorCode err = parse_doubles( 3, argv, v3 );
00466     if( MB_SUCCESS != err ) return err;
00467 
00468     AffineXform M = AffineXform::scale( v3 );
00469     // Mat4 M = Mat4::scale(atof(argv(0)), atof(argv(1)), atof(argv(2)));
00470     state.back().mmult( M );
00471 
00472     return MB_SUCCESS;
00473 }
00474 
00475 ErrorCode ReadSmf::rot( std::vector< std::string >& argv )
00476 {
00477     ErrorCode err = check_length( 2, argv );
00478     if( MB_SUCCESS != err ) return err;
00479 
00480     double axis[3]       = { 0., 0., 0. };
00481     std::string axisname = argv.front();
00482     argv.erase( argv.begin() );
00483     if( axisname.size() != 1 ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo ); }
00484     switch( axisname[0] )
00485     {
00486         case 'x':
00487             axis[0] = 1.;
00488             break;
00489         case 'y':
00490             axis[1] = 1.;
00491             break;
00492         case 'z':
00493             axis[2] = 1.;
00494             break;
00495         default:
00496             MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo );
00497     }
00498 
00499     double angle;
00500     err = parse_doubles( 1, argv, &angle );
00501     if( MB_SUCCESS != err ) return err;
00502     angle *= M_PI / 180.0;
00503 
00504     AffineXform M = AffineXform::rotation( angle, axis );
00505     state.back().mmult( M );
00506 
00507     return MB_SUCCESS;
00508 }
00509 
00510 ErrorCode ReadSmf::mmult( std::vector< std::string >& argv )
00511 {
00512     AffineXform mat;
00513     ErrorCode rval = parse_mat( argv, mat );
00514     if( MB_SUCCESS != rval ) return rval;
00515 
00516     state.back().mmult( mat );
00517 
00518     return MB_SUCCESS;
00519 }
00520 
00521 ErrorCode ReadSmf::mload( std::vector< std::string >& argv )
00522 {
00523     AffineXform mat;
00524     ErrorCode rval = parse_mat( argv, mat );
00525     if( MB_SUCCESS != rval ) return rval;
00526 
00527     state.back().mload( mat );
00528 
00529     return MB_SUCCESS;
00530 }
00531 
00532 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines