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