MOAB: Mesh Oriented datABase  (version 5.4.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 */,
00107                                     const char* /* tag_name */,
00108                                     const FileOptions& /* opts */,
00109                                     std::vector< int >& /* tag_values_out */,
00110                                     const SubsetList* /* subset_list */ )
00111 {
00112     return MB_NOT_IMPLEMENTED;
00113 }
00114 
00115 ErrorCode ReadSmf::load_file( const char* filename,
00116                               const EntityHandle* /* file_set */,
00117                               const FileOptions& opts,
00118                               const ReaderIface::SubsetList* subset_list,
00119                               const Tag* file_id_tag )
00120 {
00121     ErrorCode result;
00122     lineNo       = 0;
00123     commandNo    = 0;
00124     versionMajor = 0;
00125     versionMinor = 0;
00126 
00127     if( subset_list )
00128     {
00129         MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for VTK" );
00130     }
00131 
00132     // Does the caller want a field to be used for partitioning the entities?
00133     // If not, we'll assume any scalar integer field named MATERIAL_SET specifies partitions.
00134     std::string partition_tag_name;
00135     result = opts.get_option( "PARTITION", partition_tag_name );
00136     if( result == MB_SUCCESS ) mPartitionTagName = partition_tag_name;
00137 
00138     std::ifstream smfFile( filename );
00139     if( !smfFile ) return MB_FILE_DOES_NOT_EXIST;
00140 
00141     ivar.next_face   = 1;
00142     ivar.next_vertex = 1;
00143     state.push_back( SMF_State( ivar ) );
00144 
00145     while( smfFile.getline( line, SMF_MAXLINE, '\n' ).good() )
00146     {
00147         ++lineNo;
00148         result = parse_line( line );
00149         if( MB_SUCCESS != result ) return result;
00150     }
00151 
00152     if( !smfFile.eof() )
00153     {
00154         // Parsing terminated for a reason other than EOF: signal failure.
00155         return MB_FILE_WRITE_ERROR;
00156     }
00157 
00158     // At this point we have _numNodesInFile vertices and _numElementsInFile triangles
00159     // the coordinates are in _coords, and connectivities in _connec
00160     // std::vector<double> _coords; // 3*numNodes; we might not know the number of nodes
00161     // std::vector<int> _connec; // 3*num of elements; we might not know them;
00162 
00163     // Create vertices
00164     std::vector< double* > arrays;
00165     EntityHandle start_handle_out;
00166     start_handle_out = 0;
00167     result           = readMeshIface->get_node_coords( 3, _numNodesInFile, MB_START_ID, start_handle_out, arrays );
00168 
00169     if( MB_SUCCESS != result ) return result;
00170 
00171     // Fill the arrays with data from _coords
00172     // Cppcheck warning (false positive): variable arrays is assigned a value that is never used
00173     for( int i = 0; i < _numNodesInFile; i++ )
00174     {
00175         int i3       = 3 * i;
00176         arrays[0][i] = _coords[i3];
00177         arrays[1][i] = _coords[i3 + 1];
00178         arrays[2][i] = _coords[i3 + 2];
00179     }
00180     // Elements
00181 
00182     EntityHandle start_handle_elem_out;
00183     start_handle_elem_out = 0;
00184     EntityHandle* conn_array_out;
00185     result = readMeshIface->get_element_connect( _numElementsInFile, 3,
00186                                                  MBTRI,  // EntityType
00187                                                  MB_START_ID, start_handle_elem_out, conn_array_out );
00188     if( MB_SUCCESS != result ) return result;
00189     for( int j = 0; j < _numElementsInFile * 3; j++ )
00190         conn_array_out[j] = _connec[j];
00191 
00192     // Notify MOAB of the new elements
00193     result = readMeshIface->update_adjacencies( start_handle_elem_out, _numElementsInFile, 3, conn_array_out );
00194 
00195     if( MB_SUCCESS != result ) return result;
00196 
00197     if( file_id_tag )
00198     {
00199         Range nodes( start_handle_out, start_handle_out + _numNodesInFile - 1 );
00200         Range elems( start_handle_elem_out, start_handle_elem_out + _numElementsInFile - 1 );
00201         readMeshIface->assign_ids( *file_id_tag, nodes );
00202         readMeshIface->assign_ids( *file_id_tag, elems );
00203     }
00204 
00205     return MB_SUCCESS;
00206 }
00207 
00208 ErrorCode ReadSmf::annotation( char* cmd, std::vector< std::string >& argv )
00209 {
00210     // Skip over the '#$' prefix
00211     cmd += 2;
00212 
00213     if( streq( cmd, "SMF" ) )
00214     {
00215         // If SMF version is specified, it must be the first
00216         // thing specified in the file.
00217         if( commandNo > 1 )
00218         {
00219             MB_SET_ERR( MB_FILE_WRITE_ERROR, "SMF file version specified at line " << lineNo );
00220         }
00221 
00222         if( 2 == sscanf( argv[0].c_str(), "%d.%d", &versionMajor, &versionMinor ) )
00223         {
00224             if( versionMajor != 1 || versionMinor != 0 )
00225             {
00226                 MB_SET_ERR( MB_FILE_WRITE_ERROR,
00227                             "Unsupported SMF file version: " << versionMajor << "." << versionMinor );
00228             }
00229         }
00230         else
00231         {
00232             MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid SMF version annotation" );
00233         }
00234     }
00235     else if( streq( cmd, "vertices" ) )
00236     {
00237         if( argv.size() == 1 )
00238             _numNodes = atoi( argv[0].c_str() );
00239         else
00240             bad_annotation( cmd );
00241     }
00242     else if( streq( cmd, "faces" ) )
00243     {
00244         if( argv.size() == 1 )
00245             _numFaces = atoi( argv[0].c_str() );
00246         else
00247             bad_annotation( cmd );
00248     }
00249     else if( streq( cmd, "BBox" ) )
00250     {
00251     }
00252     else if( streq( cmd, "BSphere" ) )
00253     {
00254     }
00255     else if( streq( cmd, "PXform" ) )
00256     {
00257         if( argv.size() == 16 )
00258         {
00259             // parse_mat(argv);
00260         }
00261         else
00262             bad_annotation( cmd );
00263     }
00264     else if( streq( cmd, "MXform" ) )
00265     {
00266         if( argv.size() == 16 )
00267         {
00268             // parse_mat(argv);
00269         }
00270         else
00271             bad_annotation( cmd );
00272     }
00273 
00274     return MB_SUCCESS;
00275 }
00276 
00277 ErrorCode ReadSmf::parse_line( char* ln )
00278 {
00279     char *cmd, *s;
00280     std::vector< std::string > argv;
00281     ErrorCode err;
00282 
00283     while( *ln == ' ' || *ln == '\t' )
00284         ln++;  // Skip initial white space
00285 
00286     // Ignore empty lines
00287     if( ln[0] == '\n' || ln[0] == '\0' ) return MB_SUCCESS;
00288 
00289     // Ignore comments
00290     if( ln[0] == '#' && ln[1] != '$' ) return MB_SUCCESS;
00291 
00292     // First, split the line into tokens
00293     cmd = strtok( ln, " \t\n" );
00294 
00295     while( ( s = strtok( NULL, " \t\n" ) ) )
00296     {
00297         std::string stg( s );
00298         argv.push_back( stg );
00299     }
00300 
00301     // Figure out what command it is and execute it
00302     if( cmd[0] == '#' && cmd[1] == '$' )
00303     {
00304         err = annotation( cmd, argv );
00305         if( MB_SUCCESS != err ) return err;
00306     }
00307     else
00308     {
00309         cmd_entry* entry = &read_cmds[0];
00310         bool handled     = false;
00311 
00312         while( entry->name && !handled )
00313         {
00314             if( streq( entry->name, cmd ) )
00315             {
00316                 err = ( this->*( entry->cmd ) )( argv );
00317                 if( MB_SUCCESS != err ) return err;
00318                 handled = true;
00319                 ++commandNo;
00320             }
00321             else
00322                 entry++;
00323         }
00324 
00325         if( !handled )
00326         {
00327             // If the first command was invalid, this probably
00328             // wasn't an Smf file. Fail silently in this case.
00329             // If versionMajor is set, then we saw an initial #$SMF,
00330             // in which case it must be a SMF file.
00331             if( !versionMajor && !commandNo ) return MB_FILE_WRITE_ERROR;
00332 
00333             // Invalid command:
00334             MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Illegal SMF command at line " << lineNo << ": \"" << cmd << "\"" );
00335         }
00336     }
00337 
00338     return MB_SUCCESS;
00339 }
00340 
00341 ErrorCode ReadSmf::check_length( int count, const std::vector< std::string >& argv )
00342 {
00343     if( ( argv.size() < (unsigned)count ) || ( argv.size() > (unsigned)count && argv[count][0] != '#' ) )
00344     {
00345         MB_SET_ERR( MB_FILE_WRITE_ERROR, "Expect " << count << " arguments at line " << lineNo );
00346     }
00347 
00348     return MB_SUCCESS;
00349 }
00350 
00351 ErrorCode ReadSmf::parse_doubles( int count, const std::vector< std::string >& argv, double results[] )
00352 {
00353     ErrorCode rval = check_length( count, argv );
00354     if( MB_SUCCESS != rval ) return rval;
00355 
00356     char* endptr;
00357     for( int i = 0; i < count; i++ )
00358     {
00359         results[i] = strtod( argv[i].c_str(), &endptr );
00360         if( *endptr )
00361         {
00362             MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid vertex coordinates at line " << lineNo );
00363         }
00364     }
00365 
00366     return MB_SUCCESS;
00367 }
00368 
00369 ErrorCode ReadSmf::vertex( std::vector< std::string >& argv )
00370 {
00371     double v[3];
00372     ErrorCode err = parse_doubles( 3, argv, v );
00373     if( MB_SUCCESS != err ) return err;
00374 
00375     state.back().vertex( v );
00376     ivar.next_vertex++;
00377     _numNodesInFile++;
00378     for( int j = 0; j < 3; j++ )
00379         _coords.push_back( v[j] );
00380     // model->in_Vertex(v);
00381     return MB_SUCCESS;
00382 }
00383 
00384 ErrorCode ReadSmf::v_normal( std::vector< std::string >& /*argv*/ )
00385 {
00386     return MB_SUCCESS;
00387 }
00388 
00389 ErrorCode ReadSmf::v_color( std::vector< std::string >& /*argv*/ )
00390 {
00391     return MB_SUCCESS;
00392 }
00393 
00394 ErrorCode ReadSmf::f_color( std::vector< std::string >& /*argv*/ )
00395 {
00396     return MB_SUCCESS;
00397 }
00398 
00399 ErrorCode ReadSmf::face( std::vector< std::string >& argv )
00400 {
00401     ErrorCode err = check_length( 3, argv );
00402     if( MB_SUCCESS != err ) return err;
00403 
00404     int vert[3] = {};
00405     char* endptr;
00406     for( unsigned int i = 0; i < argv.size(); i++ )
00407     {
00408         vert[i] = strtol( argv[i].c_str(), &endptr, 0 );
00409         if( *endptr )
00410         {
00411             MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid face spec at line " << lineNo );
00412         }
00413     }
00414 
00415     state.back().face( vert, ivar );
00416     ivar.next_face++;
00417     for( int j = 0; j < 3; j++ )
00418         _connec.push_back( vert[j] );
00419     _numElementsInFile++;
00420 
00421     return MB_SUCCESS;
00422 }
00423 
00424 ErrorCode ReadSmf::begin( std::vector< std::string >& /*argv*/ )
00425 {
00426     state.push_back( SMF_State( ivar, &state.back() ) );
00427 
00428     return MB_SUCCESS;
00429 }
00430 
00431 ErrorCode ReadSmf::end( std::vector< std::string >& /*argv*/ )
00432 {
00433     // There must always be at least one state on the stack.
00434     // Don't let mismatched begin/end statements cause us
00435     // to read from an empty vector.
00436     if( state.size() == 1 )
00437     {
00438         MB_SET_ERR( MB_FILE_WRITE_ERROR, "End w/out Begin at line " << lineNo );
00439     }
00440 
00441     state.pop_back();
00442 
00443     return MB_SUCCESS;
00444 }
00445 
00446 ErrorCode ReadSmf::set( std::vector< std::string >& argv )
00447 {
00448     if( argv.size() < 2 || argv[0] != "vertex_coorection" ) return MB_SUCCESS;
00449 
00450     char* endptr;
00451     int val = strtol( argv[1].c_str(), &endptr, 0 );
00452     if( *endptr )
00453     {
00454         MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid value at line " << lineNo );
00455     }
00456 
00457     state.back().set_vertex_correction( val );
00458 
00459     return MB_SUCCESS;
00460 }
00461 
00462 ErrorCode ReadSmf::inc( std::vector< std::string >& /*argv*/ )
00463 {
00464     // std::cerr << "SMF: INC not yet implemented." << std::endl;
00465     return MB_SUCCESS;
00466 }
00467 
00468 ErrorCode ReadSmf::dec( std::vector< std::string >& )
00469 {
00470     // std::cerr << "SMF: DEC not yet implemented." << std::endl;
00471     return MB_SUCCESS;
00472 }
00473 
00474 ErrorCode ReadSmf::trans( std::vector< std::string >& argv )
00475 {
00476     double v3[3];
00477     ErrorCode err = parse_doubles( 3, argv, v3 );
00478     if( MB_SUCCESS != err ) return err;
00479 
00480     AffineXform M = AffineXform::translation( v3 );
00481     // Mat4 M = Mat4::trans(atof(argv(0)), atof(argv(1)), atof(argv(2)));
00482     state.back().mmult( M );
00483 
00484     return MB_SUCCESS;
00485 }
00486 
00487 ErrorCode ReadSmf::scale( std::vector< std::string >& argv )
00488 {
00489     double v3[3];
00490     ErrorCode err = parse_doubles( 3, argv, v3 );
00491     if( MB_SUCCESS != err ) return err;
00492 
00493     AffineXform M = AffineXform::scale( v3 );
00494     // Mat4 M = Mat4::scale(atof(argv(0)), atof(argv(1)), atof(argv(2)));
00495     state.back().mmult( M );
00496 
00497     return MB_SUCCESS;
00498 }
00499 
00500 ErrorCode ReadSmf::rot( std::vector< std::string >& argv )
00501 {
00502     ErrorCode err = check_length( 2, argv );
00503     if( MB_SUCCESS != err ) return err;
00504 
00505     double axis[3]       = { 0., 0., 0. };
00506     std::string axisname = argv.front();
00507     argv.erase( argv.begin() );
00508     if( axisname.size() != 1 )
00509     {
00510         MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo );
00511     }
00512     switch( axisname[0] )
00513     {
00514         case 'x':
00515             axis[0] = 1.;
00516             break;
00517         case 'y':
00518             axis[1] = 1.;
00519             break;
00520         case 'z':
00521             axis[2] = 1.;
00522             break;
00523         default:
00524             MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo );
00525     }
00526 
00527     double angle;
00528     err = parse_doubles( 1, argv, &angle );
00529     if( MB_SUCCESS != err ) return err;
00530     angle *= M_PI / 180.0;
00531 
00532     AffineXform M = AffineXform::rotation( angle, axis );
00533     state.back().mmult( M );
00534 
00535     return MB_SUCCESS;
00536 }
00537 
00538 ErrorCode ReadSmf::mmult( std::vector< std::string >& argv )
00539 {
00540     AffineXform mat;
00541     ErrorCode rval = parse_mat( argv, mat );
00542     if( MB_SUCCESS != rval ) return rval;
00543 
00544     state.back().mmult( mat );
00545 
00546     return MB_SUCCESS;
00547 }
00548 
00549 ErrorCode ReadSmf::mload( std::vector< std::string >& argv )
00550 {
00551     AffineXform mat;
00552     ErrorCode rval = parse_mat( argv, mat );
00553     if( MB_SUCCESS != rval ) return rval;
00554 
00555     state.back().mload( mat );
00556 
00557     return MB_SUCCESS;
00558 }
00559 
00560 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines