![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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
00027 #include
00028 #include
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 _coords; // 3*numNodes; we might not know the number of nodes
00161 // std::vector _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