moab
|
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