MOAB: Mesh Oriented datABase
(version 5.3.1)
|
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 { 00334 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Expect " << count << " arguments at line " << lineNo ); 00335 } 00336 00337 return MB_SUCCESS; 00338 } 00339 00340 ErrorCode ReadSmf::parse_doubles( int count, const std::vector< std::string >& argv, double results[] ) 00341 { 00342 ErrorCode rval = check_length( count, argv ); 00343 if( MB_SUCCESS != rval ) return rval; 00344 00345 char* endptr; 00346 for( int i = 0; i < count; i++ ) 00347 { 00348 results[i] = strtod( argv[i].c_str(), &endptr ); 00349 if( *endptr ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid vertex coordinates at line " << lineNo ); } 00350 } 00351 00352 return MB_SUCCESS; 00353 } 00354 00355 ErrorCode ReadSmf::vertex( std::vector< std::string >& argv ) 00356 { 00357 double v[3]; 00358 ErrorCode err = parse_doubles( 3, argv, v ); 00359 if( MB_SUCCESS != err ) return err; 00360 00361 state.back().vertex( v ); 00362 ivar.next_vertex++; 00363 _numNodesInFile++; 00364 for( int j = 0; j < 3; j++ ) 00365 _coords.push_back( v[j] ); 00366 // model->in_Vertex(v); 00367 return MB_SUCCESS; 00368 } 00369 00370 ErrorCode ReadSmf::v_normal( std::vector< std::string >& /*argv*/ ) 00371 { 00372 return MB_SUCCESS; 00373 } 00374 00375 ErrorCode ReadSmf::v_color( std::vector< std::string >& /*argv*/ ) 00376 { 00377 return MB_SUCCESS; 00378 } 00379 00380 ErrorCode ReadSmf::f_color( std::vector< std::string >& /*argv*/ ) 00381 { 00382 return MB_SUCCESS; 00383 } 00384 00385 ErrorCode ReadSmf::face( std::vector< std::string >& argv ) 00386 { 00387 ErrorCode err = check_length( 3, argv ); 00388 if( MB_SUCCESS != err ) return err; 00389 00390 int vert[3] = {}; 00391 char* endptr; 00392 for( unsigned int i = 0; i < argv.size(); i++ ) 00393 { 00394 vert[i] = strtol( argv[i].c_str(), &endptr, 0 ); 00395 if( *endptr ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid face spec at line " << lineNo ); } 00396 } 00397 00398 state.back().face( vert, ivar ); 00399 ivar.next_face++; 00400 for( int j = 0; j < 3; j++ ) 00401 _connec.push_back( vert[j] ); 00402 _numElementsInFile++; 00403 00404 return MB_SUCCESS; 00405 } 00406 00407 ErrorCode ReadSmf::begin( std::vector< std::string >& /*argv*/ ) 00408 { 00409 state.push_back( SMF_State( ivar, &state.back() ) ); 00410 00411 return MB_SUCCESS; 00412 } 00413 00414 ErrorCode ReadSmf::end( std::vector< std::string >& /*argv*/ ) 00415 { 00416 // There must always be at least one state on the stack. 00417 // Don't let mismatched begin/end statements cause us 00418 // to read from an empty vector. 00419 if( state.size() == 1 ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "End w/out Begin at line " << lineNo ); } 00420 00421 state.pop_back(); 00422 00423 return MB_SUCCESS; 00424 } 00425 00426 ErrorCode ReadSmf::set( std::vector< std::string >& argv ) 00427 { 00428 if( argv.size() < 2 || argv[0] != "vertex_coorection" ) return MB_SUCCESS; 00429 00430 char* endptr; 00431 int val = strtol( argv[1].c_str(), &endptr, 0 ); 00432 if( *endptr ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid value at line " << lineNo ); } 00433 00434 state.back().set_vertex_correction( val ); 00435 00436 return MB_SUCCESS; 00437 } 00438 00439 ErrorCode ReadSmf::inc( std::vector< std::string >& /*argv*/ ) 00440 { 00441 // std::cerr << "SMF: INC not yet implemented." << std::endl; 00442 return MB_SUCCESS; 00443 } 00444 00445 ErrorCode ReadSmf::dec( std::vector< std::string >& ) 00446 { 00447 // std::cerr << "SMF: DEC not yet implemented." << std::endl; 00448 return MB_SUCCESS; 00449 } 00450 00451 ErrorCode ReadSmf::trans( std::vector< std::string >& argv ) 00452 { 00453 double v3[3]; 00454 ErrorCode err = parse_doubles( 3, argv, v3 ); 00455 if( MB_SUCCESS != err ) return err; 00456 00457 AffineXform M = AffineXform::translation( v3 ); 00458 // Mat4 M = Mat4::trans(atof(argv(0)), atof(argv(1)), atof(argv(2))); 00459 state.back().mmult( M ); 00460 00461 return MB_SUCCESS; 00462 } 00463 00464 ErrorCode ReadSmf::scale( std::vector< std::string >& argv ) 00465 { 00466 double v3[3]; 00467 ErrorCode err = parse_doubles( 3, argv, v3 ); 00468 if( MB_SUCCESS != err ) return err; 00469 00470 AffineXform M = AffineXform::scale( v3 ); 00471 // Mat4 M = Mat4::scale(atof(argv(0)), atof(argv(1)), atof(argv(2))); 00472 state.back().mmult( M ); 00473 00474 return MB_SUCCESS; 00475 } 00476 00477 ErrorCode ReadSmf::rot( std::vector< std::string >& argv ) 00478 { 00479 ErrorCode err = check_length( 2, argv ); 00480 if( MB_SUCCESS != err ) return err; 00481 00482 double axis[3] = { 0., 0., 0. }; 00483 std::string axisname = argv.front(); 00484 argv.erase( argv.begin() ); 00485 if( axisname.size() != 1 ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo ); } 00486 switch( axisname[0] ) 00487 { 00488 case 'x': 00489 axis[0] = 1.; 00490 break; 00491 case 'y': 00492 axis[1] = 1.; 00493 break; 00494 case 'z': 00495 axis[2] = 1.; 00496 break; 00497 default: 00498 MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo ); 00499 } 00500 00501 double angle; 00502 err = parse_doubles( 1, argv, &angle ); 00503 if( MB_SUCCESS != err ) return err; 00504 angle *= M_PI / 180.0; 00505 00506 AffineXform M = AffineXform::rotation( angle, axis ); 00507 state.back().mmult( M ); 00508 00509 return MB_SUCCESS; 00510 } 00511 00512 ErrorCode ReadSmf::mmult( std::vector< std::string >& argv ) 00513 { 00514 AffineXform mat; 00515 ErrorCode rval = parse_mat( argv, mat ); 00516 if( MB_SUCCESS != rval ) return rval; 00517 00518 state.back().mmult( mat ); 00519 00520 return MB_SUCCESS; 00521 } 00522 00523 ErrorCode ReadSmf::mload( std::vector< std::string >& argv ) 00524 { 00525 AffineXform mat; 00526 ErrorCode rval = parse_mat( argv, mat ); 00527 if( MB_SUCCESS != rval ) return rval; 00528 00529 state.back().mload( mat ); 00530 00531 return MB_SUCCESS; 00532 } 00533 00534 } // namespace moab