![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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
00032 #include
00033 #include
00034 #include
00035 #include
00036
00037 #ifdef WIN32
00038 #define stat _stat
00039 #else
00040 #include
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