MOAB: Mesh Oriented datABase  (version 5.3.0)
WriteUtil.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 #ifdef WIN32
00017 #pragma warning( disable : 4786 )
00018 #endif
00019 
00020 #include "WriteUtil.hpp"
00021 #include "moab/Core.hpp"
00022 #include "moab/Error.hpp"
00023 #include "SequenceManager.hpp"
00024 #include "ElementSequence.hpp"
00025 #include "VertexSequence.hpp"
00026 #include "AEntityFactory.hpp"
00027 #include "MBTagConventions.hpp"
00028 #include "RangeSeqIntersectIter.hpp"
00029 #include "MeshSetSequence.hpp"
00030 
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <cerrno>
00034 #include <cassert>
00035 #include <iostream>
00036 
00037 #ifdef WIN32
00038 #define stat _stat
00039 #else
00040 #include <unistd.h>
00041 #endif
00042 
00043 namespace moab
00044 {
00045 
00046 WriteUtil::WriteUtil( Core* mdb ) : WriteUtilIface(), mMB( mdb ) {}
00047 
00048 //! Check if the specified file already exists.
00049 //! Returns MB_SUCCESS if file does not exist, MB_ALREADY_ALLOCATED
00050 //! if file does exist, or MB_FAILURE for some other error condition.
00051 ErrorCode WriteUtil::check_doesnt_exist( const char* file_name )
00052 {
00053     struct stat s;
00054     if( 0 == stat( file_name, &s ) ) { MB_SET_ERR( MB_ALREADY_ALLOCATED, file_name << ": file already exists" ); }
00055     else if( errno == ENOENT )
00056         return MB_SUCCESS;
00057     else
00058         return MB_FAILURE;
00059 }
00060 
00061 //! Gather all entities in the mesh, or in the sets specified
00062 ErrorCode WriteUtil::gather_entities( Range& all_ents,
00063                                       /**< range in which entities are returned */
00064                                       const EntityHandle* ent_sets,
00065                                       /**< entity sets whose contents are to be gathered */
00066                                       const int num_sets
00067                                       /**< number of sets in list */
00068 )
00069 {
00070     ErrorCode rval = MB_SUCCESS;
00071     if( !ent_sets || num_sets == 0 ) { rval = mMB->get_entities_by_handle( 0, all_ents ); }
00072     else
00073     {
00074         for( int i = 0; i < num_sets; i++ )
00075         {
00076             ErrorCode tmp_rval = mMB->get_entities_by_handle( ent_sets[i], all_ents );
00077             if( MB_SUCCESS != tmp_rval ) rval = tmp_rval;
00078         }
00079     }
00080 
00081     return rval;
00082 }
00083 
00084 ErrorCode WriteUtil::get_node_coords( const int num_arrays, const int num_nodes, const Range& entities, Tag node_id_tag,
00085                                       const int start_node_id, std::vector< double* >& arrays )
00086 {
00087     // Check the data coming into the function
00088     // Dimension should be proper
00089     if( num_arrays < 1 || num_arrays > 3 ) return MB_FAILURE;
00090 
00091     // There should be some entities
00092     // if (entities.empty())
00093     //  return MB_FAILURE;
00094     // The above necessitates annoying special cases for files
00095     // w/out vertices (e.g. a kD-tree).  Return NULL array
00096     // pointers instead. - kraftcheck, 3-14-08
00097     if( entities.empty() )
00098     {
00099         arrays.clear();
00100         arrays.resize( num_arrays, NULL );
00101         return MB_SUCCESS;
00102     }
00103 
00104     // Memory should already be allocated for us
00105     int tmp_num_arrays = 0;
00106     for( unsigned int i = 0; i < 3; i++ )
00107         if( i + 1 <= arrays.size() && NULL != arrays[i] ) tmp_num_arrays++;
00108     if( 0 == tmp_num_arrays ) return MB_FAILURE;
00109 
00110     // Get coordinate data
00111     ErrorCode result = mMB->get_coords( entities, num_arrays < 1 || arrays.size() < 1 ? NULL : arrays[0],
00112                                         num_arrays < 2 || arrays.size() < 2 ? NULL : arrays[1],
00113                                         num_arrays < 3 || arrays.size() < 3 ? NULL : arrays[2] );
00114 
00115     if( 0 == node_id_tag || MB_SUCCESS != result ) return result;
00116 
00117     // Now assign tags
00118     std::vector< int > ids( num_nodes );
00119     int node_id = start_node_id;
00120     for( int i = 0; i < num_nodes; i++ )
00121         ids[i] = node_id++;
00122     result = mMB->tag_set_data( node_id_tag, entities, &ids[0] );
00123 
00124     return result;
00125 }
00126 
00127 ErrorCode WriteUtil::get_node_coords( const int which_array, /* 0->X, 1->Y, 2->Z, -1->all */
00128                                       Range::const_iterator iter, const Range::const_iterator& end,
00129                                       const size_t output_array_len, double* const output_array )
00130 {
00131     // Check the data coming into the function
00132     // Dimension should be proper
00133     if( which_array < -1 || which_array > 2 ) return MB_FAILURE;
00134 
00135     // There should be some entities
00136     if( iter == end ) return MB_FAILURE;
00137 
00138     // Memory should already be allocated for us
00139     if( NULL == output_array || 0 == output_array_len ) return MB_FAILURE;
00140 
00141     // Sequence iterators
00142     TypeSequenceManager::iterator seq_iter, seq_end;
00143     seq_iter = mMB->sequence_manager()->entity_map( MBVERTEX ).begin();
00144     seq_end  = mMB->sequence_manager()->entity_map( MBVERTEX ).end();
00145 
00146     // Loop over range, getting coordinate value
00147     double* output_iter      = output_array;
00148     double* const output_end = output_array + output_array_len;
00149     while( iter != end )
00150     {
00151         // Find the sequence containing the current handle
00152         while( seq_iter != seq_end && ( *seq_iter )->end_handle() < *iter )
00153             ++seq_iter;
00154         if( seq_iter == seq_end || *iter < ( *seq_iter )->start_handle() ) return MB_FAILURE;
00155 
00156         // Determine how much of the sequence we want.
00157         Range::pair_iterator pair( iter );
00158         Range::const_iterator prev( end );
00159         --prev;
00160         EntityHandle range_end    = pair->second;
00161         EntityHandle sequence_end = ( *seq_iter )->end_handle();
00162         EntityHandle end_handle   = range_end > sequence_end ? sequence_end : range_end;
00163         if( end_handle > *prev ) end_handle = *prev;
00164         EntityHandle count = end_handle - *iter + 1;
00165 
00166         // Get offset in sequence to start at
00167         assert( *iter >= ( *seq_iter )->start_handle() );
00168         EntityHandle offset = *iter - ( *seq_iter )->start_handle();
00169 
00170         // Get coordinate arrays from sequence
00171         double* coord_array[3];
00172         static_cast< VertexSequence* >( *seq_iter )
00173             ->get_coordinate_arrays( coord_array[0], coord_array[1], coord_array[2] );
00174 
00175         // Copy data to output buffer
00176         if( -1 != which_array )
00177         {
00178             if( output_iter + count > output_end ) return MB_FAILURE;
00179             memcpy( output_iter, coord_array[which_array] + offset, count * sizeof( double ) );
00180             output_iter += count;
00181         }
00182         else
00183         {
00184             if( output_iter + 3 * count > output_end ) return MB_FAILURE;
00185             for( unsigned int i = 0; i < count; i++ )
00186             {
00187                 *output_iter = coord_array[0][i + offset];
00188                 output_iter++;
00189                 *output_iter = coord_array[1][i + offset];
00190                 output_iter++;
00191                 *output_iter = coord_array[2][i + offset];
00192                 output_iter++;
00193             }
00194         }
00195 
00196         // Iterate
00197         iter += count;
00198     }
00199 
00200     return MB_SUCCESS;
00201 }
00202 
00203 ErrorCode WriteUtil::get_element_connect( const int num_elements, const int verts_per_element, Tag node_id_tag,
00204                                           const Range& elements, Tag element_id_tag, int start_element_id,
00205                                           int* element_array, bool add_sizes )
00206 {
00207     // Check the data we got
00208     if( num_elements < 1 ) return MB_FAILURE;
00209     if( verts_per_element < 1 ) return MB_FAILURE;
00210     if( elements.empty() ) return MB_FAILURE;
00211     if( !element_array ) return MB_FAILURE;
00212 
00213     Range::const_iterator range_iter     = elements.begin();
00214     Range::const_iterator range_iter_end = elements.end();
00215 
00216     TypeSequenceManager::iterator seq_iter, seq_iter_end;
00217     EntityType current_type = TYPE_FROM_HANDLE( *range_iter );
00218 
00219     seq_iter     = mMB->sequence_manager()->entity_map( current_type ).begin();
00220     seq_iter_end = mMB->sequence_manager()->entity_map( current_type ).end();
00221 
00222     // Let's find the entity sequence which holds the first entity
00223     TypeSequenceManager::iterator seq_iter_lookahead = seq_iter;
00224     ++seq_iter_lookahead;
00225     for( ; seq_iter_lookahead != seq_iter_end && ( *seq_iter_lookahead )->start_handle() < *range_iter; )
00226     {
00227         ++seq_iter;
00228         ++seq_iter_lookahead;
00229     }
00230 
00231     // A look ahead iterator
00232     Range::const_iterator range_iter_lookahead = range_iter;
00233 
00234     // Our main loop
00235     for( ; range_iter != range_iter_end && seq_iter != seq_iter_end; /* ++ is handled in loop*/ )
00236     {
00237         // Find a range that fits in the current entity sequence
00238         for( ; range_iter_lookahead != range_iter_end && *range_iter_lookahead <= ( *seq_iter )->end_handle();
00239              ++range_iter_lookahead )
00240         {
00241         }
00242 
00243         if( current_type != TYPE_FROM_HANDLE( *range_iter ) )
00244         {
00245             current_type = TYPE_FROM_HANDLE( *range_iter );
00246             seq_iter     = mMB->sequence_manager()->entity_map( current_type ).begin();
00247             seq_iter_end = mMB->sequence_manager()->entity_map( current_type ).end();
00248 
00249             // Let's find the entity sequence which holds the first entity of this type
00250             TypeSequenceManager::const_iterator seq_iter_lookahead2 = seq_iter;
00251             ++seq_iter_lookahead2;
00252             for( ; seq_iter_lookahead2 != seq_iter_end && ( *seq_iter_lookahead2 )->start_handle() < *range_iter; )
00253             {
00254                 ++seq_iter;
00255                 ++seq_iter_lookahead2;
00256             }
00257         }
00258 
00259         int i = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
00260 
00261         // Get the connectivity array
00262         EntityHandle* conn_array = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
00263 
00264         EntityHandle start_handle = ( *seq_iter )->start_handle();
00265 
00266         for( Range::const_iterator tmp_iter = range_iter; tmp_iter != range_iter_lookahead; ++tmp_iter )
00267         {
00268             // Set the element id tag
00269             mMB->tag_set_data( element_id_tag, &*tmp_iter, 1, &start_element_id );
00270             ++start_element_id;
00271 
00272             if( add_sizes ) *element_array++ = i;
00273 
00274             // For each node
00275             for( int j = 0; j < i; j++ )
00276             {
00277                 EntityHandle node = *( conn_array + j + i * ( *tmp_iter - start_handle ) );
00278                 mMB->tag_get_data( node_id_tag, &node, 1, element_array );
00279                 element_array++;
00280             }
00281         }
00282 
00283         // Go to the next entity sequence
00284         ++seq_iter;
00285         // Start with the next entities
00286         range_iter = range_iter_lookahead;
00287     }
00288 
00289     return MB_SUCCESS;
00290 }
00291 
00292 ErrorCode WriteUtil::get_element_connect( Range::const_iterator iter, const Range::const_iterator& end,
00293                                           const int vertices_per_elem, Tag node_id_tag, const size_t elem_array_size,
00294                                           int* const element_array, bool add_sizes )
00295 {
00296     // Check the data we got
00297     if( iter == end ) return MB_FAILURE;
00298     if( vertices_per_elem < 1 ) return MB_FAILURE;
00299     if( !element_array || elem_array_size < (unsigned)vertices_per_elem ) return MB_FAILURE;
00300 
00301     // Sequence iterators
00302     TypeSequenceManager::const_iterator seq_iter, seq_end;
00303 
00304     // loop over range, getting coordinate value
00305     EntityType current_type = MBMAXTYPE;
00306     int* output_iter        = element_array;
00307     int* const output_end   = element_array + elem_array_size;
00308     while( iter != end )
00309     {
00310         // Make sure we have the right sequence list (and get the sequence
00311         // list for the first iteration.)
00312         EntityType type = TYPE_FROM_HANDLE( *iter );
00313         if( type != current_type )
00314         {
00315             if( type >= MBENTITYSET || type < MBEDGE ) return MB_FAILURE;
00316             seq_iter     = mMB->sequence_manager()->entity_map( type ).begin();
00317             seq_end      = mMB->sequence_manager()->entity_map( type ).end();
00318             current_type = type;
00319         }
00320 
00321         // Find the sequence containing the current handle
00322         while( seq_iter != seq_end && ( *seq_iter )->end_handle() < *iter )
00323             ++seq_iter;
00324         if( seq_iter == seq_end || *iter < ( *seq_iter )->start_handle() ) return MB_FAILURE;
00325 
00326         // Get the connectivity array
00327         EntityHandle* conn_array = NULL;
00328         int conn_size            = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
00329         conn_array               = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
00330 
00331         // Determine how much of the sequence we want.
00332         Range::pair_iterator pair( iter );
00333         Range::const_iterator prev( end );
00334         --prev;
00335         EntityHandle range_end    = pair->second;
00336         EntityHandle sequence_end = ( *seq_iter )->end_handle();
00337         EntityHandle end_handle   = range_end > sequence_end ? sequence_end : range_end;
00338         if( end_handle > *prev ) end_handle = *prev;
00339         EntityHandle count = end_handle - *iter + 1;
00340 
00341         // Get offset in sequence to start at
00342         assert( *iter >= ( *seq_iter )->start_handle() );
00343         EntityHandle offset = *iter - ( *seq_iter )->start_handle();
00344 
00345         // Make sure sufficient space in output array
00346         if( ( !add_sizes && output_iter + ( count * conn_size ) > output_end ) ||
00347             ( add_sizes && output_iter + ( count * ( conn_size + 1 ) ) > output_end ) )
00348             return MB_FAILURE;
00349 
00350         // If the nodes per element match, do in one call
00351         conn_array += ( conn_size * offset );
00352         if( vertices_per_elem == conn_size && !add_sizes )
00353         {
00354             ErrorCode rval = mMB->tag_get_data( node_id_tag, conn_array, count * conn_size, output_iter );
00355             if( MB_SUCCESS != rval ) return rval;
00356 
00357             output_iter += count * conn_size;
00358         }
00359         // Otherwise need to do one at a time
00360         else
00361         {
00362             int min = vertices_per_elem > conn_size ? conn_size : vertices_per_elem;
00363             for( EntityHandle i = 0; i < count; ++i )
00364             {
00365                 *output_iter++ = min;
00366                 ErrorCode rval = mMB->tag_get_data( node_id_tag, conn_array, min, output_iter );
00367                 if( MB_SUCCESS != rval ) return rval;
00368 
00369                 output_iter += min;
00370                 conn_array += conn_size;
00371 
00372                 if( vertices_per_elem > conn_size )
00373                 {  // Need to pad
00374                     memset( output_iter, 0, sizeof( int ) * ( vertices_per_elem - conn_size ) );
00375                     output_iter += ( vertices_per_elem - conn_size );
00376                 }
00377             }
00378         }
00379 
00380         iter += count;
00381     }
00382 
00383     return MB_SUCCESS;
00384 }
00385 
00386 ErrorCode WriteUtil::get_element_connect( Range::const_iterator iter, const Range::const_iterator& end,
00387                                           const int vertices_per_elem, const size_t elem_array_size,
00388                                           EntityHandle* const element_array )
00389 {
00390     // Check the data we got
00391     if( iter == end ) return MB_FAILURE;
00392     if( vertices_per_elem < 1 ) return MB_FAILURE;
00393     if( !element_array || elem_array_size < (unsigned)vertices_per_elem ) return MB_FAILURE;
00394 
00395     // Sequence iterators
00396     TypeSequenceManager::const_iterator seq_iter, seq_end;
00397 
00398     // Loop over range, getting coordinate value
00399     EntityType current_type        = MBMAXTYPE;
00400     EntityHandle* output_iter      = element_array;
00401     EntityHandle* const output_end = element_array + elem_array_size;
00402     while( iter != end )
00403     {
00404         // Make sure we have the right sequence list (and get the sequence
00405         // list for the first iteration.)
00406         EntityType type = TYPE_FROM_HANDLE( *iter );
00407         if( type != current_type )
00408         {
00409             if( type >= MBENTITYSET || type < MBEDGE ) return MB_FAILURE;
00410             seq_iter     = mMB->sequence_manager()->entity_map( type ).begin();
00411             seq_end      = mMB->sequence_manager()->entity_map( type ).end();
00412             current_type = type;
00413         }
00414 
00415         // Find the sequence containing the current handle
00416         while( seq_iter != seq_end && ( *seq_iter )->end_handle() < *iter )
00417             ++seq_iter;
00418         if( seq_iter == seq_end || *iter < ( *seq_iter )->start_handle() ) return MB_FAILURE;
00419 
00420         // Get the connectivity array
00421         EntityHandle* conn_array = NULL;
00422         int conn_size            = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
00423         if( conn_size != vertices_per_elem ) return MB_FAILURE;
00424         conn_array = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
00425 
00426         // Determine how much of the sequence we want.
00427         Range::pair_iterator pair( iter );
00428         Range::const_iterator prev( end );
00429         --prev;
00430         EntityHandle range_end    = pair->second;
00431         EntityHandle sequence_end = ( *seq_iter )->end_handle();
00432         EntityHandle end_handle   = range_end > sequence_end ? sequence_end : range_end;
00433         if( end_handle > *prev ) end_handle = *prev;
00434         EntityHandle count = end_handle - *iter + 1;
00435 
00436         // Get offset in sequence to start at
00437         assert( *iter >= ( *seq_iter )->start_handle() );
00438         EntityHandle offset = *iter - ( *seq_iter )->start_handle();
00439 
00440         // Make sure sufficient space in output array
00441         if( output_iter + ( count * conn_size ) > output_end ) return MB_FAILURE;
00442 
00443         if( conn_array == NULL )
00444         {  // If it is structured mesh
00445             ErrorCode rval;
00446             int temp_buff_size = conn_size * sizeof( EntityHandle );
00447             for( unsigned i = 0; i < count; i++ )
00448             {  // Copy connectivity element by element
00449                 std::vector< EntityHandle > connect;
00450                 rval = static_cast< ElementSequence* >( *seq_iter )->get_connectivity( *iter, connect );
00451                 if( MB_SUCCESS != rval ) { return rval; }
00452                 memcpy( output_iter, &connect[0], temp_buff_size );
00453                 output_iter += conn_size;
00454                 ++iter;
00455             }
00456         }
00457         else
00458         {
00459             // Copy connectivity into output array
00460             conn_array += ( conn_size * offset );
00461             memcpy( output_iter, conn_array, count * conn_size * sizeof( EntityHandle ) );
00462             output_iter += count * conn_size;
00463             iter += count;
00464         }
00465     }
00466 
00467     return MB_SUCCESS;
00468 }
00469 
00470 ErrorCode WriteUtil::get_poly_connect_size( Range::const_iterator /* begin */, const Range::const_iterator& /* end */,
00471                                             int& /* connectivity_size */ )
00472 {
00473     return MB_NOT_IMPLEMENTED;
00474 }
00475 
00476 ErrorCode WriteUtil::get_poly_connect( Range::const_iterator& /* iter */, const Range::const_iterator& /* end */,
00477                                        const Tag /* node_id_tag */, size_t& /* handle_array_len */,
00478                                        int* const /* handle_array */, size_t& /* index_array_len */,
00479                                        int* const /* index_array */, int& /* index_offset */ )
00480 {
00481     return MB_NOT_IMPLEMENTED;
00482 }
00483 
00484 ErrorCode WriteUtil::gather_nodes_from_elements( const Range& elements, const Tag node_bit_mark_tag, Range& nodes )
00485 {
00486     bool printed_warning = false;
00487 
00488     if( elements.empty() ) return MB_SUCCESS;
00489 
00490     if( TYPE_FROM_HANDLE( elements.front() ) <= MBVERTEX || TYPE_FROM_HANDLE( elements.back() ) >= MBENTITYSET )
00491         return MB_TYPE_OUT_OF_RANGE;
00492 
00493     // See if we need to use our own marking tag
00494     Tag exporting_nodes_tag = 0;
00495     if( node_bit_mark_tag )
00496         exporting_nodes_tag = node_bit_mark_tag;
00497     else
00498     {
00499         mMB->tag_get_handle( "__MBWriteUtil::exporting_nodes", 1, MB_TYPE_BIT, exporting_nodes_tag, MB_TAG_CREAT );
00500     }
00501 
00502     // The x,y,z tag handles we need
00503     EntityHandle lower_bound = ~0, upper_bound = 0;
00504 
00505     std::vector< EntityHandle > tmp_conn;
00506 
00507     RangeSeqIntersectIter iter( mMB->sequence_manager() );
00508     for( ErrorCode rval = iter.init( elements.begin(), elements.end() ); MB_FAILURE != rval; rval = iter.step() )
00509     {
00510         if( MB_ENTITY_NOT_FOUND == rval )
00511         {
00512             if( !printed_warning )
00513             {
00514                 std::cerr << "Warning: ignoring invalid element handle(s) in gather_nodes_from_elements" << std::endl;
00515                 printed_warning = true;
00516             }
00517             continue;
00518         }
00519 
00520         ElementSequence* seq = static_cast< ElementSequence* >( iter.get_sequence() );
00521 
00522         // Get the connectivity array
00523         const EntityHandle* conn_array = seq->get_connectivity_array();
00524 
00525         // If unstructured mesh
00526         if( conn_array && mMB->type_from_handle( iter.get_start_handle() ) != MBPOLYHEDRON )
00527         {
00528             assert( iter.get_start_handle() >= seq->start_handle() );
00529             assert( iter.get_end_handle() <= seq->end_handle() );
00530             const EntityHandle offset   = iter.get_start_handle() - seq->start_handle();
00531             const EntityHandle num_elem = iter.get_end_handle() - iter.get_start_handle() + 1;
00532 
00533             conn_array += offset * seq->nodes_per_element();
00534             const EntityHandle num_node = num_elem * seq->nodes_per_element();
00535 
00536             // For each node
00537             for( EntityHandle j = 0; j < num_node; j++ )
00538             {
00539                 EntityHandle node = conn_array[j];
00540                 if( node < lower_bound ) lower_bound = node;
00541                 if( node > upper_bound ) upper_bound = node;
00542                 unsigned char bit = 0x1;
00543                 rval              = mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
00544                 assert( MB_SUCCESS == rval );
00545                 if( MB_SUCCESS != rval ) return rval;
00546             }
00547         }
00548         // Polyhedra
00549         else if( conn_array && mMB->type_from_handle( iter.get_start_handle() ) == MBPOLYHEDRON )
00550         {
00551             assert( iter.get_start_handle() >= seq->start_handle() );
00552             assert( iter.get_end_handle() <= seq->end_handle() );
00553             const EntityHandle offset   = iter.get_start_handle() - seq->start_handle();
00554             const EntityHandle num_elem = iter.get_end_handle() - iter.get_start_handle() + 1;
00555 
00556             conn_array += offset * seq->nodes_per_element();
00557             int num_face = num_elem * seq->nodes_per_element();
00558 
00559             // For each node
00560             for( int j = 0; j < num_face; j++ )
00561             {
00562                 const EntityHandle* face_conn = NULL;
00563                 int face_num_conn             = 0;
00564                 rval                          = mMB->get_connectivity( conn_array[j], face_conn, face_num_conn, false );
00565                 if( MB_SUCCESS != rval ) return rval;
00566                 for( int k = 0; k < face_num_conn; k++ )
00567                 {
00568                     EntityHandle node = face_conn[k];
00569                     if( node < lower_bound ) lower_bound = node;
00570                     if( node > upper_bound ) upper_bound = node;
00571                     unsigned char bit = 0x1;
00572                     rval              = mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
00573                     assert( MB_SUCCESS == rval );
00574                     if( MB_SUCCESS != rval ) return rval;
00575                 }
00576             }
00577         }
00578         // Structured mesh
00579         else
00580         {
00581             EntityHandle end_h = iter.get_end_handle() + 1;
00582             for( EntityHandle h = iter.get_start_handle(); h < end_h; ++h )
00583             {
00584                 tmp_conn.clear();
00585                 rval = seq->get_connectivity( h, tmp_conn, false );
00586                 if( MB_SUCCESS != rval )
00587                 {
00588                     if( node_bit_mark_tag == 0 ) mMB->tag_delete( exporting_nodes_tag );
00589                     return rval;
00590                 }
00591 
00592                 // For each node
00593                 for( size_t j = 0; j < tmp_conn.size(); j++ )
00594                 {
00595                     EntityHandle node = tmp_conn[j];
00596                     if( node < lower_bound ) lower_bound = node;
00597                     if( node > upper_bound ) upper_bound = node;
00598                     unsigned char bit = 0x1;
00599                     mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
00600                 }
00601             }
00602         }
00603     }
00604 
00605     // We can get a REALLY long loop if lower_bound is zero
00606     assert( lower_bound != 0 );
00607     // Gather up all the nodes
00608     for( ; upper_bound >= lower_bound; --upper_bound )
00609     {
00610         unsigned char node_marked = 0;
00611         mMB->tag_get_data( exporting_nodes_tag, &upper_bound, 1, &node_marked );
00612         if( node_marked == 0x1 ) nodes.insert( upper_bound );
00613     }
00614 
00615     // Clean up our own marking tag
00616     if( node_bit_mark_tag == 0 ) mMB->tag_delete( exporting_nodes_tag );
00617 
00618     return MB_SUCCESS;
00619 }
00620 
00621 //! Assign ids to input elements starting with start_id, written to id_tag
00622 //! if zero, assigns to GLOBAL_ID_TAG_NAME
00623 ErrorCode WriteUtil::assign_ids( Range& elements, Tag id_tag, const int start_id )
00624 {
00625     ErrorCode result;
00626     if( 0 == id_tag )
00627     {
00628         // Get the global id tag
00629         id_tag = mMB->globalId_tag();
00630     }
00631 
00632     // Now assign the ids
00633     int i;
00634     Range::iterator rit;
00635     ErrorCode tmp_result;
00636     result = MB_SUCCESS;
00637     for( i = start_id, rit = elements.begin(); rit != elements.end(); ++rit, i++ )
00638     {
00639         tmp_result = mMB->tag_set_data( id_tag, &( *rit ), 1, &i );
00640         if( MB_SUCCESS != tmp_result ) result = tmp_result;
00641     }
00642 
00643     return result;
00644 }
00645 
00646 ErrorCode WriteUtil::get_adjacencies( EntityHandle entity, Tag id_tag, std::vector< int >& adj )
00647 {
00648     ErrorCode rval;
00649     const EntityHandle* adj_array;
00650     int num_adj, id;
00651 
00652     // Get handles of adjacent entities
00653     rval = mMB->a_entity_factory()->get_adjacencies( entity, adj_array, num_adj );
00654     if( MB_SUCCESS != rval )
00655     {
00656         adj.clear();
00657         return rval;
00658     }
00659 
00660     // Append IDs of adjacent entities -- skip meshsets
00661     adj.resize( num_adj );  // Pre-allocate space
00662     adj.clear();            // Clear used space
00663 
00664     const EntityHandle* const end = adj_array + num_adj;
00665     for( const EntityHandle* iter = adj_array; iter != end; ++iter )
00666     {
00667         if( TYPE_FROM_HANDLE( *iter ) != MBENTITYSET )
00668         {
00669             rval = mMB->tag_get_data( id_tag, iter, 1, &id );
00670             if( MB_SUCCESS != rval ) return rval;
00671             adj.push_back( id );
00672         }
00673     }
00674 
00675     return MB_SUCCESS;
00676 }
00677 
00678 ErrorCode WriteUtil::get_adjacencies( EntityHandle entity, const EntityHandle*& adj_array, int& num_adj )
00679 {
00680     return mMB->a_entity_factory()->get_adjacencies( entity, adj_array, num_adj );
00681 }
00682 
00683 ErrorCode WriteUtil::get_tag_list( std::vector< Tag >& result_list, const Tag* user_tag_list, int user_tag_list_length,
00684                                    bool include_variable_length_tags )
00685 {
00686     ErrorCode rval;
00687 
00688     if( user_tag_list )
00689     {
00690         result_list.clear();
00691         result_list.reserve( user_tag_list_length );
00692         for( int i = 0; i < user_tag_list_length; ++i )
00693         {
00694             std::string name;
00695             rval = mMB->tag_get_name( user_tag_list[i], name );MB_CHK_SET_ERR( rval, "Error " << (int)rval << " getting name for tag (Invalid input tag handle?)" );
00696 
00697             if( name.empty() ) { MB_SET_ERR( MB_TAG_NOT_FOUND, "Explicit request to save anonymous tag" ); }
00698 
00699             int size;
00700             if( !include_variable_length_tags &&
00701                 MB_VARIABLE_DATA_LENGTH == mMB->tag_get_length( user_tag_list[i], size ) )
00702             {
00703                 MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "File format cannot store variable-length tag: \"" << name << "\"" );
00704             }
00705 
00706             result_list.push_back( user_tag_list[i] );
00707         }
00708     }
00709     else
00710     {
00711         std::vector< Tag > temp_list;
00712         rval = mMB->tag_get_tags( temp_list );MB_CHK_SET_ERR( rval, "Interface::tag_get_tags failed" );
00713 
00714         result_list.clear();
00715         result_list.reserve( temp_list.size() );
00716 
00717         std::vector< Tag >::iterator i;
00718         for( i = temp_list.begin(); i != temp_list.end(); ++i )
00719         {
00720             std::string name;
00721             rval = mMB->tag_get_name( *i, name );MB_CHK_SET_ERR( rval, "Error " << (int)rval << " getting name for tag (Stale tag handle?)" );
00722 
00723             // Skip anonymous tags
00724             if( name.empty() ) continue;
00725 
00726             // Skip private/internal tags
00727             if( name.size() >= 2 && name[0] == '_' && name[1] == '_' ) continue;
00728 
00729             // If requested, skip variable-length tags
00730             int size;
00731             if( !include_variable_length_tags && MB_VARIABLE_DATA_LENGTH == mMB->tag_get_length( *i, size ) ) continue;
00732 
00733             result_list.push_back( *i );
00734         }
00735     }
00736 
00737     return MB_SUCCESS;
00738 }
00739 
00740 ErrorCode WriteUtil::get_entity_list_pointers( Range::const_iterator begin, Range::const_iterator end,
00741                                                EntityHandle const** pointers, EntityListType relation, int* lengths,
00742                                                unsigned char* flags )
00743 {
00744     RangeSeqIntersectIter iter( mMB->sequence_manager() );
00745     ErrorCode rval = iter.init( begin, end );
00746     while( MB_SUCCESS == rval )
00747     {
00748         EntityType type = TYPE_FROM_HANDLE( iter.get_start_handle() );
00749 
00750         if( MBENTITYSET == type )
00751         {
00752             const MeshSetSequence* seq = reinterpret_cast< MeshSetSequence* >( iter.get_sequence() );
00753             const MeshSet* set;
00754             int len = 0;
00755             size_t clen;
00756             for( EntityHandle h = iter.get_start_handle(); h <= iter.get_end_handle(); ++h )
00757             {
00758                 set = seq->get_set( h );
00759                 switch( relation )
00760                 {
00761                     case CONTENTS:
00762                         *pointers = set->get_contents( clen );
00763                         len       = clen;
00764                         break;
00765                     case CHILDREN:
00766                         *pointers = set->get_children( len );
00767                         break;
00768                     case PARENTS:
00769                         *pointers = set->get_parents( len );
00770                         break;
00771                 }
00772                 if( lengths )
00773                 {
00774                     *lengths = len;
00775                     ++lengths;
00776                 }
00777                 if( flags )
00778                 {
00779                     *flags = (unsigned char)set->flags();
00780                     ++flags;
00781                 }
00782                 ++pointers;
00783             }
00784         }
00785 
00786         else if( MBVERTEX != type )
00787         {
00788             const bool topological = ( relation == TOPOLOGICAL );
00789             int len;
00790             const ElementSequence* seq = reinterpret_cast< ElementSequence* >( iter.get_sequence() );
00791             for( EntityHandle h = iter.get_start_handle(); h <= iter.get_end_handle(); ++h )
00792             {
00793                 rval = seq->get_connectivity( h, *pointers, len, topological );
00794                 if( MB_SUCCESS != rval ) return rval;
00795                 if( lengths )
00796                 {
00797                     *lengths = len;
00798                     ++lengths;
00799                 }
00800                 if( flags )
00801                 {
00802                     *flags = 0;
00803                     ++flags;
00804                 }
00805                 ++pointers;
00806             }
00807         }
00808         else
00809         {
00810             return MB_TYPE_OUT_OF_RANGE;
00811         }
00812 
00813         rval = iter.step();
00814     }
00815     if( MB_FAILURE == rval )
00816         return MB_SUCCESS;  // At end of list
00817     else
00818         return rval;
00819 }
00820 
00821 ErrorCode WriteUtil::get_entity_list_pointers( EntityHandle const* entities, int num_entities,
00822                                                EntityHandle const** pointers, EntityListType relation, int* lengths,
00823                                                unsigned char* flags )
00824 {
00825     SequenceManager* sm = mMB->sequence_manager();
00826     const EntitySequence* tmp_seq;
00827     ErrorCode rval = MB_SUCCESS;
00828     for( int i = 0; i < num_entities; i++ )
00829     {
00830         rval = sm->find( entities[i], tmp_seq );
00831         if( MB_SUCCESS != rval ) return rval;
00832 
00833         EntityType type = TYPE_FROM_HANDLE( entities[i] );
00834 
00835         if( MBENTITYSET == type )
00836         {
00837             const MeshSetSequence* seq = reinterpret_cast< const MeshSetSequence* >( tmp_seq );
00838             const MeshSet* set;
00839             int len = 0;
00840             size_t clen;
00841             set = seq->get_set( entities[i] );
00842             switch( relation )
00843             {
00844                 case CONTENTS:
00845                     *pointers = set->get_contents( clen );
00846                     len       = clen;
00847                     break;
00848                 case CHILDREN:
00849                     *pointers = set->get_children( len );
00850                     break;
00851                 case PARENTS:
00852                     *pointers = set->get_parents( len );
00853                     break;
00854             }
00855             if( lengths )
00856             {
00857                 *lengths = len;
00858                 ++lengths;
00859             }
00860             if( flags )
00861             {
00862                 *flags = (unsigned char)set->flags();
00863                 ++flags;
00864             }
00865             ++pointers;
00866         }
00867         else if( MBVERTEX != type )
00868         {
00869             const bool topological = ( relation == TOPOLOGICAL );
00870             int len;
00871             const ElementSequence* seq = reinterpret_cast< const ElementSequence* >( tmp_seq );
00872             rval                       = seq->get_connectivity( entities[i], *pointers, len, topological );
00873             if( MB_SUCCESS != rval ) return rval;
00874             if( lengths )
00875             {
00876                 *lengths = len;
00877                 ++lengths;
00878             }
00879             if( flags )
00880             {
00881                 *flags = 0;
00882                 ++flags;
00883             }
00884             ++pointers;
00885         }
00886         else
00887         {
00888             return MB_TYPE_OUT_OF_RANGE;
00889         }
00890     }
00891 
00892     return MB_SUCCESS;
00893 }
00894 
00895 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines