MOAB: Mesh Oriented datABase  (version 5.3.0)
ReadVtk.cpp
Go to the documentation of this file.
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 ReadVtk
00018  * \brief VTK reader from Mesquite
00019  * \author Jason Kraftcheck
00020  */
00021 
00022 #include <cassert>
00023 #include <cstdlib>
00024 #include <cstring>
00025 
00026 #include "ReadVtk.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 "FileTokenizer.hpp"
00033 #include "moab/VtkUtil.hpp"
00034 #include "MBTagConventions.hpp"
00035 
00036 // #define MB_VTK_MATERIAL_SETS
00037 #ifdef MB_VTK_MATERIAL_SETS
00038 #include <map>
00039 #endif
00040 
00041 namespace moab
00042 {
00043 
00044 #ifdef MB_VTK_MATERIAL_SETS
00045 
00046 class Hash
00047 {
00048   public:
00049     unsigned long value;
00050 
00051     Hash()
00052     {
00053         this->value = 5381L;
00054     }
00055 
00056     Hash( const unsigned char* bytes, size_t len )
00057     {  // djb2, a hash by dan bernstein presented on comp.lang.c for hashing strings.
00058         this->value = 5381L;
00059         for( ; len; --len, ++bytes )
00060             this->value = this->value * 33 + ( *bytes );
00061     }
00062 
00063     Hash( bool duh )
00064     {
00065         this->value = duh;  // Hashing a single bit with a long is stupid but easy.
00066     }
00067 
00068     Hash( const Hash& src )
00069     {
00070         this->value = src.value;
00071     }
00072 
00073     Hash& operator=( const Hash& src )
00074     {
00075         this->value = src.value;
00076         return *this;
00077     }
00078 
00079     bool operator<( const Hash& other ) const
00080     {
00081         return this->value < other.value;
00082     }
00083 };
00084 
00085 // Pass this class opaque data + a handle and it adds the handle to a set
00086 // whose opaque data has the same hash. If no set exists for the hash,
00087 // it creates one. Each set is tagged with the opaque data.
00088 // When entities with different opaque data have the same hash, they
00089 // will be placed into the same set.
00090 // There will be no collisions when the opaque data is shorter than an
00091 // unsigned long, and this is really the only case we need to support.
00092 // The rest is bonus. Hash does quite well with strings, even those
00093 // with identical prefixes.
00094 class Modulator : public std::map< Hash, EntityHandle >
00095 {
00096   public:
00097     Modulator( Interface* iface ) : mesh( iface ) {}
00098 
00099     ErrorCode initialize( std::string tag_name, DataType mb_type, size_t sz, size_t per_elem )
00100     {
00101         std::vector< unsigned char > default_val;
00102         default_val.resize( sz * per_elem );
00103         ErrorCode rval = this->mesh->tag_get_handle( tag_name.c_str(), per_elem, mb_type, this->tag,
00104                                                      MB_TAG_SPARSE | MB_TAG_BYTES | MB_TAG_CREAT, &default_val[0] );
00105         return rval;
00106     }
00107 
00108     void add_entity( EntityHandle ent, const unsigned char* bytes, size_t len )
00109     {
00110         Hash h( bytes, len );
00111         EntityHandle mset = this->congruence_class( h, bytes );
00112         ErrorCode rval;
00113         rval = this->mesh->add_entities( mset, &ent, 1 );MB_CHK_SET_ERR_RET( rval, "Failed to add entities to mesh" );
00114     }
00115 
00116     void add_entities( Range& range, const unsigned char* bytes, size_t bytes_per_ent )
00117     {
00118         for( Range::iterator it = range.begin(); it != range.end(); ++it, bytes += bytes_per_ent )
00119         {
00120             Hash h( bytes, bytes_per_ent );
00121             EntityHandle mset = this->congruence_class( h, bytes );
00122             ErrorCode rval;
00123             rval = this->mesh->add_entities( mset, &*it, 1 );MB_CHK_SET_ERR_RET( rval, "Failed to add entities to mesh" );
00124         }
00125     }
00126 
00127     EntityHandle congruence_class( const Hash& h, const void* tag_data )
00128     {
00129         std::map< Hash, EntityHandle >::iterator it = this->find( h );
00130         if( it == this->end() )
00131         {
00132             EntityHandle mset;
00133             Range preexist;
00134             ErrorCode rval;
00135             rval = this->mesh->get_entities_by_type_and_tag( 0, MBENTITYSET, &this->tag, &tag_data, 1, preexist );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to get entities by type and tag", (EntityHandle)0 );
00136             if( preexist.size() ) { mset = *preexist.begin(); }
00137             else
00138             {
00139                 rval = this->mesh->create_meshset( MESHSET_SET, mset );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to create mesh set", (EntityHandle)0 );
00140                 rval = this->mesh->tag_set_data( this->tag, &mset, 1, tag_data );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to set tag data", (EntityHandle)0 );
00141             }
00142             ( *this )[h] = mset;
00143             return mset;
00144         }
00145         return it->second;
00146     }
00147 
00148     Interface* mesh;
00149     Tag tag;
00150 };
00151 #endif  // MB_VTK_MATERIAL_SETS
00152 
00153 ReaderIface* ReadVtk::factory( Interface* iface )
00154 {
00155     return new ReadVtk( iface );
00156 }
00157 
00158 ReadVtk::ReadVtk( Interface* impl ) : mdbImpl( impl ), mPartitionTagName( MATERIAL_SET_TAG_NAME )
00159 {
00160     mdbImpl->query_interface( readMeshIface );
00161 }
00162 
00163 ReadVtk::~ReadVtk()
00164 {
00165     if( readMeshIface )
00166     {
00167         mdbImpl->release_interface( readMeshIface );
00168         readMeshIface = 0;
00169     }
00170 }
00171 
00172 const char* const vtk_type_names[] = {
00173     "bit",  "char",          "unsigned_char", "short",  "unsigned_short", "int", "unsigned_int",
00174     "long", "unsigned_long", "float",         "double", "vtkIdType",      0
00175 };
00176 
00177 ErrorCode ReadVtk::read_tag_values( const char* /* file_name */, const char* /* tag_name */,
00178                                     const FileOptions& /* opts */, std::vector< int >& /* tag_values_out */,
00179                                     const SubsetList* /* subset_list */ )
00180 {
00181     return MB_NOT_IMPLEMENTED;
00182 }
00183 
00184 ErrorCode ReadVtk::load_file( const char* filename, const EntityHandle* /* file_set */, const FileOptions& opts,
00185                               const ReaderIface::SubsetList* subset_list, const Tag* file_id_tag )
00186 {
00187     ErrorCode result;
00188 
00189     int major, minor;
00190     char vendor_string[257];
00191     std::vector< Range > element_list;
00192     Range vertices;
00193 
00194     if( subset_list ) { MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for VTK" ); }
00195 
00196     // Does the caller want a field to be used for partitioning the entities?
00197     // If not, we'll assume any scalar integer field named MATERIAL_SET specifies partitions.
00198     std::string partition_tag_name;
00199     result = opts.get_option( "PARTITION", partition_tag_name );
00200     if( result == MB_SUCCESS ) mPartitionTagName = partition_tag_name;
00201 
00202     FILE* file = fopen( filename, "r" );
00203     if( !file ) return MB_FILE_DOES_NOT_EXIST;
00204 
00205     // Read file header
00206 
00207     if( !fgets( vendor_string, sizeof( vendor_string ), file ) )
00208     {
00209         fclose( file );
00210         return MB_FAILURE;
00211     }
00212 
00213     if( !strchr( vendor_string, '\n' ) || 2 != sscanf( vendor_string, "# vtk DataFile Version %d.%d", &major, &minor ) )
00214     {
00215         fclose( file );
00216         return MB_FAILURE;
00217     }
00218 
00219     if( !fgets( vendor_string, sizeof( vendor_string ), file ) )
00220     {
00221         fclose( file );
00222         return MB_FAILURE;
00223     }
00224 
00225     // VTK spec says this should not exceed 256 chars.
00226     if( !strchr( vendor_string, '\n' ) )
00227     {
00228         fclose( file );
00229         MB_SET_ERR( MB_FAILURE, "Vendor string (line 2) exceeds 256 characters" );
00230     }
00231 
00232     // Check file type
00233 
00234     FileTokenizer tokens( file, readMeshIface );
00235     const char* const file_type_names[] = { "ASCII", "BINARY", 0 };
00236     int filetype                        = tokens.match_token( file_type_names );
00237     switch( filetype )
00238     {
00239         case 2:  // BINARY
00240             MB_SET_ERR( MB_FAILURE, "Cannot read BINARY VTK files" );
00241         default:  // ERROR
00242             return MB_FAILURE;
00243         case 1:  // ASCII
00244             break;
00245     }
00246 
00247     // Read the mesh
00248     if( !tokens.match_token( "DATASET" ) ) return MB_FAILURE;
00249     result = vtk_read_dataset( tokens, vertices, element_list );
00250     if( MB_SUCCESS != result ) return result;
00251 
00252     if( file_id_tag )
00253     {
00254         result = store_file_ids( *file_id_tag, vertices, element_list );
00255         if( MB_SUCCESS != result ) return result;
00256     }
00257 
00258     // Count the number of elements read
00259     long elem_count = 0;
00260     for( std::vector< Range >::iterator it = element_list.begin(); it != element_list.end(); ++it )
00261         elem_count += it->size();
00262 
00263     // Read attribute data until end of file.
00264     const char* const block_type_names[] = { "POINT_DATA", "CELL_DATA", 0 };
00265     std::vector< Range > vertex_list( 1 );
00266     vertex_list[0] = vertices;
00267     int blocktype  = 0;
00268     while( !tokens.eof() )
00269     {
00270         // Get POINT_DATA or CELL_DATA
00271         int new_block_type = tokens.match_token( block_type_names, false );
00272         if( tokens.eof() ) break;
00273 
00274         if( !new_block_type )
00275         {
00276             // If next token was neither POINT_DATA nor CELL_DATA,
00277             // then there's another attribute under the current one.
00278             if( blocktype )
00279                 tokens.unget_token();
00280             else
00281                 break;
00282         }
00283         else
00284         {
00285             blocktype = new_block_type;
00286             long count;
00287             if( !tokens.get_long_ints( 1, &count ) ) return MB_FAILURE;
00288 
00289             if( blocktype == 1 && (unsigned long)count != vertices.size() )
00290             {
00291                 MB_SET_ERR( MB_FAILURE, "Count inconsistent with number of vertices at line " << tokens.line_number() );
00292             }
00293             else if( blocktype == 2 && count != elem_count )
00294             {
00295                 MB_SET_ERR( MB_FAILURE, "Count inconsistent with number of elements at line " << tokens.line_number() );
00296             }
00297         }
00298 
00299         if( blocktype == 1 )
00300             result = vtk_read_attrib_data( tokens, vertex_list );
00301         else
00302             result = vtk_read_attrib_data( tokens, element_list );
00303 
00304         if( MB_SUCCESS != result ) return result;
00305     }
00306 
00307     return MB_SUCCESS;
00308 }
00309 
00310 ErrorCode ReadVtk::allocate_vertices( long num_verts, EntityHandle& start_handle_out, double*& x_coord_array_out,
00311                                       double*& y_coord_array_out, double*& z_coord_array_out )
00312 {
00313     ErrorCode result;
00314 
00315     // Create vertices
00316     std::vector< double* > arrays;
00317     start_handle_out = 0;
00318     result           = readMeshIface->get_node_coords( 3, num_verts, MB_START_ID, start_handle_out, arrays );
00319     if( MB_SUCCESS != result ) return result;
00320 
00321     x_coord_array_out = arrays[0];
00322     y_coord_array_out = arrays[1];
00323     z_coord_array_out = arrays[2];
00324 
00325     return MB_SUCCESS;
00326 }
00327 
00328 ErrorCode ReadVtk::read_vertices( FileTokenizer& tokens, long num_verts, EntityHandle& start_handle_out )
00329 {
00330     ErrorCode result;
00331     double *x, *y, *z;
00332 
00333     result = allocate_vertices( num_verts, start_handle_out, x, y, z );
00334     if( MB_SUCCESS != result ) return result;
00335 
00336     // Read vertex coordinates
00337     for( long vtx = 0; vtx < num_verts; ++vtx )
00338     {
00339         if( !tokens.get_doubles( 1, x++ ) || !tokens.get_doubles( 1, y++ ) || !tokens.get_doubles( 1, z++ ) )
00340             return MB_FAILURE;
00341     }
00342 
00343     return MB_SUCCESS;
00344 }
00345 
00346 ErrorCode ReadVtk::allocate_elements( long num_elements, int vert_per_element, EntityType type,
00347                                       EntityHandle& start_handle_out, EntityHandle*& conn_array_out,
00348                                       std::vector< Range >& append_to_this )
00349 {
00350     ErrorCode result;
00351 
00352     start_handle_out = 0;
00353     result = readMeshIface->get_element_connect( num_elements, vert_per_element, type, MB_START_ID, start_handle_out,
00354                                                  conn_array_out );
00355     if( MB_SUCCESS != result ) return result;
00356 
00357     Range range( start_handle_out, start_handle_out + num_elements - 1 );
00358     append_to_this.push_back( range );
00359     return MB_SUCCESS;
00360 }
00361 
00362 ErrorCode ReadVtk::vtk_read_dataset( FileTokenizer& tokens, Range& vertex_list, std::vector< Range >& element_list )
00363 {
00364     const char* const data_type_names[] = {
00365         "STRUCTURED_POINTS", "STRUCTURED_GRID", "UNSTRUCTURED_GRID", "POLYDATA", "RECTILINEAR_GRID", "FIELD", 0
00366     };
00367     int datatype = tokens.match_token( data_type_names );
00368     switch( datatype )
00369     {
00370         case 1:
00371             return vtk_read_structured_points( tokens, vertex_list, element_list );
00372         case 2:
00373             return vtk_read_structured_grid( tokens, vertex_list, element_list );
00374         case 3:
00375             return vtk_read_unstructured_grid( tokens, vertex_list, element_list );
00376         case 4:
00377             return vtk_read_polydata( tokens, vertex_list, element_list );
00378         case 5:
00379             return vtk_read_rectilinear_grid( tokens, vertex_list, element_list );
00380         case 6:
00381             return vtk_read_field( tokens );
00382         default:
00383             return MB_FAILURE;
00384     }
00385 }
00386 
00387 ErrorCode ReadVtk::vtk_read_structured_points( FileTokenizer& tokens, Range& vertex_list,
00388                                                std::vector< Range >& elem_list )
00389 {
00390     long i, j, k;
00391     long dims[3];
00392     double origin[3], space[3];
00393     ErrorCode result;
00394 
00395     if( !tokens.match_token( "DIMENSIONS" ) || !tokens.get_long_ints( 3, dims ) || !tokens.get_newline() )
00396         return MB_FAILURE;
00397 
00398     if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
00399     {
00400         MB_SET_ERR( MB_FAILURE, "Invalid dimension at line " << tokens.line_number() );
00401     }
00402 
00403     if( !tokens.match_token( "ORIGIN" ) || !tokens.get_doubles( 3, origin ) || !tokens.get_newline() )
00404         return MB_FAILURE;
00405 
00406     const char* const spacing_names[] = { "SPACING", "ASPECT_RATIO", 0 };
00407     if( !tokens.match_token( spacing_names ) || !tokens.get_doubles( 3, space ) || !tokens.get_newline() )
00408         return MB_FAILURE;
00409 
00410     // Create vertices
00411     double *x, *y, *z;
00412     EntityHandle start_handle = 0;
00413     long num_verts            = dims[0] * dims[1] * dims[2];
00414     result                    = allocate_vertices( num_verts, start_handle, x, y, z );
00415     if( MB_SUCCESS != result ) return result;
00416     vertex_list.insert( start_handle, start_handle + num_verts - 1 );
00417 
00418     for( k = 0; k < dims[2]; ++k )
00419         for( j = 0; j < dims[1]; ++j )
00420             for( i = 0; i < dims[0]; ++i )
00421             {
00422                 *x = origin[0] + i * space[0];
00423                 ++x;
00424                 *y = origin[1] + j * space[1];
00425                 ++y;
00426                 *z = origin[2] + k * space[2];
00427                 ++z;
00428             }
00429 
00430     return vtk_create_structured_elems( dims, start_handle, elem_list );
00431 }
00432 
00433 ErrorCode ReadVtk::vtk_read_structured_grid( FileTokenizer& tokens, Range& vertex_list,
00434                                              std::vector< Range >& elem_list )
00435 {
00436     long num_verts, dims[3];
00437     ErrorCode result;
00438 
00439     if( !tokens.match_token( "DIMENSIONS" ) || !tokens.get_long_ints( 3, dims ) || !tokens.get_newline() )
00440         return MB_FAILURE;
00441 
00442     if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
00443     {
00444         MB_SET_ERR( MB_FAILURE, "Invalid dimension at line " << tokens.line_number() );
00445     }
00446 
00447     if( !tokens.match_token( "POINTS" ) || !tokens.get_long_ints( 1, &num_verts ) ||
00448         !tokens.match_token( vtk_type_names ) || !tokens.get_newline() )
00449         return MB_FAILURE;
00450 
00451     if( num_verts != ( dims[0] * dims[1] * dims[2] ) )
00452     {
00453         MB_SET_ERR( MB_FAILURE, "Point count not consistent with dimensions at line " << tokens.line_number() );
00454     }
00455 
00456     // Create and read vertices
00457     EntityHandle start_handle = 0;
00458     result                    = read_vertices( tokens, num_verts, start_handle );
00459     if( MB_SUCCESS != result ) return result;
00460     vertex_list.insert( start_handle, start_handle + num_verts - 1 );
00461 
00462     return vtk_create_structured_elems( dims, start_handle, elem_list );
00463 }
00464 
00465 ErrorCode ReadVtk::vtk_read_rectilinear_grid( FileTokenizer& tokens, Range& vertex_list,
00466                                               std::vector< Range >& elem_list )
00467 {
00468     int i, j, k;
00469     long dims[3];
00470     const char* labels[] = { "X_COORDINATES", "Y_COORDINATES", "Z_COORDINATES" };
00471     std::vector< double > coords[3];
00472     ErrorCode result;
00473 
00474     if( !tokens.match_token( "DIMENSIONS" ) || !tokens.get_long_ints( 3, dims ) || !tokens.get_newline() )
00475         return MB_FAILURE;
00476 
00477     if( dims[0] < 1 || dims[1] < 1 || dims[2] < 1 )
00478     {
00479         MB_SET_ERR( MB_FAILURE, "Invalid dimension at line " << tokens.line_number() );
00480     }
00481 
00482     for( i = 0; i < 3; i++ )
00483     {
00484         long count;
00485         if( !tokens.match_token( labels[i] ) || !tokens.get_long_ints( 1, &count ) ||
00486             !tokens.match_token( vtk_type_names ) )
00487             return MB_FAILURE;
00488 
00489         if( count != dims[i] )
00490         {
00491             MB_SET_ERR( MB_FAILURE, "Coordinate count inconsistent with dimensions at line " << tokens.line_number() );
00492         }
00493 
00494         coords[i].resize( count );
00495         if( !tokens.get_doubles( count, &coords[i][0] ) ) return MB_FAILURE;
00496     }
00497 
00498     // Create vertices
00499     double *x, *y, *z;
00500     EntityHandle start_handle = 0;
00501     long num_verts            = dims[0] * dims[1] * dims[2];
00502     result                    = allocate_vertices( num_verts, start_handle, x, y, z );
00503     if( MB_SUCCESS != result ) return result;
00504     vertex_list.insert( start_handle, start_handle + num_verts - 1 );
00505 
00506     // Calculate vertex coordinates
00507     for( k = 0; k < dims[2]; ++k )
00508         for( j = 0; j < dims[1]; ++j )
00509             for( i = 0; i < dims[0]; ++i )
00510             {
00511                 *x = coords[0][i];
00512                 ++x;
00513                 *y = coords[1][j];
00514                 ++y;
00515                 *z = coords[2][k];
00516                 ++z;
00517             }
00518 
00519     return vtk_create_structured_elems( dims, start_handle, elem_list );
00520 }
00521 
00522 ErrorCode ReadVtk::vtk_read_polydata( FileTokenizer& tokens, Range& vertex_list, std::vector< Range >& elem_list )
00523 {
00524     ErrorCode result;
00525     long num_verts;
00526     const char* const poly_data_names[] = { "VERTICES", "LINES", "POLYGONS", "TRIANGLE_STRIPS", 0 };
00527 
00528     if( !tokens.match_token( "POINTS" ) || !tokens.get_long_ints( 1, &num_verts ) ||
00529         !tokens.match_token( vtk_type_names ) || !tokens.get_newline() )
00530         return MB_FAILURE;
00531 
00532     if( num_verts < 1 ) { MB_SET_ERR( MB_FAILURE, "Invalid point count at line " << tokens.line_number() ); }
00533 
00534     // Create vertices and read coordinates
00535     EntityHandle start_handle = 0;
00536     result                    = read_vertices( tokens, num_verts, start_handle );
00537     if( MB_SUCCESS != result ) return result;
00538     vertex_list.insert( start_handle, start_handle + num_verts - 1 );
00539 
00540     int poly_type = tokens.match_token( poly_data_names );
00541     switch( poly_type )
00542     {
00543         case 0:
00544             result = MB_FAILURE;
00545             break;
00546         case 1:
00547             MB_SET_ERR( MB_FAILURE, "Vertex element type at line " << tokens.line_number() );
00548             break;
00549         case 2:
00550             MB_SET_ERR( MB_FAILURE, "Unsupported type: polylines at line " << tokens.line_number() );
00551             result = MB_FAILURE;
00552             break;
00553         case 3:
00554             result = vtk_read_polygons( tokens, start_handle, elem_list );
00555             break;
00556         case 4:
00557             MB_SET_ERR( MB_FAILURE, "Unsupported type: triangle strips at line " << tokens.line_number() );
00558             result = MB_FAILURE;
00559             break;
00560     }
00561 
00562     return result;
00563 }
00564 
00565 ErrorCode ReadVtk::vtk_read_polygons( FileTokenizer& tokens, EntityHandle first_vtx, std::vector< Range >& elem_list )
00566 {
00567     ErrorCode result;
00568     long size[2];
00569 
00570     if( !tokens.get_long_ints( 2, size ) || !tokens.get_newline() ) return MB_FAILURE;
00571 
00572     const Range empty;
00573     std::vector< EntityHandle > conn_hdl;
00574     std::vector< long > conn_idx;
00575     EntityHandle first = 0, prev = 0, handle;
00576     for( int i = 0; i < size[0]; ++i )
00577     {
00578         long count;
00579         if( !tokens.get_long_ints( 1, &count ) ) return MB_FAILURE;
00580         conn_idx.resize( count );
00581         conn_hdl.resize( count );
00582         if( !tokens.get_long_ints( count, &conn_idx[0] ) ) return MB_FAILURE;
00583 
00584         for( long j = 0; j < count; ++j )
00585             conn_hdl[j] = first_vtx + conn_idx[j];
00586 
00587         result = mdbImpl->create_element( MBPOLYGON, &conn_hdl[0], count, handle );
00588         if( MB_SUCCESS != result ) return result;
00589 
00590         if( prev + 1 != handle )
00591         {
00592             if( first )
00593             {  // True except for first iteration (first == 0)
00594                 if( elem_list.empty() || first < elem_list.back().front() )  // Only need new range if order would get
00595                                                                              // mixed up, or we just began inserting
00596                     elem_list.push_back( empty );
00597                 elem_list.back().insert( first, prev );
00598             }
00599             first = handle;
00600         }
00601         prev = handle;
00602     }
00603     if( first )
00604     {                                                                // True unless no elements (size[0] == 0)
00605         if( elem_list.empty() || first < elem_list.back().front() )  // Only need new range if order would get mixed
00606                                                                      // up, or we just began inserting
00607             elem_list.push_back( empty );
00608         elem_list.back().insert( first, prev );
00609     }
00610 
00611     return MB_SUCCESS;
00612 }
00613 
00614 ErrorCode ReadVtk::vtk_read_unstructured_grid( FileTokenizer& tokens, Range& vertex_list,
00615                                                std::vector< Range >& elem_list )
00616 {
00617     ErrorCode result;
00618     long i, num_verts, num_elems[2];
00619     EntityHandle tmp_conn_list[27];
00620 
00621     // Poorly formatted VTK legacy format document seems to
00622     // lead many to think that a FIELD block can occur within
00623     // an UNSTRUCTURED_GRID dataset rather than as its own data
00624     // set. So allow for field data between other blocks of
00625     // data.
00626 
00627     const char* pts_str[] = { "FIELD", "POINTS", 0 };
00628     while( 1 == ( i = tokens.match_token( pts_str ) ) )
00629     {
00630         result = vtk_read_field( tokens );
00631         if( MB_SUCCESS != result ) return result;
00632     }
00633     if( i != 2 ) return MB_FAILURE;
00634 
00635     if( !tokens.get_long_ints( 1, &num_verts ) || !tokens.match_token( vtk_type_names ) || !tokens.get_newline() )
00636         return MB_FAILURE;
00637 
00638     if( num_verts < 1 ) { MB_SET_ERR( MB_FAILURE, "Invalid point count at line " << tokens.line_number() ); }
00639 
00640     // Create vertices and read coordinates
00641     EntityHandle first_vertex = 0;
00642     result                    = read_vertices( tokens, num_verts, first_vertex );
00643     if( MB_SUCCESS != result ) return result;
00644     vertex_list.insert( first_vertex, first_vertex + num_verts - 1 );
00645 
00646     const char* cell_str[] = { "FIELD", "CELLS", 0 };
00647     while( 1 == ( i = tokens.match_token( cell_str ) ) )
00648     {
00649         result = vtk_read_field( tokens );
00650         if( MB_SUCCESS != result ) return result;
00651     }
00652     if( i != 2 ) return MB_FAILURE;
00653 
00654     if( !tokens.get_long_ints( 2, num_elems ) || !tokens.get_newline() ) return MB_FAILURE;
00655 
00656     // Read element connectivity for all elements
00657     std::vector< long > connectivity( num_elems[1] );
00658     if( !tokens.get_long_ints( num_elems[1], &connectivity[0] ) ) return MB_FAILURE;
00659 
00660     if( !tokens.match_token( "CELL_TYPES" ) || !tokens.get_long_ints( 1, &num_elems[1] ) || !tokens.get_newline() )
00661         return MB_FAILURE;
00662 
00663     // Read element types
00664     std::vector< long > types( num_elems[0] );
00665     if( !tokens.get_long_ints( num_elems[0], &types[0] ) ) return MB_FAILURE;
00666 
00667     // Create elements in blocks of the same type
00668     // It is important to preserve the order in
00669     // which the elements were read for later reading
00670     // attribute data.
00671     long id                                 = 0;
00672     std::vector< long >::iterator conn_iter = connectivity.begin();
00673     while( id < num_elems[0] )
00674     {
00675         unsigned vtk_type = types[id];
00676         if( vtk_type >= VtkUtil::numVtkElemType ) return MB_FAILURE;
00677 
00678         EntityType type = VtkUtil::vtkElemTypes[vtk_type].mb_type;
00679         if( type == MBMAXTYPE )
00680         {
00681             MB_SET_ERR( MB_FAILURE, "Unsupported VTK element type: " << VtkUtil::vtkElemTypes[vtk_type].name << " ("
00682                                                                      << vtk_type << ")" );
00683         }
00684 
00685         int num_vtx = *conn_iter;
00686         if( type != MBPOLYGON && type != MBPOLYHEDRON && num_vtx != (int)VtkUtil::vtkElemTypes[vtk_type].num_nodes )
00687         {
00688             MB_SET_ERR( MB_FAILURE, "Cell " << id << " is of type '" << VtkUtil::vtkElemTypes[vtk_type].name
00689                                             << "' but has " << num_vtx << " vertices" );
00690         }
00691 
00692         // Find any subsequent elements of the same type
00693         // if polyhedra, need to look at the number of faces to put in the same range
00694         std::vector< long >::iterator conn_iter2 = conn_iter + num_vtx + 1;
00695         long end_id                              = id + 1;
00696         if( MBPOLYHEDRON != type )
00697         {
00698             while( end_id < num_elems[0] && (unsigned)types[end_id] == vtk_type && *conn_iter2 == num_vtx )
00699             {
00700                 ++end_id;
00701                 conn_iter2 += num_vtx + 1;
00702             }
00703         }
00704         else
00705         {
00706             // advance only if next is polyhedron too, and if number of faces is the same
00707             int num_faces = conn_iter[1];
00708             while( end_id < num_elems[0] && (unsigned)types[end_id] == vtk_type && conn_iter2[1] == num_faces )
00709             {
00710                 ++end_id;
00711                 conn_iter2 += num_vtx + 1;
00712             }
00713             // num_vtx becomes in this case num_faces
00714             num_vtx = num_faces;  // for polyhedra, this is what we want
00715             // trigger vertex adjacency call
00716             Range firstFaces;
00717             mdbImpl->get_adjacencies( &first_vertex, 1, 2, false, firstFaces );
00718         }
00719 
00720         // Allocate element block
00721         long num_elem             = end_id - id;
00722         EntityHandle start_handle = 0;
00723         EntityHandle* conn_array;
00724 
00725         // if type is MBVERTEX, skip, we will not create elements with one vertex
00726         if( MBVERTEX == type )
00727         {
00728             id += num_elem;
00729             conn_iter += 2 * num_elem;  // skip 2 * number of 1-vertex elements
00730             continue;
00731         }
00732 
00733         result = allocate_elements( num_elem, num_vtx, type, start_handle, conn_array, elem_list );
00734         if( MB_SUCCESS != result ) return result;
00735 
00736         EntityHandle* conn_sav = conn_array;
00737 
00738         // Store element connectivity
00739         if( type != MBPOLYHEDRON )
00740         {
00741             for( ; id < end_id; ++id )
00742             {
00743                 if( conn_iter == connectivity.end() )
00744                 {
00745                     MB_SET_ERR( MB_FAILURE, "Connectivity data truncated at cell " << id );
00746                 }
00747                 // Make sure connectivity length is correct.
00748                 if( *conn_iter != num_vtx )
00749                 {
00750                     MB_SET_ERR( MB_FAILURE, "Cell " << id << " is of type '" << VtkUtil::vtkElemTypes[vtk_type].name
00751                                                     << "' but has " << num_vtx << " vertices" );
00752                 }
00753                 ++conn_iter;
00754 
00755                 for( i = 0; i < num_vtx; ++i, ++conn_iter )
00756                 {
00757                     if( conn_iter == connectivity.end() )
00758                     {
00759                         MB_SET_ERR( MB_FAILURE, "Connectivity data truncated at cell " << id );
00760                     }
00761 
00762                     conn_array[i] = *conn_iter + first_vertex;
00763                 }
00764 
00765                 const unsigned* order = VtkUtil::vtkElemTypes[vtk_type].node_order;
00766                 if( order )
00767                 {
00768                     assert( num_vtx * sizeof( EntityHandle ) <= sizeof( tmp_conn_list ) );
00769                     memcpy( tmp_conn_list, conn_array, num_vtx * sizeof( EntityHandle ) );
00770                     for( int j = 0; j < num_vtx; ++j )
00771                         conn_array[order[j]] = tmp_conn_list[j];
00772                 }
00773 
00774                 conn_array += num_vtx;
00775             }
00776         }
00777         else  // type == MBPOLYHEDRON
00778         {
00779             // in some cases, we may need to create new elements; will it screw the tags?
00780             // not if the file was not from moab
00781             ErrorCode rv = MB_SUCCESS;
00782             for( ; id < end_id; ++id )
00783             {
00784                 if( conn_iter == connectivity.end() )
00785                 {
00786                     MB_SET_ERR( MB_FAILURE, "Connectivity data truncated at polyhedra cell " << id );
00787                 }
00788                 ++conn_iter;
00789                 // iterator is now at number of faces
00790                 // we should check it is indeed num_vtx
00791                 int num_faces = *conn_iter;
00792                 if( num_faces != num_vtx ) MB_SET_ERR( MB_FAILURE, "Connectivity data wrong at polyhedra cell " << id );
00793 
00794                 EntityHandle connec[20];  // we bet we will have only 20 vertices at most, in a
00795                                           // face in a polyhedra
00796                 for( int j = 0; j < num_faces; j++ )
00797                 {
00798                     conn_iter++;
00799                     int numverticesInFace = (int)*conn_iter;
00800                     if( numverticesInFace > 20 )
00801                         MB_SET_ERR( MB_FAILURE,
00802                                     "too many vertices in face index " << j << " for polyhedra cell " << id );
00803                     // need to find the face, but first fill with vertices
00804                     for( int k = 0; k < numverticesInFace; k++ )
00805                     {
00806                         connec[k] = first_vertex + *( ++conn_iter );  //
00807                     }
00808                     Range adjFaces;
00809                     // find a face with these vertices; if not, we need to create one, on the fly :(
00810                     rv = mdbImpl->get_adjacencies( connec, numverticesInFace, 2, false, adjFaces );MB_CHK_ERR( rv );
00811                     if( adjFaces.size() >= 1 )
00812                     {
00813                         conn_array[j] = adjFaces[0];  // get the first face found
00814                     }
00815                     else
00816                     {
00817                         // create the face; tri, quad or polygon
00818                         EntityType etype = MBTRI;
00819                         if( 4 == numverticesInFace ) etype = MBQUAD;
00820                         if( 4 < numverticesInFace ) etype = MBPOLYGON;
00821 
00822                         rv = mdbImpl->create_element( etype, connec, numverticesInFace, conn_array[j] );MB_CHK_ERR( rv );
00823                     }
00824                 }
00825 
00826                 conn_array += num_vtx;  // advance for next polyhedra
00827                 conn_iter++;            // advance to the next field
00828             }
00829         }
00830 
00831         // Notify MOAB of the new elements
00832         result = readMeshIface->update_adjacencies( start_handle, num_elem, num_vtx, conn_sav );
00833         if( MB_SUCCESS != result ) return result;
00834     }
00835 
00836     return MB_SUCCESS;
00837 }
00838 
00839 ErrorCode ReadVtk::vtk_create_structured_elems( const long* dims, EntityHandle first_vtx,
00840                                                 std::vector< Range >& elem_list )
00841 {
00842     ErrorCode result;
00843     // int non_zero[3] = {0, 0, 0}; // True if dim > 0 for x, y, z respectively
00844     long elem_dim  = 0;           // Element dimension (2->quad, 3->hex)
00845     long num_elems = 1;           // Total number of elements
00846     long vert_per_elem;           // Element connectivity length
00847     long edims[3] = { 1, 1, 1 };  // Number of elements in each grid direction
00848 
00849     // Populate above data
00850     for( int d = 0; d < 3; d++ )
00851     {
00852         if( dims[d] > 1 )
00853         {
00854             // non_zero[elem_dim] = d;
00855             ++elem_dim;
00856             edims[d] = dims[d] - 1;
00857             num_elems *= edims[d];
00858         }
00859     }
00860     vert_per_elem = 1 << elem_dim;
00861 
00862     // Get element type from element dimension
00863     EntityType type;
00864     switch( elem_dim )
00865     {
00866         case 1:
00867             type = MBEDGE;
00868             break;
00869         case 2:
00870             type = MBQUAD;
00871             break;
00872         case 3:
00873             type = MBHEX;
00874             break;
00875         default:
00876             MB_SET_ERR( MB_FAILURE, "Invalid dimension for structured elements: " << elem_dim );
00877     }
00878 
00879     // Allocate storage for elements
00880     EntityHandle start_handle = 0;
00881     EntityHandle* conn_array;
00882     result = allocate_elements( num_elems, vert_per_elem, type, start_handle, conn_array, elem_list );
00883     if( MB_SUCCESS != result ) return MB_FAILURE;
00884 
00885     EntityHandle* conn_sav = conn_array;
00886 
00887     // Offsets of element vertices in grid relative to corner closest to origin
00888     long k                = dims[0] * dims[1];
00889     const long corners[8] = { 0, 1, 1 + dims[0], dims[0], k, k + 1, k + 1 + dims[0], k + dims[0] };
00890 
00891     // Populate element list
00892     for( long z = 0; z < edims[2]; ++z )
00893         for( long y = 0; y < edims[1]; ++y )
00894             for( long x = 0; x < edims[0]; ++x )
00895             {
00896                 const long index = x + y * dims[0] + z * ( dims[0] * dims[1] );
00897                 for( long j = 0; j < vert_per_elem; ++j, ++conn_array )
00898                     *conn_array = index + corners[j] + first_vtx;
00899             }
00900 
00901     // Notify MOAB of the new elements
00902     result = readMeshIface->update_adjacencies( start_handle, num_elems, vert_per_elem, conn_sav );
00903     if( MB_SUCCESS != result ) return result;
00904 
00905     return MB_SUCCESS;
00906 }
00907 
00908 ErrorCode ReadVtk::vtk_read_field( FileTokenizer& tokens )
00909 {
00910     // This is not supported yet.
00911     // Parse the data but throw it away because
00912     // Mesquite has no internal representation for it.
00913 
00914     // Could save this in tags, but the only useful thing that
00915     // could be done with the data is to write it back out
00916     // with the modified mesh. As there's no way to save the
00917     // type of a tag in Mesquite, it cannot be written back
00918     // out correctly either.
00919     // FIXME: Don't know what to do with this data.
00920     // For now, read it and throw it out.
00921 
00922     long num_arrays;
00923     if( !tokens.get_string() ||  // Name
00924         !tokens.get_long_ints( 1, &num_arrays ) )
00925         return MB_FAILURE;
00926 
00927     for( long i = 0; i < num_arrays; ++i )
00928     {
00929         /*const char* name =*/tokens.get_string();
00930 
00931         long dims[2];
00932         if( !tokens.get_long_ints( 2, dims ) || !tokens.match_token( vtk_type_names ) ) return MB_FAILURE;
00933 
00934         long num_vals = dims[0] * dims[1];
00935 
00936         for( long j = 0; j < num_vals; j++ )
00937         {
00938             double junk;
00939             if( !tokens.get_doubles( 1, &junk ) ) return MB_FAILURE;
00940         }
00941     }
00942 
00943     return MB_SUCCESS;
00944 }
00945 
00946 ErrorCode ReadVtk::vtk_read_attrib_data( FileTokenizer& tokens, std::vector< Range >& entities )
00947 {
00948     const char* const type_names[] = { "SCALARS", "COLOR_SCALARS", "VECTORS", "NORMALS", "TEXTURE_COORDINATES",
00949                                        "TENSORS", "FIELD",         0 };
00950 
00951     int type             = tokens.match_token( type_names );
00952     const char* tmp_name = tokens.get_string();
00953     if( !type || !tmp_name ) return MB_FAILURE;
00954 
00955     std::string name_alloc( tmp_name );
00956     const char* name = name_alloc.c_str();
00957     switch( type )
00958     {
00959         case 1:
00960             return vtk_read_scalar_attrib( tokens, entities, name );
00961         case 2:
00962             return vtk_read_color_attrib( tokens, entities, name );
00963         case 3:
00964             return vtk_read_vector_attrib( tokens, entities, name );
00965         case 4:
00966             return vtk_read_vector_attrib( tokens, entities, name );
00967         case 5:
00968             return vtk_read_texture_attrib( tokens, entities, name );
00969         case 6:
00970             return vtk_read_tensor_attrib( tokens, entities, name );
00971         case 7:
00972             return vtk_read_field_attrib( tokens, entities, name );
00973     }
00974 
00975     return MB_FAILURE;
00976 }
00977 
00978 ErrorCode ReadVtk::vtk_read_tag_data( FileTokenizer& tokens, int type, size_t per_elem, std::vector< Range >& entities,
00979                                       const char* name )
00980 {
00981     ErrorCode result;
00982     DataType mb_type;
00983     if( type == 1 ) { mb_type = MB_TYPE_BIT; }
00984     else if( type >= 2 && type <= 9 )
00985     {
00986         mb_type = MB_TYPE_INTEGER;
00987     }
00988     else if( type == 10 || type == 11 )
00989     {
00990         mb_type = MB_TYPE_DOUBLE;
00991     }
00992     else if( type == 12 )
00993     {
00994         mb_type = MB_TYPE_INTEGER;
00995     }
00996     else
00997         return MB_FAILURE;
00998 
00999 #ifdef MB_VTK_MATERIAL_SETS
01000     size_t size;
01001     if( type == 1 ) { size = sizeof( bool ); }
01002     else if( type >= 2 && type <= 9 )
01003     {
01004         size = sizeof( int );
01005     }
01006     else if( type == 10 || type == 11 )
01007     {
01008         size = sizeof( double );
01009     }
01010     else /* (type == 12) */
01011     {
01012         size = 4;  // Could be 4 or 8, but we don't know. Hope it's 4 because MOAB doesn't support
01013                    // 64-bit ints.
01014     }
01015     Modulator materialMap( this->mdbImpl );
01016     result = materialMap.initialize( this->mPartitionTagName, mb_type, size, per_elem );MB_CHK_SET_ERR( result, "MaterialMap tag (" << this->mPartitionTagName << ") creation failed." );
01017     bool isMaterial = size * per_elem <= 4 &&              // Must have int-sized values (ParallelComm requires it)
01018                       !this->mPartitionTagName.empty() &&  // Must have a non-empty field name...
01019                       !strcmp( name, this->mPartitionTagName.c_str() );  // ... that matches our spec.
01020 #endif                                                                   // MB_VTK_MATERIAL_SETS
01021 
01022     // Get/create tag
01023     Tag handle;
01024     result = mdbImpl->tag_get_handle( name, per_elem, mb_type, handle, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_SET_ERR( result, "Tag name conflict for attribute \"" << name << "\" at line " << tokens.line_number() );
01025 
01026     std::vector< Range >::iterator iter;
01027 
01028     if( type == 1 )
01029     {
01030         for( iter = entities.begin(); iter != entities.end(); ++iter )
01031         {
01032             bool* data = new bool[iter->size() * per_elem];
01033             if( !tokens.get_booleans( per_elem * iter->size(), data ) )
01034             {
01035                 delete[] data;
01036                 return MB_FAILURE;
01037             }
01038 
01039             bool* data_iter          = data;
01040             Range::iterator ent_iter = iter->begin();
01041             for( ; ent_iter != iter->end(); ++ent_iter )
01042             {
01043                 unsigned char bits = 0;
01044                 for( unsigned j = 0; j < per_elem; ++j, ++data_iter )
01045                     bits |= (unsigned char)( *data_iter << j );
01046 #ifdef MB_VTK_MATERIAL_SETS
01047                 if( isMaterial ) materialMap.add_entity( *ent_iter, &bits, 1 );
01048 #endif  // MB_VTK_MATERIAL_SETS
01049                 result = mdbImpl->tag_set_data( handle, &*ent_iter, 1, &bits );
01050                 if( MB_SUCCESS != result )
01051                 {
01052                     delete[] data;
01053                     return result;
01054                 }
01055             }
01056             delete[] data;
01057         }
01058     }
01059     else if( ( type >= 2 && type <= 9 ) || type == 12 )
01060     {
01061         std::vector< int > data;
01062         for( iter = entities.begin(); iter != entities.end(); ++iter )
01063         {
01064             data.resize( iter->size() * per_elem );
01065             if( !tokens.get_integers( iter->size() * per_elem, &data[0] ) ) return MB_FAILURE;
01066 #ifdef MB_VTK_MATERIAL_SETS
01067             if( isMaterial ) materialMap.add_entities( *iter, (unsigned char*)&data[0], per_elem * size );
01068 #endif  // MB_VTK_MATERIAL_SETS
01069             result = mdbImpl->tag_set_data( handle, *iter, &data[0] );
01070             if( MB_SUCCESS != result ) return result;
01071         }
01072     }
01073     else if( type == 10 || type == 11 )
01074     {
01075         std::vector< double > data;
01076         for( iter = entities.begin(); iter != entities.end(); ++iter )
01077         {
01078             data.resize( iter->size() * per_elem );
01079             if( !tokens.get_doubles( iter->size() * per_elem, &data[0] ) ) return MB_FAILURE;
01080 #ifdef MB_VTK_MATERIAL_SETS
01081             if( isMaterial ) materialMap.add_entities( *iter, (unsigned char*)&data[0], per_elem * size );
01082 #endif  // MB_VTK_MATERIAL_SETS
01083             result = mdbImpl->tag_set_data( handle, *iter, &data[0] );
01084             if( MB_SUCCESS != result ) return result;
01085         }
01086     }
01087 
01088     return MB_SUCCESS;
01089 }
01090 
01091 ErrorCode ReadVtk::vtk_read_scalar_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
01092 {
01093     int type = tokens.match_token( vtk_type_names );
01094     if( !type ) return MB_FAILURE;
01095 
01096     long size;
01097     const char* tok = tokens.get_string();
01098     if( !tok ) return MB_FAILURE;
01099 
01100     const char* end = 0;
01101     size            = strtol( tok, (char**)&end, 0 );
01102     if( *end )
01103     {
01104         size = 1;
01105         tokens.unget_token();
01106     }
01107 
01108     // VTK spec says cannot be greater than 4--do we care?
01109     if( size < 1 )
01110     {  //|| size > 4)
01111         MB_SET_ERR( MB_FAILURE, "Scalar count out of range [1,4] at line " << tokens.line_number() );
01112     }
01113 
01114     if( !tokens.match_token( "LOOKUP_TABLE" ) || !tokens.match_token( "default" ) ) return MB_FAILURE;
01115 
01116     return vtk_read_tag_data( tokens, type, size, entities, name );
01117 }
01118 
01119 ErrorCode ReadVtk::vtk_read_color_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
01120 {
01121     long size;
01122     if( !tokens.get_long_ints( 1, &size ) || size < 1 ) return MB_FAILURE;
01123 
01124     return vtk_read_tag_data( tokens, 10, size, entities, name );
01125 }
01126 
01127 ErrorCode ReadVtk::vtk_read_vector_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
01128 {
01129     int type = tokens.match_token( vtk_type_names );
01130     if( !type ) return MB_FAILURE;
01131 
01132     return vtk_read_tag_data( tokens, type, 3, entities, name );
01133 }
01134 
01135 ErrorCode ReadVtk::vtk_read_texture_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
01136 {
01137     int type, dim;
01138     if( !tokens.get_integers( 1, &dim ) || !( type = tokens.match_token( vtk_type_names ) ) ) return MB_FAILURE;
01139 
01140     if( dim < 1 || dim > 3 )
01141     {
01142         MB_SET_ERR( MB_FAILURE, "Invalid dimension (" << dim << ") at line " << tokens.line_number() );
01143     }
01144 
01145     return vtk_read_tag_data( tokens, type, dim, entities, name );
01146 }
01147 
01148 ErrorCode ReadVtk::vtk_read_tensor_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* name )
01149 {
01150     int type = tokens.match_token( vtk_type_names );
01151     if( !type ) return MB_FAILURE;
01152 
01153     return vtk_read_tag_data( tokens, type, 9, entities, name );
01154 }
01155 
01156 ErrorCode ReadVtk::vtk_read_field_attrib( FileTokenizer& tokens, std::vector< Range >& entities, const char* )
01157 {
01158     long num_fields;
01159     if( !tokens.get_long_ints( 1, &num_fields ) ) return MB_FAILURE;
01160 
01161     long i;
01162     for( i = 0; i < num_fields; ++i )
01163     {
01164         const char* tok = tokens.get_string();
01165         if( !tok ) return MB_FAILURE;
01166 
01167         std::string name_alloc( tok );
01168 
01169         long num_comp;
01170         if( !tokens.get_long_ints( 1, &num_comp ) ) return MB_FAILURE;
01171 
01172         long num_tuples;
01173         if( !tokens.get_long_ints( 1, &num_tuples ) ) return MB_FAILURE;
01174 
01175         int type = tokens.match_token( vtk_type_names );
01176         if( !type ) return MB_FAILURE;
01177 
01178         ErrorCode result = vtk_read_tag_data( tokens, type, num_comp, entities, name_alloc.c_str() );MB_CHK_SET_ERR( result, "Error reading data for field \"" << name_alloc << "\" (" << num_comp << " components, "
01179                                                                   << num_tuples << " tuples, type " << type
01180                                                                   << ") at line " << tokens.line_number() );
01181     }
01182 
01183     return MB_SUCCESS;
01184 }
01185 
01186 ErrorCode ReadVtk::store_file_ids( Tag tag, const Range& verts, const std::vector< Range >& elems )
01187 {
01188     ErrorCode rval;
01189 
01190     rval = readMeshIface->assign_ids( tag, verts );
01191     if( MB_SUCCESS != rval ) return rval;
01192 
01193     int id = 0;
01194     for( size_t i = 0; i < elems.size(); ++i )
01195     {
01196         rval = readMeshIface->assign_ids( tag, elems[i], id );
01197         id += elems[i].size();
01198     }
01199 
01200     return MB_SUCCESS;
01201 }
01202 
01203 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines