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