MOAB: Mesh Oriented datABase
(version 5.4.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 ) ) 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