Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ReadSmf.cpp
Go to the documentation of this file.
1 /** 2  * MOAB, a Mesh-Oriented datABase, is a software component for creating, 3  * storing and accessing finite element mesh data. 4  * 5  * Copyright 2004 Sandia Corporation. Under the terms of Contract 6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 7  * retains certain rights in this software. 8  * 9  * This library is free software; you can redistribute it and/or 10  * modify it under the terms of the GNU Lesser General Public 11  * License as published by the Free Software Foundation; either 12  * version 2.1 of the License, or (at your option) any later version. 13  * 14  */ 15  16 /** 17  * \class ReadSmf 18  * \brief SMF reader from QSLIM 19  * \author Michael Garland 20  */ 21  22 #ifdef _WIN32 /* windows */ 23 #define _USE_MATH_DEFINES // For M_PI 24 #endif 25  26 #include <cassert> 27 #include <cstdlib> 28 #include <iostream> 29  30 #include "ReadSmf.hpp" 31 #include "moab/Range.hpp" 32 #include "Internals.hpp" 33 #include "moab/Interface.hpp" 34 #include "moab/ReadUtilIface.hpp" 35 #include "moab/FileOptions.hpp" 36 #include "AffineXform.hpp" 37  38 static inline int streq( const char* a, const char* b ) 39 { 40  return strcmp( a, b ) == 0; 41 } 42  43 namespace moab 44 { 45  46 ReadSmf::cmd_entry ReadSmf::read_cmds[] = { { "v", &ReadSmf::vertex }, 47  { ":vn", &ReadSmf::v_normal }, 48  { ":vc", &ReadSmf::v_color }, 49  { ":fc", &ReadSmf::f_color }, 50  { "t", &ReadSmf::face }, 51  { "f", &ReadSmf::face }, 52  53  { "begin", &ReadSmf::begin }, 54  { "end", &ReadSmf::end }, 55  { "set", &ReadSmf::set }, 56  { "inc", &ReadSmf::inc }, 57  { "dec", &ReadSmf::dec }, 58  59  { "mmult", &ReadSmf::mload }, 60  { "mload", &ReadSmf::mmult }, 61  { "trans", &ReadSmf::trans }, 62  { "scale", &ReadSmf::scale }, 63  { "rot", &ReadSmf::rot }, 64  65  { NULL, NULL } }; 66  67 ErrorCode ReadSmf::parse_mat( const std::vector< std::string >& argv, AffineXform& mat ) 68 { 69  double values[12]; 70  ErrorCode err = parse_doubles( 12, argv, values ); 71  if( MB_SUCCESS != err ) return err; 72  73  mat = AffineXform( values, values + 9 ); 74  return MB_SUCCESS; 75 } 76  77 void ReadSmf::bad_annotation( const char* cmd ) 78 { 79  std::cerr << "SMF: Malformed annotation [" << cmd << "]" << std::endl; 80 } 81  82 ReaderIface* ReadSmf::factory( Interface* iface ) 83 { 84  return new ReadSmf( iface ); 85 } 86  87 ReadSmf::ReadSmf( Interface* impl ) 88  : mdbImpl( impl ), mCurrentMeshHandle( 0 ), lineNo( 0 ), commandNo( 0 ), versionMajor( 0 ), versionMinor( 0 ) 89 { 90  mdbImpl->query_interface( readMeshIface ); 91  ivar.next_vertex = 0; 92  ivar.next_face = 0; 93  _numNodes = _numFaces = 0; 94  _numNodesInFile = _numElementsInFile = 0; 95 } 96  97 ReadSmf::~ReadSmf() 98 { 99  if( readMeshIface ) 100  { 101  mdbImpl->release_interface( readMeshIface ); 102  readMeshIface = 0; 103  } 104 } 105  106 ErrorCode ReadSmf::read_tag_values( const char* /* file_name */, 107  const char* /* tag_name */, 108  const FileOptions& /* opts */, 109  std::vector< int >& /* tag_values_out */, 110  const SubsetList* /* subset_list */ ) 111 { 112  return MB_NOT_IMPLEMENTED; 113 } 114  115 ErrorCode ReadSmf::load_file( const char* filename, 116  const EntityHandle* /* file_set */, 117  const FileOptions& opts, 118  const ReaderIface::SubsetList* subset_list, 119  const Tag* file_id_tag ) 120 { 121  ErrorCode result; 122  lineNo = 0; 123  commandNo = 0; 124  versionMajor = 0; 125  versionMinor = 0; 126  127  if( subset_list ) 128  { 129  MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for VTK" ); 130  } 131  132  // Does the caller want a field to be used for partitioning the entities? 133  // If not, we'll assume any scalar integer field named MATERIAL_SET specifies partitions. 134  std::string partition_tag_name; 135  result = opts.get_option( "PARTITION", partition_tag_name ); 136  if( result == MB_SUCCESS ) mPartitionTagName = partition_tag_name; 137  138  std::ifstream smfFile( filename ); 139  if( !smfFile ) return MB_FILE_DOES_NOT_EXIST; 140  141  ivar.next_face = 1; 142  ivar.next_vertex = 1; 143  state.push_back( SMF_State( ivar ) ); 144  145  while( smfFile.getline( line, SMF_MAXLINE, '\n' ).good() ) 146  { 147  ++lineNo; 148  result = parse_line( line ); 149  if( MB_SUCCESS != result ) return result; 150  } 151  152  if( !smfFile.eof() ) 153  { 154  // Parsing terminated for a reason other than EOF: signal failure. 155  return MB_FILE_WRITE_ERROR; 156  } 157  158  // At this point we have _numNodesInFile vertices and _numElementsInFile triangles 159  // the coordinates are in _coords, and connectivities in _connec 160  // std::vector<double> _coords; // 3*numNodes; we might not know the number of nodes 161  // std::vector<int> _connec; // 3*num of elements; we might not know them; 162  163  // Create vertices 164  std::vector< double* > arrays; 165  EntityHandle start_handle_out; 166  start_handle_out = 0; 167  result = readMeshIface->get_node_coords( 3, _numNodesInFile, MB_START_ID, start_handle_out, arrays ); 168  169  if( MB_SUCCESS != result ) return result; 170  171  // Fill the arrays with data from _coords 172  // Cppcheck warning (false positive): variable arrays is assigned a value that is never used 173  for( int i = 0; i < _numNodesInFile; i++ ) 174  { 175  int i3 = 3 * i; 176  arrays[0][i] = _coords[i3]; 177  arrays[1][i] = _coords[i3 + 1]; 178  arrays[2][i] = _coords[i3 + 2]; 179  } 180  // Elements 181  182  EntityHandle start_handle_elem_out; 183  start_handle_elem_out = 0; 184  EntityHandle* conn_array_out; 185  result = readMeshIface->get_element_connect( _numElementsInFile, 3, 186  MBTRI, // EntityType 187  MB_START_ID, start_handle_elem_out, conn_array_out ); 188  if( MB_SUCCESS != result ) return result; 189  for( int j = 0; j < _numElementsInFile * 3; j++ ) 190  conn_array_out[j] = _connec[j]; 191  192  // Notify MOAB of the new elements 193  result = readMeshIface->update_adjacencies( start_handle_elem_out, _numElementsInFile, 3, conn_array_out ); 194  195  if( MB_SUCCESS != result ) return result; 196  197  if( file_id_tag ) 198  { 199  Range nodes( start_handle_out, start_handle_out + _numNodesInFile - 1 ); 200  Range elems( start_handle_elem_out, start_handle_elem_out + _numElementsInFile - 1 ); 201  readMeshIface->assign_ids( *file_id_tag, nodes ); 202  readMeshIface->assign_ids( *file_id_tag, elems ); 203  } 204  205  return MB_SUCCESS; 206 } 207  208 ErrorCode ReadSmf::annotation( char* cmd, std::vector< std::string >& argv ) 209 { 210  // Skip over the '#$' prefix 211  cmd += 2; 212  213  if( streq( cmd, "SMF" ) ) 214  { 215  // If SMF version is specified, it must be the first 216  // thing specified in the file. 217  if( commandNo > 1 ) 218  { 219  MB_SET_ERR( MB_FILE_WRITE_ERROR, "SMF file version specified at line " << lineNo ); 220  } 221  222  if( 2 == sscanf( argv[0].c_str(), "%d.%d", &versionMajor, &versionMinor ) ) 223  { 224  if( versionMajor != 1 || versionMinor != 0 ) 225  { 226  MB_SET_ERR( MB_FILE_WRITE_ERROR, 227  "Unsupported SMF file version: " << versionMajor << "." << versionMinor ); 228  } 229  } 230  else 231  { 232  MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid SMF version annotation" ); 233  } 234  } 235  else if( streq( cmd, "vertices" ) ) 236  { 237  if( argv.size() == 1 ) 238  _numNodes = atoi( argv[0].c_str() ); 239  else 240  bad_annotation( cmd ); 241  } 242  else if( streq( cmd, "faces" ) ) 243  { 244  if( argv.size() == 1 ) 245  _numFaces = atoi( argv[0].c_str() ); 246  else 247  bad_annotation( cmd ); 248  } 249  else if( streq( cmd, "BBox" ) ) 250  { 251  } 252  else if( streq( cmd, "BSphere" ) ) 253  { 254  } 255  else if( streq( cmd, "PXform" ) ) 256  { 257  if( argv.size() == 16 ) 258  { 259  // parse_mat(argv); 260  } 261  else 262  bad_annotation( cmd ); 263  } 264  else if( streq( cmd, "MXform" ) ) 265  { 266  if( argv.size() == 16 ) 267  { 268  // parse_mat(argv); 269  } 270  else 271  bad_annotation( cmd ); 272  } 273  274  return MB_SUCCESS; 275 } 276  277 ErrorCode ReadSmf::parse_line( char* ln ) 278 { 279  char *cmd, *s; 280  std::vector< std::string > argv; 281  ErrorCode err; 282  283  while( *ln == ' ' || *ln == '\t' ) 284  ln++; // Skip initial white space 285  286  // Ignore empty lines 287  if( ln[0] == '\n' || ln[0] == '\0' ) return MB_SUCCESS; 288  289  // Ignore comments 290  if( ln[0] == '#' && ln[1] != '$' ) return MB_SUCCESS; 291  292  // First, split the line into tokens 293  cmd = strtok( ln, " \t\n" ); 294  295  while( ( s = strtok( NULL, " \t\n" ) ) ) 296  { 297  std::string stg( s ); 298  argv.push_back( stg ); 299  } 300  301  // Figure out what command it is and execute it 302  if( cmd[0] == '#' && cmd[1] == '$' ) 303  { 304  err = annotation( cmd, argv ); 305  if( MB_SUCCESS != err ) return err; 306  } 307  else 308  { 309  cmd_entry* entry = &read_cmds[0]; 310  bool handled = false; 311  312  while( entry->name && !handled ) 313  { 314  if( streq( entry->name, cmd ) ) 315  { 316  err = ( this->*( entry->cmd ) )( argv ); 317  if( MB_SUCCESS != err ) return err; 318  handled = true; 319  ++commandNo; 320  } 321  else 322  entry++; 323  } 324  325  if( !handled ) 326  { 327  // If the first command was invalid, this probably 328  // wasn't an Smf file. Fail silently in this case. 329  // If versionMajor is set, then we saw an initial #$SMF, 330  // in which case it must be a SMF file. 331  if( !versionMajor && !commandNo ) return MB_FILE_WRITE_ERROR; 332  333  // Invalid command: 334  MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Illegal SMF command at line " << lineNo << ": \"" << cmd << "\"" ); 335  } 336  } 337  338  return MB_SUCCESS; 339 } 340  341 ErrorCode ReadSmf::check_length( int count, const std::vector< std::string >& argv ) 342 { 343  if( ( argv.size() < (unsigned)count ) || ( argv.size() > (unsigned)count && argv[count][0] != '#' ) ) 344  { 345  MB_SET_ERR( MB_FILE_WRITE_ERROR, "Expect " << count << " arguments at line " << lineNo ); 346  } 347  348  return MB_SUCCESS; 349 } 350  351 ErrorCode ReadSmf::parse_doubles( int count, const std::vector< std::string >& argv, double results[] ) 352 { 353  ErrorCode rval = check_length( count, argv ); 354  if( MB_SUCCESS != rval ) return rval; 355  356  char* endptr; 357  for( int i = 0; i < count; i++ ) 358  { 359  results[i] = strtod( argv[i].c_str(), &endptr ); 360  if( *endptr ) 361  { 362  MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid vertex coordinates at line " << lineNo ); 363  } 364  } 365  366  return MB_SUCCESS; 367 } 368  369 ErrorCode ReadSmf::vertex( std::vector< std::string >& argv ) 370 { 371  double v[3]; 372  ErrorCode err = parse_doubles( 3, argv, v ); 373  if( MB_SUCCESS != err ) return err; 374  375  state.back().vertex( v ); 376  ivar.next_vertex++; 377  _numNodesInFile++; 378  for( int j = 0; j < 3; j++ ) 379  _coords.push_back( v[j] ); 380  // model->in_Vertex(v); 381  return MB_SUCCESS; 382 } 383  384 ErrorCode ReadSmf::v_normal( std::vector< std::string >& /*argv*/ ) 385 { 386  return MB_SUCCESS; 387 } 388  389 ErrorCode ReadSmf::v_color( std::vector< std::string >& /*argv*/ ) 390 { 391  return MB_SUCCESS; 392 } 393  394 ErrorCode ReadSmf::f_color( std::vector< std::string >& /*argv*/ ) 395 { 396  return MB_SUCCESS; 397 } 398  399 ErrorCode ReadSmf::face( std::vector< std::string >& argv ) 400 { 401  ErrorCode err = check_length( 3, argv ); 402  if( MB_SUCCESS != err ) return err; 403  404  int vert[3] = {}; 405  char* endptr; 406  for( unsigned int i = 0; i < argv.size(); i++ ) 407  { 408  vert[i] = strtol( argv[i].c_str(), &endptr, 0 ); 409  if( *endptr ) 410  { 411  MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid face spec at line " << lineNo ); 412  } 413  } 414  415  state.back().face( vert, ivar ); 416  ivar.next_face++; 417  for( int j = 0; j < 3; j++ ) 418  _connec.push_back( vert[j] ); 419  _numElementsInFile++; 420  421  return MB_SUCCESS; 422 } 423  424 ErrorCode ReadSmf::begin( std::vector< std::string >& /*argv*/ ) 425 { 426  state.push_back( SMF_State( ivar, &state.back() ) ); 427  428  return MB_SUCCESS; 429 } 430  431 ErrorCode ReadSmf::end( std::vector< std::string >& /*argv*/ ) 432 { 433  // There must always be at least one state on the stack. 434  // Don't let mismatched begin/end statements cause us 435  // to read from an empty vector. 436  if( state.size() == 1 ) 437  { 438  MB_SET_ERR( MB_FILE_WRITE_ERROR, "End w/out Begin at line " << lineNo ); 439  } 440  441  state.pop_back(); 442  443  return MB_SUCCESS; 444 } 445  446 ErrorCode ReadSmf::set( std::vector< std::string >& argv ) 447 { 448  if( argv.size() < 2 || argv[0] != "vertex_coorection" ) return MB_SUCCESS; 449  450  char* endptr; 451  int val = strtol( argv[1].c_str(), &endptr, 0 ); 452  if( *endptr ) 453  { 454  MB_SET_ERR( MB_FILE_WRITE_ERROR, "Invalid value at line " << lineNo ); 455  } 456  457  state.back().set_vertex_correction( val ); 458  459  return MB_SUCCESS; 460 } 461  462 ErrorCode ReadSmf::inc( std::vector< std::string >& /*argv*/ ) 463 { 464  // std::cerr << "SMF: INC not yet implemented." << std::endl; 465  return MB_SUCCESS; 466 } 467  468 ErrorCode ReadSmf::dec( std::vector< std::string >& ) 469 { 470  // std::cerr << "SMF: DEC not yet implemented." << std::endl; 471  return MB_SUCCESS; 472 } 473  474 ErrorCode ReadSmf::trans( std::vector< std::string >& argv ) 475 { 476  double v3[3]; 477  ErrorCode err = parse_doubles( 3, argv, v3 ); 478  if( MB_SUCCESS != err ) return err; 479  480  AffineXform M = AffineXform::translation( v3 ); 481  // Mat4 M = Mat4::trans(atof(argv(0)), atof(argv(1)), atof(argv(2))); 482  state.back().mmult( M ); 483  484  return MB_SUCCESS; 485 } 486  487 ErrorCode ReadSmf::scale( std::vector< std::string >& argv ) 488 { 489  double v3[3]; 490  ErrorCode err = parse_doubles( 3, argv, v3 ); 491  if( MB_SUCCESS != err ) return err; 492  493  AffineXform M = AffineXform::scale( v3 ); 494  // Mat4 M = Mat4::scale(atof(argv(0)), atof(argv(1)), atof(argv(2))); 495  state.back().mmult( M ); 496  497  return MB_SUCCESS; 498 } 499  500 ErrorCode ReadSmf::rot( std::vector< std::string >& argv ) 501 { 502  ErrorCode err = check_length( 2, argv ); 503  if( MB_SUCCESS != err ) return err; 504  505  double axis[3] = { 0., 0., 0. }; 506  std::string axisname = argv.front(); 507  argv.erase( argv.begin() ); 508  if( axisname.size() != 1 ) 509  { 510  MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo ); 511  } 512  switch( axisname[0] ) 513  { 514  case 'x': 515  axis[0] = 1.; 516  break; 517  case 'y': 518  axis[1] = 1.; 519  break; 520  case 'z': 521  axis[2] = 1.; 522  break; 523  default: 524  MB_SET_ERR( MB_FILE_WRITE_ERROR, "Malformed rotation command at line " << lineNo ); 525  } 526  527  double angle; 528  err = parse_doubles( 1, argv, &angle ); 529  if( MB_SUCCESS != err ) return err; 530  angle *= M_PI / 180.0; 531  532  AffineXform M = AffineXform::rotation( angle, axis ); 533  state.back().mmult( M ); 534  535  return MB_SUCCESS; 536 } 537  538 ErrorCode ReadSmf::mmult( std::vector< std::string >& argv ) 539 { 540  AffineXform mat; 541  ErrorCode rval = parse_mat( argv, mat ); 542  if( MB_SUCCESS != rval ) return rval; 543  544  state.back().mmult( mat ); 545  546  return MB_SUCCESS; 547 } 548  549 ErrorCode ReadSmf::mload( std::vector< std::string >& argv ) 550 { 551  AffineXform mat; 552  ErrorCode rval = parse_mat( argv, mat ); 553  if( MB_SUCCESS != rval ) return rval; 554  555  state.back().mload( mat ); 556  557  return MB_SUCCESS; 558 } 559  560 } // namespace moab