MOAB: Mesh Oriented datABase  (version 5.2.1)
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 <errno.h>
00034 #include <assert.h>
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         if( current_type != TYPE_FROM_HANDLE( *range_iter ) )
00243         {
00244             current_type = TYPE_FROM_HANDLE( *range_iter );
00245             seq_iter     = mMB->sequence_manager()->entity_map( current_type ).begin();
00246             seq_iter_end = mMB->sequence_manager()->entity_map( current_type ).end();
00247 
00248             // Let's find the entity sequence which holds the first entity of this type
00249             TypeSequenceManager::const_iterator seq_iter_lookahead2 = seq_iter;
00250             ++seq_iter_lookahead2;
00251             for( ; seq_iter_lookahead2 != seq_iter_end && ( *seq_iter_lookahead2 )->start_handle() < *range_iter; )
00252             {
00253                 ++seq_iter;
00254                 ++seq_iter_lookahead2;
00255             }
00256         }
00257 
00258         int i = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
00259 
00260         // Get the connectivity array
00261         EntityHandle* conn_array = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
00262 
00263         EntityHandle start_handle = ( *seq_iter )->start_handle();
00264 
00265         for( Range::const_iterator tmp_iter = range_iter; tmp_iter != range_iter_lookahead; ++tmp_iter )
00266         {
00267             // Set the element id tag
00268             mMB->tag_set_data( element_id_tag, &*tmp_iter, 1, &start_element_id );
00269             ++start_element_id;
00270 
00271             if( add_sizes ) *element_array++ = i;
00272 
00273             // For each node
00274             for( int j = 0; j < i; j++ )
00275             {
00276                 EntityHandle node = *( conn_array + j + i * ( *tmp_iter - start_handle ) );
00277                 mMB->tag_get_data( node_id_tag, &node, 1, element_array );
00278                 element_array++;
00279             }
00280         }
00281 
00282         // Go to the next entity sequence
00283         ++seq_iter;
00284         // Start with the next entities
00285         range_iter = range_iter_lookahead;
00286     }
00287 
00288     return MB_SUCCESS;
00289 }
00290 
00291 ErrorCode WriteUtil::get_element_connect( Range::const_iterator iter, const Range::const_iterator& end,
00292                                           const int vertices_per_elem, Tag node_id_tag, const size_t elem_array_size,
00293                                           int* const element_array, bool add_sizes )
00294 {
00295     // Check the data we got
00296     if( iter == end ) return MB_FAILURE;
00297     if( vertices_per_elem < 1 ) return MB_FAILURE;
00298     if( !element_array || elem_array_size < (unsigned)vertices_per_elem ) return MB_FAILURE;
00299 
00300     // Sequence iterators
00301     TypeSequenceManager::const_iterator seq_iter, seq_end;
00302 
00303     // loop over range, getting coordinate value
00304     EntityType current_type = MBMAXTYPE;
00305     int* output_iter        = element_array;
00306     int* const output_end   = element_array + elem_array_size;
00307     while( iter != end )
00308     {
00309         // Make sure we have the right sequence list (and get the sequence
00310         // list for the first iteration.)
00311         EntityType type = TYPE_FROM_HANDLE( *iter );
00312         if( type != current_type )
00313         {
00314             if( type >= MBENTITYSET || type < MBEDGE ) return MB_FAILURE;
00315             seq_iter     = mMB->sequence_manager()->entity_map( type ).begin();
00316             seq_end      = mMB->sequence_manager()->entity_map( type ).end();
00317             current_type = type;
00318         }
00319 
00320         // Find the sequence containing the current handle
00321         while( seq_iter != seq_end && ( *seq_iter )->end_handle() < *iter )
00322             ++seq_iter;
00323         if( seq_iter == seq_end || *iter < ( *seq_iter )->start_handle() ) return MB_FAILURE;
00324 
00325         // Get the connectivity array
00326         EntityHandle* conn_array = NULL;
00327         int conn_size            = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
00328         conn_array               = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
00329 
00330         // Determine how much of the sequence we want.
00331         Range::pair_iterator pair( iter );
00332         Range::const_iterator prev( end );
00333         --prev;
00334         EntityHandle range_end    = pair->second;
00335         EntityHandle sequence_end = ( *seq_iter )->end_handle();
00336         EntityHandle end_handle   = range_end > sequence_end ? sequence_end : range_end;
00337         if( end_handle > *prev ) end_handle = *prev;
00338         EntityHandle count = end_handle - *iter + 1;
00339 
00340         // Get offset in sequence to start at
00341         assert( *iter >= ( *seq_iter )->start_handle() );
00342         EntityHandle offset = *iter - ( *seq_iter )->start_handle();
00343 
00344         // Make sure sufficient space in output array
00345         if( ( !add_sizes && output_iter + ( count * conn_size ) > output_end ) ||
00346             ( add_sizes && output_iter + ( count * ( conn_size + 1 ) ) > output_end ) )
00347             return MB_FAILURE;
00348 
00349         // If the nodes per element match, do in one call
00350         conn_array += ( conn_size * offset );
00351         if( vertices_per_elem == conn_size && !add_sizes )
00352         {
00353             ErrorCode rval = mMB->tag_get_data( node_id_tag, conn_array, count * conn_size, output_iter );
00354             if( MB_SUCCESS != rval ) return rval;
00355 
00356             output_iter += count * conn_size;
00357         }
00358         // Otherwise need to do one at a time
00359         else
00360         {
00361             int min = vertices_per_elem > conn_size ? conn_size : vertices_per_elem;
00362             for( EntityHandle i = 0; i < count; ++i )
00363             {
00364                 *output_iter++ = min;
00365                 ErrorCode rval = mMB->tag_get_data( node_id_tag, conn_array, min, output_iter );
00366                 if( MB_SUCCESS != rval ) return rval;
00367 
00368                 output_iter += min;
00369                 conn_array += conn_size;
00370 
00371                 if( vertices_per_elem > conn_size )
00372                 {  // Need to pad
00373                     memset( output_iter, 0, sizeof( int ) * ( vertices_per_elem - conn_size ) );
00374                     output_iter += ( vertices_per_elem - conn_size );
00375                 }
00376             }
00377         }
00378 
00379         iter += count;
00380     }
00381 
00382     return MB_SUCCESS;
00383 }
00384 
00385 ErrorCode WriteUtil::get_element_connect( Range::const_iterator iter, const Range::const_iterator& end,
00386                                           const int vertices_per_elem, const size_t elem_array_size,
00387                                           EntityHandle* const element_array )
00388 {
00389     // Check the data we got
00390     if( iter == end ) return MB_FAILURE;
00391     if( vertices_per_elem < 1 ) return MB_FAILURE;
00392     if( !element_array || elem_array_size < (unsigned)vertices_per_elem ) return MB_FAILURE;
00393 
00394     // Sequence iterators
00395     TypeSequenceManager::const_iterator seq_iter, seq_end;
00396 
00397     // Loop over range, getting coordinate value
00398     EntityType current_type        = MBMAXTYPE;
00399     EntityHandle* output_iter      = element_array;
00400     EntityHandle* const output_end = element_array + elem_array_size;
00401     while( iter != end )
00402     {
00403         // Make sure we have the right sequence list (and get the sequence
00404         // list for the first iteration.)
00405         EntityType type = TYPE_FROM_HANDLE( *iter );
00406         if( type != current_type )
00407         {
00408             if( type >= MBENTITYSET || type < MBEDGE ) return MB_FAILURE;
00409             seq_iter     = mMB->sequence_manager()->entity_map( type ).begin();
00410             seq_end      = mMB->sequence_manager()->entity_map( type ).end();
00411             current_type = type;
00412         }
00413 
00414         // Find the sequence containing the current handle
00415         while( seq_iter != seq_end && ( *seq_iter )->end_handle() < *iter )
00416             ++seq_iter;
00417         if( seq_iter == seq_end || *iter < ( *seq_iter )->start_handle() ) return MB_FAILURE;
00418 
00419         // Get the connectivity array
00420         EntityHandle* conn_array = NULL;
00421         int conn_size            = static_cast< ElementSequence* >( *seq_iter )->nodes_per_element();
00422         if( conn_size != vertices_per_elem ) return MB_FAILURE;
00423         conn_array = static_cast< ElementSequence* >( *seq_iter )->get_connectivity_array();
00424 
00425         // Determine how much of the sequence we want.
00426         Range::pair_iterator pair( iter );
00427         Range::const_iterator prev( end );
00428         --prev;
00429         EntityHandle range_end    = pair->second;
00430         EntityHandle sequence_end = ( *seq_iter )->end_handle();
00431         EntityHandle end_handle   = range_end > sequence_end ? sequence_end : range_end;
00432         if( end_handle > *prev ) end_handle = *prev;
00433         EntityHandle count = end_handle - *iter + 1;
00434 
00435         // Get offset in sequence to start at
00436         assert( *iter >= ( *seq_iter )->start_handle() );
00437         EntityHandle offset = *iter - ( *seq_iter )->start_handle();
00438 
00439         // Make sure sufficient space in output array
00440         if( output_iter + ( count * conn_size ) > output_end ) return MB_FAILURE;
00441 
00442         if( conn_array == NULL )
00443         {  // If it is structured mesh
00444             ErrorCode rval;
00445             int temp_buff_size = conn_size * sizeof( EntityHandle );
00446             for( unsigned i = 0; i < count; i++ )
00447             {  // Copy connectivity element by element
00448                 std::vector< EntityHandle > connect;
00449                 rval = static_cast< ElementSequence* >( *seq_iter )->get_connectivity( *iter, connect );
00450                 if( MB_SUCCESS != rval ) { return rval; }
00451                 memcpy( output_iter, &connect[0], temp_buff_size );
00452                 output_iter += conn_size;
00453                 ++iter;
00454             }
00455         }
00456         else
00457         {
00458             // Copy connectivity into output array
00459             conn_array += ( conn_size * offset );
00460             memcpy( output_iter, conn_array, count * conn_size * sizeof( EntityHandle ) );
00461             output_iter += count * conn_size;
00462             iter += count;
00463         }
00464     }
00465 
00466     return MB_SUCCESS;
00467 }
00468 
00469 ErrorCode WriteUtil::get_poly_connect_size( Range::const_iterator /* begin */, const Range::const_iterator& /* end */,
00470                                             int& /* connectivity_size */ )
00471 {
00472     return MB_NOT_IMPLEMENTED;
00473 }
00474 
00475 ErrorCode WriteUtil::get_poly_connect( Range::const_iterator& /* iter */, const Range::const_iterator& /* end */,
00476                                        const Tag /* node_id_tag */, size_t& /* handle_array_len */,
00477                                        int* const /* handle_array */, size_t& /* index_array_len */,
00478                                        int* const /* index_array */, int& /* index_offset */ )
00479 {
00480     return MB_NOT_IMPLEMENTED;
00481 }
00482 
00483 ErrorCode WriteUtil::gather_nodes_from_elements( const Range& elements, const Tag node_bit_mark_tag, Range& nodes )
00484 {
00485     bool printed_warning = false;
00486 
00487     if( elements.empty() ) return MB_SUCCESS;
00488 
00489     if( TYPE_FROM_HANDLE( elements.front() ) <= MBVERTEX || TYPE_FROM_HANDLE( elements.back() ) >= MBENTITYSET )
00490         return MB_TYPE_OUT_OF_RANGE;
00491 
00492     // See if we need to use our own marking tag
00493     Tag exporting_nodes_tag = 0;
00494     if( node_bit_mark_tag )
00495         exporting_nodes_tag = node_bit_mark_tag;
00496     else
00497     {
00498         mMB->tag_get_handle( "__MBWriteUtil::exporting_nodes", 1, MB_TYPE_BIT, exporting_nodes_tag, MB_TAG_CREAT );
00499     }
00500 
00501     // The x,y,z tag handles we need
00502     EntityHandle lower_bound = ~0, upper_bound = 0;
00503 
00504     std::vector< EntityHandle > tmp_conn;
00505 
00506     RangeSeqIntersectIter iter( mMB->sequence_manager() );
00507     for( ErrorCode rval = iter.init( elements.begin(), elements.end() ); MB_FAILURE != rval; rval = iter.step() )
00508     {
00509         if( MB_ENTITY_NOT_FOUND == rval )
00510         {
00511             if( !printed_warning )
00512             {
00513                 std::cerr << "Warning: ignoring invalid element handle(s) in gather_nodes_from_elements" << std::endl;
00514                 printed_warning = true;
00515             }
00516             continue;
00517         }
00518 
00519         ElementSequence* seq = static_cast< ElementSequence* >( iter.get_sequence() );
00520 
00521         // Get the connectivity array
00522         const EntityHandle* conn_array = seq->get_connectivity_array();
00523 
00524         // If unstructured mesh
00525         if( conn_array && mMB->type_from_handle( iter.get_start_handle() ) != MBPOLYHEDRON )
00526         {
00527             assert( iter.get_start_handle() >= seq->start_handle() );
00528             assert( iter.get_end_handle() <= seq->end_handle() );
00529             const EntityHandle offset   = iter.get_start_handle() - seq->start_handle();
00530             const EntityHandle num_elem = iter.get_end_handle() - iter.get_start_handle() + 1;
00531 
00532             conn_array += offset * seq->nodes_per_element();
00533             const EntityHandle num_node = num_elem * seq->nodes_per_element();
00534 
00535             // For each node
00536             for( EntityHandle j = 0; j < num_node; j++ )
00537             {
00538                 EntityHandle node = conn_array[j];
00539                 if( node < lower_bound ) lower_bound = node;
00540                 if( node > upper_bound ) upper_bound = node;
00541                 unsigned char bit = 0x1;
00542                 rval              = mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
00543                 assert( MB_SUCCESS == rval );
00544                 if( MB_SUCCESS != rval ) return rval;
00545             }
00546         }
00547         // Polyhedra
00548         else if( conn_array && mMB->type_from_handle( iter.get_start_handle() ) == MBPOLYHEDRON )
00549         {
00550             assert( iter.get_start_handle() >= seq->start_handle() );
00551             assert( iter.get_end_handle() <= seq->end_handle() );
00552             const EntityHandle offset   = iter.get_start_handle() - seq->start_handle();
00553             const EntityHandle num_elem = iter.get_end_handle() - iter.get_start_handle() + 1;
00554 
00555             conn_array += offset * seq->nodes_per_element();
00556             int num_face = num_elem * seq->nodes_per_element();
00557 
00558             // For each node
00559             for( int j = 0; j < num_face; j++ )
00560             {
00561                 const EntityHandle* face_conn = NULL;
00562                 int face_num_conn             = 0;
00563                 rval                          = mMB->get_connectivity( conn_array[j], face_conn, face_num_conn, false );
00564                 if( MB_SUCCESS != rval ) return rval;
00565                 for( int k = 0; k < face_num_conn; k++ )
00566                 {
00567                     EntityHandle node = face_conn[k];
00568                     if( node < lower_bound ) lower_bound = node;
00569                     if( node > upper_bound ) upper_bound = node;
00570                     unsigned char bit = 0x1;
00571                     rval              = mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
00572                     assert( MB_SUCCESS == rval );
00573                     if( MB_SUCCESS != rval ) return rval;
00574                 }
00575             }
00576         }
00577         // Structured mesh
00578         else
00579         {
00580             EntityHandle end_h = iter.get_end_handle() + 1;
00581             for( EntityHandle h = iter.get_start_handle(); h < end_h; ++h )
00582             {
00583                 tmp_conn.clear();
00584                 rval = seq->get_connectivity( h, tmp_conn, false );
00585                 if( MB_SUCCESS != rval )
00586                 {
00587                     if( node_bit_mark_tag == 0 ) mMB->tag_delete( exporting_nodes_tag );
00588                     return rval;
00589                 }
00590 
00591                 // For each node
00592                 for( size_t j = 0; j < tmp_conn.size(); j++ )
00593                 {
00594                     EntityHandle node = tmp_conn[j];
00595                     if( node < lower_bound ) lower_bound = node;
00596                     if( node > upper_bound ) upper_bound = node;
00597                     unsigned char bit = 0x1;
00598                     mMB->tag_set_data( exporting_nodes_tag, &node, 1, &bit );
00599                 }
00600             }
00601         }
00602     }
00603 
00604     // We can get a REALLY long loop if lower_bound is zero
00605     assert( lower_bound != 0 );
00606     // Gather up all the nodes
00607     for( ; upper_bound >= lower_bound; --upper_bound )
00608     {
00609         unsigned char node_marked = 0;
00610         mMB->tag_get_data( exporting_nodes_tag, &upper_bound, 1, &node_marked );
00611         if( node_marked == 0x1 ) nodes.insert( upper_bound );
00612     }
00613 
00614     // Clean up our own marking tag
00615     if( node_bit_mark_tag == 0 ) mMB->tag_delete( exporting_nodes_tag );
00616 
00617     return MB_SUCCESS;
00618 }
00619 
00620 //! Assign ids to input elements starting with start_id, written to id_tag
00621 //! if zero, assigns to GLOBAL_ID_TAG_NAME
00622 ErrorCode WriteUtil::assign_ids( Range& elements, Tag id_tag, const int start_id )
00623 {
00624     ErrorCode result;
00625     if( 0 == id_tag )
00626     {
00627         // Get the global id tag
00628         id_tag = mMB->globalId_tag();
00629     }
00630 
00631     // Now assign the ids
00632     int i;
00633     Range::iterator rit;
00634     ErrorCode tmp_result;
00635     result = MB_SUCCESS;
00636     for( i = start_id, rit = elements.begin(); rit != elements.end(); ++rit, i++ )
00637     {
00638         tmp_result = mMB->tag_set_data( id_tag, &( *rit ), 1, &i );
00639         if( MB_SUCCESS != tmp_result ) result = tmp_result;
00640     }
00641 
00642     return result;
00643 }
00644 
00645 ErrorCode WriteUtil::get_adjacencies( EntityHandle entity, Tag id_tag, std::vector< int >& adj )
00646 {
00647     ErrorCode rval;
00648     const EntityHandle* adj_array;
00649     int num_adj, id;
00650 
00651     // Get handles of adjacent entities
00652     rval = mMB->a_entity_factory()->get_adjacencies( entity, adj_array, num_adj );
00653     if( MB_SUCCESS != rval )
00654     {
00655         adj.clear();
00656         return rval;
00657     }
00658 
00659     // Append IDs of adjacent entities -- skip meshsets
00660     adj.resize( num_adj );  // Pre-allocate space
00661     adj.clear();            // Clear used space
00662 
00663     const EntityHandle* const end = adj_array + num_adj;
00664     for( const EntityHandle* iter = adj_array; iter != end; ++iter )
00665     {
00666         if( TYPE_FROM_HANDLE( *iter ) != MBENTITYSET )
00667         {
00668             rval = mMB->tag_get_data( id_tag, iter, 1, &id );
00669             if( MB_SUCCESS != rval ) return rval;
00670             adj.push_back( id );
00671         }
00672     }
00673 
00674     return MB_SUCCESS;
00675 }
00676 
00677 ErrorCode WriteUtil::get_adjacencies( EntityHandle entity, const EntityHandle*& adj_array, int& num_adj )
00678 {
00679     return mMB->a_entity_factory()->get_adjacencies( entity, adj_array, num_adj );
00680 }
00681 
00682 ErrorCode WriteUtil::get_tag_list( std::vector< Tag >& result_list, const Tag* user_tag_list, int user_tag_list_length,
00683                                    bool include_variable_length_tags )
00684 {
00685     ErrorCode rval;
00686 
00687     if( user_tag_list )
00688     {
00689         result_list.clear();
00690         result_list.reserve( user_tag_list_length );
00691         for( int i = 0; i < user_tag_list_length; ++i )
00692         {
00693             std::string name;
00694             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?)" );
00695 
00696             if( name.empty() ) { MB_SET_ERR( MB_TAG_NOT_FOUND, "Explicit request to save anonymous tag" ); }
00697 
00698             int size;
00699             if( !include_variable_length_tags &&
00700                 MB_VARIABLE_DATA_LENGTH == mMB->tag_get_length( user_tag_list[i], size ) )
00701             {
00702                 MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "File format cannot store variable-length tag: \"" << name << "\"" );
00703             }
00704 
00705             result_list.push_back( user_tag_list[i] );
00706         }
00707     }
00708     else
00709     {
00710         std::vector< Tag > temp_list;
00711         rval = mMB->tag_get_tags( temp_list );MB_CHK_SET_ERR( rval, "Interface::tag_get_tags failed" );
00712 
00713         result_list.clear();
00714         result_list.reserve( temp_list.size() );
00715 
00716         std::vector< Tag >::iterator i;
00717         for( i = temp_list.begin(); i != temp_list.end(); ++i )
00718         {
00719             std::string name;
00720             rval = mMB->tag_get_name( *i, name );MB_CHK_SET_ERR( rval, "Error " << (int)rval << " getting name for tag (Stale tag handle?)" );
00721 
00722             // Skip anonymous tags
00723             if( name.empty() ) continue;
00724 
00725             // Skip private/internal tags
00726             if( name.size() >= 2 && name[0] == '_' && name[1] == '_' ) continue;
00727 
00728             // If requested, skip variable-length tags
00729             int size;
00730             if( !include_variable_length_tags && MB_VARIABLE_DATA_LENGTH == mMB->tag_get_length( *i, size ) ) continue;
00731 
00732             result_list.push_back( *i );
00733         }
00734     }
00735 
00736     return MB_SUCCESS;
00737 }
00738 
00739 ErrorCode WriteUtil::get_entity_list_pointers( Range::const_iterator begin, Range::const_iterator end,
00740                                                EntityHandle const** pointers, EntityListType relation, int* lengths,
00741                                                unsigned char* flags )
00742 {
00743     RangeSeqIntersectIter iter( mMB->sequence_manager() );
00744     ErrorCode rval = iter.init( begin, end );
00745     while( MB_SUCCESS == rval )
00746     {
00747         EntityType type = TYPE_FROM_HANDLE( iter.get_start_handle() );
00748 
00749         if( MBENTITYSET == type )
00750         {
00751             const MeshSetSequence* seq = reinterpret_cast< MeshSetSequence* >( iter.get_sequence() );
00752             const MeshSet* set;
00753             int len = 0;
00754             size_t clen;
00755             for( EntityHandle h = iter.get_start_handle(); h <= iter.get_end_handle(); ++h )
00756             {
00757                 set = seq->get_set( h );
00758                 switch( relation )
00759                 {
00760                     case CONTENTS:
00761                         *pointers = set->get_contents( clen );
00762                         len       = clen;
00763                         break;
00764                     case CHILDREN:
00765                         *pointers = set->get_children( len );
00766                         break;
00767                     case PARENTS:
00768                         *pointers = set->get_parents( len );
00769                         break;
00770                 }
00771                 if( lengths )
00772                 {
00773                     *lengths = len;
00774                     ++lengths;
00775                 }
00776                 if( flags )
00777                 {
00778                     *flags = (unsigned char)set->flags();
00779                     ++flags;
00780                 }
00781                 ++pointers;
00782             }
00783         }
00784 
00785         else if( MBVERTEX != type )
00786         {
00787             const bool topological = ( relation == TOPOLOGICAL );
00788             int len;
00789             const ElementSequence* seq = reinterpret_cast< ElementSequence* >( iter.get_sequence() );
00790             for( EntityHandle h = iter.get_start_handle(); h <= iter.get_end_handle(); ++h )
00791             {
00792                 rval = seq->get_connectivity( h, *pointers, len, topological );
00793                 if( MB_SUCCESS != rval ) return rval;
00794                 if( lengths )
00795                 {
00796                     *lengths = len;
00797                     ++lengths;
00798                 }
00799                 if( flags )
00800                 {
00801                     *flags = 0;
00802                     ++flags;
00803                 }
00804                 ++pointers;
00805             }
00806         }
00807         else
00808         {
00809             return MB_TYPE_OUT_OF_RANGE;
00810         }
00811 
00812         rval = iter.step();
00813     }
00814     if( MB_FAILURE == rval )
00815         return MB_SUCCESS;  // At end of list
00816     else
00817         return rval;
00818 }
00819 
00820 ErrorCode WriteUtil::get_entity_list_pointers( EntityHandle const* entities, int num_entities,
00821                                                EntityHandle const** pointers, EntityListType relation, int* lengths,
00822                                                unsigned char* flags )
00823 {
00824     SequenceManager* sm = mMB->sequence_manager();
00825     const EntitySequence* tmp_seq;
00826     ErrorCode rval = MB_SUCCESS;
00827     for( int i = 0; i < num_entities; i++ )
00828     {
00829         rval = sm->find( entities[i], tmp_seq );
00830         if( MB_SUCCESS != rval ) return rval;
00831 
00832         EntityType type = TYPE_FROM_HANDLE( entities[i] );
00833 
00834         if( MBENTITYSET == type )
00835         {
00836             const MeshSetSequence* seq = reinterpret_cast< const MeshSetSequence* >( tmp_seq );
00837             const MeshSet* set;
00838             int len = 0;
00839             size_t clen;
00840             set = seq->get_set( entities[i] );
00841             switch( relation )
00842             {
00843                 case CONTENTS:
00844                     *pointers = set->get_contents( clen );
00845                     len       = clen;
00846                     break;
00847                 case CHILDREN:
00848                     *pointers = set->get_children( len );
00849                     break;
00850                 case PARENTS:
00851                     *pointers = set->get_parents( len );
00852                     break;
00853             }
00854             if( lengths )
00855             {
00856                 *lengths = len;
00857                 ++lengths;
00858             }
00859             if( flags )
00860             {
00861                 *flags = (unsigned char)set->flags();
00862                 ++flags;
00863             }
00864             ++pointers;
00865         }
00866         else if( MBVERTEX != type )
00867         {
00868             const bool topological = ( relation == TOPOLOGICAL );
00869             int len;
00870             const ElementSequence* seq = reinterpret_cast< const ElementSequence* >( tmp_seq );
00871             rval                       = seq->get_connectivity( entities[i], *pointers, len, topological );
00872             if( MB_SUCCESS != rval ) return rval;
00873             if( lengths )
00874             {
00875                 *lengths = len;
00876                 ++lengths;
00877             }
00878             if( flags )
00879             {
00880                 *flags = 0;
00881                 ++flags;
00882             }
00883             ++pointers;
00884         }
00885         else
00886         {
00887             return MB_TYPE_OUT_OF_RANGE;
00888         }
00889     }
00890 
00891     return MB_SUCCESS;
00892 }
00893 
00894 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines