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