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 #include "AEntityFactory.hpp" 00017 #include "Internals.hpp" 00018 #include "moab/Core.hpp" 00019 #include "moab/Range.hpp" 00020 #include "moab/Error.hpp" 00021 #include "moab/CN.hpp" 00022 #include "moab/MeshTopoUtil.hpp" 00023 #include "EntitySequence.hpp" 00024 #include "SequenceData.hpp" 00025 #include "SequenceManager.hpp" 00026 #include "RangeSeqIntersectIter.hpp" 00027 00028 #include <cassert> 00029 #include <algorithm> 00030 #include <set> 00031 00032 namespace moab 00033 { 00034 00035 ErrorCode AEntityFactory::get_vertices( EntityHandle h, 00036 const EntityHandle*& vect_out, 00037 int& count_out, 00038 std::vector< EntityHandle >& storage ) 00039 { 00040 ErrorCode result; 00041 if( MBPOLYHEDRON == TYPE_FROM_HANDLE( h ) ) 00042 { 00043 storage.clear(); 00044 result = thisMB->get_adjacencies( &h, 1, 0, false, storage ); 00045 vect_out = &storage[0]; 00046 count_out = storage.size(); 00047 } 00048 else 00049 { 00050 result = thisMB->get_connectivity( h, vect_out, count_out, false, &storage ); 00051 } 00052 return result; 00053 } 00054 00055 AEntityFactory::AEntityFactory( Core* mdb ) 00056 { 00057 assert( NULL != mdb ); 00058 thisMB = mdb; 00059 mVertElemAdj = false; 00060 } 00061 00062 AEntityFactory::~AEntityFactory() 00063 { 00064 // clean up all the adjacency information that was created 00065 EntityType ent_type; 00066 00067 // iterate through each element type 00068 for( ent_type = MBVERTEX; ent_type <= MBENTITYSET; ent_type++ ) 00069 { 00070 TypeSequenceManager::iterator i; 00071 TypeSequenceManager& seqman = thisMB->sequence_manager()->entity_map( ent_type ); 00072 for( i = seqman.begin(); i != seqman.end(); ++i ) 00073 { 00074 std::vector< EntityHandle >** adj_list = ( *i )->data()->get_adjacency_data(); 00075 if( !adj_list ) continue; 00076 adj_list += ( *i )->start_handle() - ( *i )->data()->start_handle(); 00077 00078 for( EntityID j = 0; j < ( *i )->size(); ++j ) 00079 { 00080 delete adj_list[j]; 00081 adj_list[j] = 0; 00082 } 00083 } 00084 } 00085 } 00086 00087 //! get the elements contained by source_entity, of 00088 //! type target_type, passing back in target_entities; if create_if_missing 00089 //! is true and no entity is found, one is created; if create_adjacency_option 00090 //! is >= 0, adjacencies from entities of that dimension to each target_entity 00091 //! are created (this function uses AEntityFactory::get_element for each element) 00092 ErrorCode AEntityFactory::get_elements( EntityHandle source_entity, 00093 const unsigned int target_dimension, 00094 std::vector< EntityHandle >& target_entities, 00095 const bool create_if_missing, 00096 const int create_adjacency_option ) 00097 { 00098 // check for trivial case first 00099 const EntityType source_type = TYPE_FROM_HANDLE( source_entity ); 00100 const unsigned source_dimension = CN::Dimension( source_type ); 00101 00102 if( source_type >= MBENTITYSET || target_dimension < 1 || target_dimension > 3 ) 00103 { 00104 return MB_TYPE_OUT_OF_RANGE; 00105 } 00106 else if( source_dimension == target_dimension ) 00107 { 00108 target_entities.push_back( source_entity ); 00109 return MB_SUCCESS; 00110 } 00111 00112 ErrorCode result; 00113 if( mVertElemAdj == false ) 00114 { 00115 result = create_vert_elem_adjacencies(); 00116 if( MB_SUCCESS != result ) return result; 00117 } 00118 00119 if( source_dimension == 0 ) 00120 { 00121 result = get_zero_to_n_elements( source_entity, target_dimension, target_entities, create_if_missing, 00122 create_adjacency_option ); 00123 } 00124 else if( source_dimension > target_dimension ) 00125 { 00126 result = get_down_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing, 00127 create_adjacency_option ); 00128 } 00129 else // if(source_dimension < target_dimension) 00130 { 00131 result = get_up_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing, 00132 create_adjacency_option ); 00133 } 00134 00135 return result; 00136 } 00137 00138 ErrorCode AEntityFactory::get_polyhedron_vertices( const EntityHandle source_entity, 00139 std::vector< EntityHandle >& target_entities ) 00140 { 00141 // get the connectivity array pointer 00142 const EntityHandle* connect = NULL; 00143 int num_connect = 0; 00144 ErrorCode result = thisMB->get_connectivity( source_entity, connect, num_connect ); 00145 if( MB_SUCCESS != result ) return result; 00146 00147 // now get the union of those polygons' vertices 00148 result = thisMB->get_adjacencies( connect, num_connect, 0, false, target_entities, Interface::UNION ); 00149 return result; 00150 } 00151 00152 ErrorCode AEntityFactory::get_associated_meshsets( EntityHandle source_entity, 00153 std::vector< EntityHandle >& target_entities ) 00154 { 00155 00156 ErrorCode result; 00157 00158 const EntityHandle* adj_vec; 00159 int num_adj; 00160 result = get_adjacencies( source_entity, adj_vec, num_adj ); 00161 if( result != MB_SUCCESS || adj_vec == NULL ) return result; 00162 00163 // find the meshsets in this vector 00164 DimensionPair dim_pair = CN::TypeDimensionMap[4]; 00165 int dum; 00166 const EntityHandle* start_ent = 00167 std::lower_bound( adj_vec, adj_vec + num_adj, CREATE_HANDLE( dim_pair.first, MB_START_ID, dum ) ); 00168 const EntityHandle* end_ent = 00169 std::lower_bound( start_ent, adj_vec + num_adj, CREATE_HANDLE( dim_pair.second, MB_END_ID, dum ) ); 00170 00171 // copy the the meshsets 00172 target_entities.insert( target_entities.end(), start_ent, end_ent ); 00173 00174 return result; 00175 } 00176 00177 //! get the element defined by the vertices in vertex_list, of the 00178 //! type target_type, passing back in target_entity; if create_if_missing 00179 //! is true and no entity is found, one is created; if create_adjacency_option 00180 //! is >= 0, adjacencies from entities of that dimension to target_entity 00181 //! are created (only create_adjacency_option=0 is supported right now, 00182 //! so that never creates other ancillary entities) 00183 ErrorCode AEntityFactory::get_element( const EntityHandle* vertex_list, 00184 const int vertex_list_size, 00185 const EntityType target_type, 00186 EntityHandle& target_entity, 00187 const bool create_if_missing, 00188 const EntityHandle source_entity, 00189 const int /*create_adjacency_option*/ ) 00190 { 00191 00192 // look over nodes to see if this entity already exists 00193 target_entity = 0; 00194 ErrorCode result; 00195 const EntityHandle *i_adj, *end_adj; 00196 00197 // need vertex adjacencies, so create if necessary 00198 if( mVertElemAdj == false ) create_vert_elem_adjacencies(); 00199 00200 // get the adjacency list 00201 const EntityHandle* adj_vec; 00202 int num_adj; 00203 result = get_adjacencies( vertex_list[0], adj_vec, num_adj ); 00204 if( result != MB_SUCCESS || adj_vec == NULL ) return result; 00205 00206 // check to see if any of these are equivalent to the vertex list 00207 int dum; 00208 00209 // use a fixed-size array, for speed; there should never be more than 5 equivalent entities 00210 EntityHandle temp_vec[15]; 00211 int temp_vec_size = 0; 00212 00213 i_adj = std::lower_bound( adj_vec, adj_vec + num_adj, CREATE_HANDLE( target_type, MB_START_ID, dum ) ); 00214 end_adj = std::lower_bound( i_adj, adj_vec + num_adj, CREATE_HANDLE( target_type, MB_END_ID, dum ) ); 00215 for( ; i_adj != end_adj; ++i_adj ) 00216 { 00217 if( TYPE_FROM_HANDLE( *i_adj ) != target_type ) continue; 00218 00219 if( true == entities_equivalent( *i_adj, vertex_list, vertex_list_size, target_type ) ) 00220 { 00221 temp_vec[temp_vec_size++] = *i_adj; 00222 } 00223 } 00224 00225 if( temp_vec_size == 0 && !create_if_missing ) return result; 00226 00227 // test for size against fixed-size array 00228 assert( temp_vec_size <= 15 ); 00229 00230 // test for empty first, 'cuz it's cheap 00231 if( temp_vec_size == 0 && true == create_if_missing ) 00232 { 00233 00234 // Create the element with this handle (handle is a return type and should be the last 00235 // parameter) 00236 result = thisMB->create_element( target_type, vertex_list, vertex_list_size, target_entity ); 00237 } 00238 00239 // next most likely is one entity 00240 else if( temp_vec_size == 1 ) 00241 target_entity = temp_vec[0]; 00242 00243 // least likely, most work - leave for last test 00244 else 00245 { 00246 // multiple entities found - look for direct adjacencies 00247 if( 0 != source_entity ) 00248 { 00249 00250 int num_adjs; 00251 for( dum = 0; dum < temp_vec_size; dum++ ) 00252 { 00253 result = get_adjacencies( temp_vec[dum], adj_vec, num_adjs ); 00254 if( std::find( adj_vec, ( adj_vec + num_adjs ), source_entity ) != ( adj_vec + num_adjs ) ) 00255 { 00256 // found it, return it 00257 target_entity = temp_vec[dum]; 00258 break; 00259 } 00260 } 00261 00262 if( 0 == target_entity && 00263 thisMB->dimension_from_handle( source_entity ) > CN::Dimension( target_type ) + 1 ) 00264 { 00265 // still have multiple entities, and source dimension is two greater than target, 00266 // so there may not be any explicit adjacencies between the two; look for common 00267 // entities of the intermediate dimension 00268 MeshTopoUtil mtu( thisMB ); 00269 int intermed_dim = CN::Dimension( target_type ) + 1; 00270 for( dum = 0; dum < temp_vec_size; dum++ ) 00271 { 00272 if( 0 != mtu.common_entity( temp_vec[dum], source_entity, intermed_dim ) ) 00273 { 00274 target_entity = temp_vec[dum]; 00275 break; 00276 } 00277 } 00278 } 00279 } 00280 00281 if( target_entity == 0 ) 00282 { 00283 // if we get here, we didn't find a matching adjacency; just take the first one, but 00284 // return a non-success result 00285 target_entity = temp_vec[0]; 00286 result = MB_MULTIPLE_ENTITIES_FOUND; 00287 } 00288 } 00289 00290 return result; 00291 } 00292 00293 bool AEntityFactory::entities_equivalent( const EntityHandle this_entity, 00294 const EntityHandle* vertex_list, 00295 const int vertex_list_size, 00296 const EntityType target_type ) 00297 { 00298 // compare vertices of this_entity with those in the list, returning true if they 00299 // represent the same element 00300 EntityType this_type = TYPE_FROM_HANDLE( this_entity ); 00301 00302 if( this_type != target_type ) 00303 return false; 00304 00305 else if( this_type == MBVERTEX && ( vertex_list_size > 1 || vertex_list[0] != this_entity ) ) 00306 return false; 00307 00308 // need to compare the actual vertices 00309 const EntityHandle* this_vertices = NULL; 00310 int num_this_vertices = 0; 00311 std::vector< EntityHandle > storage; 00312 thisMB->get_connectivity( this_entity, this_vertices, num_this_vertices, false, &storage ); 00313 00314 // see if we can get one node id to match 00315 assert( vertex_list_size > 0 ); 00316 int num_corner_verts = 00317 ( ( this_type == MBPOLYGON || this_type == MBPOLYHEDRON ) ? num_this_vertices 00318 : CN::VerticesPerEntity( target_type ) ); 00319 const EntityHandle* iter = std::find( this_vertices, ( this_vertices + num_corner_verts ), vertex_list[0] ); 00320 if( iter == ( this_vertices + num_corner_verts ) ) return false; 00321 00322 // now lets do connectivity matching 00323 bool they_match = true; 00324 00325 // line up our vectors 00326 int i; 00327 int offset = iter - this_vertices; 00328 00329 // first compare forward 00330 for( i = 1; i < num_corner_verts; ++i ) 00331 { 00332 if( i >= vertex_list_size ) 00333 { 00334 they_match = false; 00335 break; 00336 } 00337 00338 if( vertex_list[i] != this_vertices[( offset + i ) % num_corner_verts] ) 00339 { 00340 they_match = false; 00341 break; 00342 } 00343 } 00344 00345 if( they_match == true ) return true; 00346 00347 they_match = true; 00348 00349 // then compare reverse 00350 // offset iter to avoid addition inside loop; this just makes sure we don't 00351 // go off beginning of this_vertices with an index < 0 00352 offset += num_corner_verts; 00353 for( i = 1; i < num_corner_verts; i++ ) 00354 { 00355 if( vertex_list[i] != this_vertices[( offset - i ) % num_corner_verts] ) 00356 { 00357 they_match = false; 00358 break; 00359 } 00360 } 00361 return they_match; 00362 } 00363 00364 //! add an adjacency from from_ent to to_ent; if both_ways is true, add one 00365 //! in reverse too 00366 //! NOTE: this function is defined even though we may only be implementing 00367 //! vertex-based up-adjacencies 00368 ErrorCode AEntityFactory::add_adjacency( EntityHandle from_ent, EntityHandle to_ent, const bool both_ways ) 00369 { 00370 EntityType to_type = TYPE_FROM_HANDLE( to_ent ); 00371 00372 if( to_type == MBVERTEX ) return MB_ALREADY_ALLOCATED; 00373 00374 AdjacencyVector* adj_list_ptr = NULL; 00375 ErrorCode result = get_adjacencies( from_ent, adj_list_ptr, true ); 00376 if( MB_SUCCESS != result ) return result; 00377 00378 // get an iterator to the right spot in this sorted vector 00379 AdjacencyVector::iterator adj_iter; 00380 if( !adj_list_ptr->empty() ) 00381 { 00382 adj_iter = std::lower_bound( adj_list_ptr->begin(), adj_list_ptr->end(), to_ent ); 00383 00384 if( adj_iter == adj_list_ptr->end() || to_ent != *adj_iter ) 00385 { 00386 adj_list_ptr->insert( adj_iter, to_ent ); 00387 } 00388 } 00389 else 00390 adj_list_ptr->push_back( to_ent ); 00391 00392 // if both_ways is true, recursively call this function 00393 if( true == both_ways && to_type != MBVERTEX ) result = add_adjacency( to_ent, from_ent, false ); 00394 00395 return result; 00396 } 00397 00398 //! remove an adjacency from from the base_entity. 00399 ErrorCode AEntityFactory::remove_adjacency( EntityHandle base_entity, EntityHandle adj_to_remove ) 00400 { 00401 ErrorCode result; 00402 00403 if( TYPE_FROM_HANDLE( base_entity ) == MBENTITYSET ) 00404 return thisMB->remove_entities( base_entity, &adj_to_remove, 1 ); 00405 00406 // get the adjacency tag 00407 AdjacencyVector* adj_list = NULL; 00408 result = get_adjacencies( base_entity, adj_list ); 00409 if( adj_list == NULL || MB_SUCCESS != result ) return result; 00410 00411 // remove the specified entity from the adjacency list and truncate 00412 // the list to the new length 00413 adj_list->erase( std::remove( adj_list->begin(), adj_list->end(), adj_to_remove ), adj_list->end() ); 00414 00415 return result; 00416 } 00417 00418 //! remove all adjacencies from from the base_entity. 00419 ErrorCode AEntityFactory::remove_all_adjacencies( EntityHandle base_entity, const bool delete_adj_list ) 00420 { 00421 ErrorCode result; 00422 EntityType base_type = TYPE_FROM_HANDLE( base_entity ); 00423 00424 if( base_type == MBENTITYSET ) return thisMB->clear_meshset( &base_entity, 1 ); 00425 const int base_ent_dim = CN::Dimension( base_type ); 00426 00427 // Remove adjacencies from element vertices back to 00428 // this element. Also check any elements adjacent 00429 // to the vertex and of higher dimension than this 00430 // element for downward adjacencies to this element. 00431 if( vert_elem_adjacencies() && base_type != MBVERTEX ) 00432 { 00433 EntityHandle const *connvect = 0, *adjvect = 0; 00434 int numconn = 0, numadj = 0; 00435 std::vector< EntityHandle > connstorage; 00436 result = get_vertices( base_entity, connvect, numconn, connstorage ); 00437 if( MB_SUCCESS != result ) return result; 00438 00439 for( int i = 0; i < numconn; ++i ) 00440 { 00441 result = get_adjacencies( connvect[i], adjvect, numadj ); 00442 if( MB_SUCCESS != result ) return result; 00443 00444 bool remove_this = false; 00445 for( int j = 0; j < numadj; ++j ) 00446 { 00447 if( adjvect[j] == base_entity ) remove_this = true; 00448 00449 if( CN::Dimension( TYPE_FROM_HANDLE( adjvect[j] ) ) != base_ent_dim && 00450 explicitly_adjacent( adjvect[j], base_entity ) ) 00451 remove_adjacency( adjvect[j], base_entity ); 00452 } 00453 00454 if( remove_this ) remove_adjacency( connvect[i], base_entity ); 00455 } 00456 } 00457 00458 // get the adjacency tag 00459 AdjacencyVector* adj_list = 0; 00460 result = get_adjacencies( base_entity, adj_list ); 00461 if( MB_SUCCESS != result || !adj_list ) return result; 00462 00463 // check adjacent entities for references back to this entity 00464 for( AdjacencyVector::reverse_iterator it = adj_list->rbegin(); it != adj_list->rend(); ++it ) 00465 remove_adjacency( *it, base_entity ); 00466 00467 if( delete_adj_list ) 00468 result = set_adjacency_ptr( base_entity, NULL ); 00469 else 00470 adj_list->clear(); 00471 00472 return MB_SUCCESS; 00473 } 00474 00475 ErrorCode AEntityFactory::create_vert_elem_adjacencies() 00476 { 00477 00478 mVertElemAdj = true; 00479 00480 EntityType ent_type; 00481 Range::iterator i_range; 00482 const EntityHandle* connectivity; 00483 std::vector< EntityHandle > aux_connect; 00484 int number_nodes; 00485 ErrorCode result; 00486 Range handle_range; 00487 00488 // 1. over all element types, for each element, create vertex-element adjacencies 00489 for( ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++ ) 00490 { 00491 handle_range.clear(); 00492 00493 // get this type of entity 00494 result = thisMB->get_entities_by_type( 0, ent_type, handle_range ); 00495 if( result != MB_SUCCESS ) return result; 00496 00497 for( i_range = handle_range.begin(); i_range != handle_range.end(); ++i_range ) 00498 { 00499 result = get_vertices( *i_range, connectivity, number_nodes, aux_connect ); 00500 if( MB_SUCCESS != result ) return result; 00501 00502 // add the adjacency 00503 for( int k = 0; k < number_nodes; k++ ) 00504 if( ( result = add_adjacency( connectivity[k], *i_range ) ) != MB_SUCCESS ) return result; 00505 } 00506 } 00507 00508 return MB_SUCCESS; 00509 } 00510 00511 ErrorCode AEntityFactory::get_adjacencies( EntityHandle entity, 00512 const EntityHandle*& adjacent_entities, 00513 int& num_entities ) const 00514 { 00515 AdjacencyVector const* vec_ptr = 0; 00516 ErrorCode result = get_adjacency_ptr( entity, vec_ptr ); 00517 if( MB_SUCCESS != result || !vec_ptr ) 00518 { 00519 adjacent_entities = 0; 00520 num_entities = 0; 00521 return result; 00522 } 00523 00524 num_entities = vec_ptr->size(); 00525 adjacent_entities = ( vec_ptr->empty() ) ? NULL : &( ( *vec_ptr )[0] ); 00526 return MB_SUCCESS; 00527 } 00528 00529 ErrorCode AEntityFactory::get_adjacencies( EntityHandle entity, std::vector< EntityHandle >& adjacent_entities ) const 00530 { 00531 AdjacencyVector const* vec_ptr = 0; 00532 ErrorCode result = get_adjacency_ptr( entity, vec_ptr ); 00533 if( MB_SUCCESS != result || !vec_ptr ) 00534 { 00535 adjacent_entities.clear(); 00536 return result; 00537 } 00538 00539 adjacent_entities = *vec_ptr; 00540 return MB_SUCCESS; 00541 } 00542 00543 ErrorCode AEntityFactory::get_adjacencies( EntityHandle entity, std::vector< EntityHandle >*& adj_vec, bool create ) 00544 { 00545 adj_vec = 0; 00546 ErrorCode result = get_adjacency_ptr( entity, adj_vec ); 00547 if( MB_SUCCESS == result && !adj_vec && create ) 00548 { 00549 adj_vec = new AdjacencyVector; 00550 result = set_adjacency_ptr( entity, adj_vec ); 00551 if( MB_SUCCESS != result ) 00552 { 00553 delete adj_vec; 00554 adj_vec = 0; 00555 } 00556 } 00557 return result; 00558 } 00559 00560 ErrorCode AEntityFactory::get_adjacencies( const EntityHandle source_entity, 00561 const unsigned int target_dimension, 00562 bool create_if_missing, 00563 std::vector< EntityHandle >& target_entities ) 00564 { 00565 const EntityType source_type = TYPE_FROM_HANDLE( source_entity ); 00566 const unsigned source_dimension = CN::Dimension( source_type ); 00567 00568 ErrorCode result; 00569 if( target_dimension == 4 ) 00570 { // get meshsets 'source' is in 00571 result = get_associated_meshsets( source_entity, target_entities ); 00572 } 00573 else if( target_dimension == ( source_type != MBPOLYHEDRON ? 0 : 2 ) ) 00574 { 00575 std::vector< EntityHandle > tmp_storage; 00576 const EntityHandle* conn = NULL; 00577 int len = 0; 00578 result = thisMB->get_connectivity( source_entity, conn, len, false, &tmp_storage ); 00579 target_entities.insert( target_entities.end(), conn, conn + len ); 00580 } 00581 else if( target_dimension == 0 && source_type == MBPOLYHEDRON ) 00582 { 00583 result = get_polyhedron_vertices( source_entity, target_entities ); 00584 } 00585 else if( source_dimension == target_dimension ) 00586 { 00587 target_entities.push_back( source_entity ); 00588 result = MB_SUCCESS; 00589 } 00590 else 00591 { 00592 if( mVertElemAdj == false ) 00593 { 00594 result = create_vert_elem_adjacencies(); 00595 if( MB_SUCCESS != result ) return result; 00596 } 00597 00598 if( source_dimension == 0 ) 00599 { 00600 result = get_zero_to_n_elements( source_entity, target_dimension, target_entities, create_if_missing ); 00601 } 00602 else if( source_dimension > target_dimension ) 00603 { 00604 result = get_down_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing ); 00605 } 00606 else // if(source_dimension < target_dimension) 00607 { 00608 result = get_up_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing ); 00609 } 00610 } 00611 00612 return result; 00613 } 00614 00615 ErrorCode AEntityFactory::notify_create_entity( const EntityHandle entity, 00616 const EntityHandle* node_array, 00617 const int number_nodes ) 00618 { 00619 ErrorCode result = MB_SUCCESS, tmp_result; 00620 if( vert_elem_adjacencies() ) 00621 { 00622 // iterate through nodes and add adjacency information 00623 if( TYPE_FROM_HANDLE( entity ) == MBPOLYHEDRON ) 00624 { 00625 // polyhedron - get real vertex connectivity 00626 std::vector< EntityHandle > verts; 00627 tmp_result = get_adjacencies( entity, 0, false, verts ); 00628 if( MB_SUCCESS != tmp_result ) return tmp_result; 00629 for( std::vector< EntityHandle >::iterator vit = verts.begin(); vit != verts.end(); ++vit ) 00630 { 00631 tmp_result = add_adjacency( *vit, entity ); 00632 if( MB_SUCCESS != tmp_result ) result = tmp_result; 00633 } 00634 } 00635 else 00636 { 00637 for( unsigned int i = number_nodes; i--; ) 00638 { 00639 tmp_result = add_adjacency( node_array[i], entity ); 00640 if( MB_SUCCESS != tmp_result ) result = tmp_result; 00641 } 00642 } 00643 } 00644 00645 return result; 00646 } 00647 00648 ErrorCode AEntityFactory::get_zero_to_n_elements( EntityHandle source_entity, 00649 const unsigned int target_dimension, 00650 std::vector< EntityHandle >& target_entities, 00651 const bool create_if_missing, 00652 const int /*create_adjacency_option = -1*/ ) 00653 { 00654 AdjacencyVector::iterator start_ent, end_ent; 00655 00656 // get the adjacency vector 00657 AdjacencyVector* adj_vec = NULL; 00658 ErrorCode result = get_adjacencies( source_entity, adj_vec ); 00659 if( result != MB_SUCCESS || adj_vec == NULL ) return result; 00660 00661 if( target_dimension < 3 && create_if_missing ) 00662 { 00663 std::vector< EntityHandle > tmp_ents; 00664 00665 start_ent = std::lower_bound( adj_vec->begin(), adj_vec->end(), 00666 FIRST_HANDLE( CN::TypeDimensionMap[target_dimension + 1].first ) ); 00667 00668 end_ent = std::lower_bound( start_ent, adj_vec->end(), LAST_HANDLE( CN::TypeDimensionMap[3].second ) ); 00669 00670 std::vector< EntityHandle > elems( start_ent, end_ent ); 00671 00672 // make target_dimension elements from all adjacient higher-dimension elements 00673 for( start_ent = elems.begin(); start_ent != elems.end(); ++start_ent ) 00674 { 00675 tmp_ents.clear(); 00676 get_down_adjacency_elements( *start_ent, target_dimension, tmp_ents, create_if_missing, 0 ); 00677 } 00678 } 00679 00680 DimensionPair dim_pair = CN::TypeDimensionMap[target_dimension]; 00681 start_ent = std::lower_bound( adj_vec->begin(), adj_vec->end(), FIRST_HANDLE( dim_pair.first ) ); 00682 end_ent = std::lower_bound( start_ent, adj_vec->end(), LAST_HANDLE( dim_pair.second ) ); 00683 target_entities.insert( target_entities.end(), start_ent, end_ent ); 00684 return MB_SUCCESS; 00685 } 00686 00687 ErrorCode AEntityFactory::get_down_adjacency_elements( EntityHandle source_entity, 00688 const unsigned int target_dimension, 00689 std::vector< EntityHandle >& target_entities, 00690 const bool create_if_missing, 00691 const int create_adjacency_option ) 00692 { 00693 00694 EntityType source_type = TYPE_FROM_HANDLE( source_entity ); 00695 00696 if( source_type == MBPOLYHEDRON || source_type == MBPOLYGON ) 00697 return get_down_adjacency_elements_poly( source_entity, target_dimension, target_entities, create_if_missing, 00698 create_adjacency_option ); 00699 00700 // make this a fixed size to avoid cost of working with STL vectors 00701 EntityHandle vertex_array[27] = {}; 00702 ErrorCode temp_result; 00703 00704 const EntityHandle* vertices = NULL; 00705 int num_verts = 0; 00706 00707 // I know there are already vertex adjacencies for this - call 00708 // another function to get them 00709 std::vector< EntityHandle > storage; 00710 ErrorCode result = thisMB->get_connectivity( source_entity, vertices, num_verts, false, &storage ); 00711 if( MB_SUCCESS != result ) return result; 00712 00713 int has_mid_nodes[4]; 00714 CN::HasMidNodes( source_type, num_verts, has_mid_nodes ); 00715 00716 std::vector< int > index_list; 00717 int num_sub_ents = CN::NumSubEntities( source_type, target_dimension ); 00718 00719 for( int j = 0; j < num_sub_ents; j++ ) 00720 { 00721 const CN::ConnMap& cmap = CN::mConnectivityMap[source_type][target_dimension - 1]; 00722 00723 int verts_per_sub = cmap.num_corners_per_sub_element[j]; 00724 00725 // get the corner vertices 00726 for( int i = 0; i < verts_per_sub; i++ ) 00727 vertex_array[i] = vertices[cmap.conn[j][i]]; 00728 00729 // get the ho nodes for sub-subfacets 00730 if( has_mid_nodes[1] && target_dimension > 1 ) 00731 { 00732 // has edge mid-nodes; for each edge, get the right mid-node and put in vertices 00733 // first get the edge indices 00734 index_list.clear(); 00735 int int_result = CN::AdjacentSubEntities( source_type, &j, 1, target_dimension, 1, index_list ); 00736 if( 0 != int_result ) return MB_FAILURE; 00737 for( unsigned int k = 0; k < index_list.size(); k++ ) 00738 { 00739 int tmp_index = CN::HONodeIndex( source_type, num_verts, 1, index_list[k] ); 00740 if( tmp_index >= (int)num_verts ) return MB_INDEX_OUT_OF_RANGE; 00741 00742 // put this vertex on the end; reuse verts_per_sub as an index 00743 vertex_array[verts_per_sub++] = vertices[tmp_index]; 00744 } 00745 } 00746 // get the ho nodes for the target dimension 00747 if( has_mid_nodes[target_dimension] ) 00748 { 00749 // get the ho node index for this subfacet 00750 int tmp_index = CN::HONodeIndex( source_type, num_verts, target_dimension, j ); 00751 if( tmp_index >= num_verts ) return MB_INDEX_OUT_OF_RANGE; 00752 vertex_array[verts_per_sub++] = vertices[tmp_index]; 00753 } 00754 00755 EntityHandle tmp_target = 0; 00756 temp_result = get_element( vertex_array, verts_per_sub, cmap.target_type[j], tmp_target, create_if_missing, 00757 source_entity, create_adjacency_option ); 00758 00759 if( temp_result != MB_SUCCESS ) 00760 result = temp_result; 00761 else if( 0 != tmp_target ) 00762 target_entities.push_back( tmp_target ); 00763 00764 // make sure we're not writing past the end of our fixed-size array 00765 if( verts_per_sub > 27 ) return MB_INDEX_OUT_OF_RANGE; 00766 } 00767 00768 return result; 00769 } 00770 00771 ErrorCode AEntityFactory::get_down_adjacency_elements_poly( EntityHandle source_entity, 00772 const unsigned int target_dimension, 00773 std::vector< EntityHandle >& target_entities, 00774 const bool create_if_missing, 00775 const int /*create_adjacency_option*/ ) 00776 { 00777 00778 EntityType source_type = TYPE_FROM_HANDLE( source_entity ); 00779 00780 if( !( source_type == MBPOLYHEDRON && target_dimension > 0 && target_dimension < 3 ) && 00781 !( source_type == MBPOLYGON && target_dimension == 1 ) ) 00782 return MB_TYPE_OUT_OF_RANGE; 00783 00784 // make this a fixed size to avoid cost of working with STL vectors 00785 std::vector< EntityHandle > vertex_array; 00786 00787 // I know there are already vertex adjacencies for this - call 00788 // another function to get them 00789 ErrorCode result = get_adjacencies( source_entity, 0, false, vertex_array ); 00790 if( MB_SUCCESS != result ) return result; 00791 00792 ErrorCode tmp_result; 00793 if( source_type == MBPOLYGON ) 00794 { 00795 result = MB_SUCCESS; 00796 // put the first vertex on the end so we have a ring 00797 vertex_array.push_back( *vertex_array.begin() ); 00798 for( unsigned int i = 0; i < vertex_array.size() - 1; i++ ) 00799 { 00800 Range vrange, adj_edges; 00801 vrange.insert( vertex_array[i] ); 00802 vrange.insert( vertex_array[i + 1] ); 00803 // account for padded polygons; if the vertices are the same, skip 00804 if( vrange.size() == 1 ) continue; 00805 tmp_result = thisMB->get_adjacencies( vrange, 1, false, adj_edges ); 00806 if( MB_SUCCESS != tmp_result ) result = tmp_result; 00807 if( adj_edges.size() == 1 ) 00808 { 00809 // single edge - don't check adjacencies 00810 target_entities.push_back( *adj_edges.begin() ); 00811 } 00812 else if( adj_edges.size() != 0 ) 00813 { 00814 // multiple ones - need to check for explicit adjacencies 00815 unsigned int start_sz = target_entities.size(); 00816 const EntityHandle* explicit_adjs; 00817 int num_exp; 00818 for( Range::iterator rit = adj_edges.begin(); rit != adj_edges.end(); ++rit ) 00819 { 00820 // TODO check return value 00821 this->get_adjacencies( *rit, explicit_adjs, num_exp ); 00822 if( NULL != explicit_adjs && 00823 std::find( explicit_adjs, explicit_adjs + num_exp, source_entity ) != explicit_adjs + num_exp ) 00824 target_entities.push_back( *rit ); 00825 } 00826 if( target_entities.size() == start_sz ) 00827 { 00828 result = MB_MULTIPLE_ENTITIES_FOUND; 00829 target_entities.push_back( *adj_edges.begin() ); 00830 } 00831 } 00832 else 00833 { 00834 // we have no adjacent edge yet; we need to create one and also add 00835 // them to the adjacency of the vertices 00836 if( create_if_missing ) 00837 { 00838 EntityHandle newEdge; 00839 EntityHandle v[2] = { vertex_array[i], vertex_array[i + 1] }; 00840 result = thisMB->create_element( MBEDGE, v, 2, newEdge ); 00841 if( MB_SUCCESS != result ) return result; 00842 // we also need to add explicit adjacency, so next time we do not 00843 // create again (because we do not find the edge if it is not adjacent to the 00844 // vertices 00845 // if (create_adjacency_option >= 0) 00846 //{ 00847 result = add_adjacency( v[0], newEdge ); 00848 if( MB_SUCCESS != result ) return result; 00849 result = add_adjacency( v[1], newEdge ); 00850 if( MB_SUCCESS != result ) return result; 00851 target_entities.push_back( newEdge ); 00852 //} 00853 } 00854 } 00855 } 00856 return result; 00857 } 00858 00859 else 00860 { 00861 if( target_dimension == 2 ) 00862 { 00863 result = thisMB->get_connectivity( &source_entity, 1, target_entities ); 00864 } 00865 else 00866 { 00867 std::vector< EntityHandle > dum_vec; 00868 result = thisMB->get_connectivity( &source_entity, 1, dum_vec ); 00869 if( MB_SUCCESS != result ) return result; 00870 result = thisMB->get_adjacencies( &dum_vec[0], dum_vec.size(), 1, create_if_missing, target_entities, 00871 Interface::UNION ); 00872 return result; 00873 } 00874 } 00875 00876 return MB_SUCCESS; 00877 } 00878 00879 #if 0 00880 // Do in-place set intersect of two *sorted* containers. 00881 // First container is modifed. Second is not. 00882 // First container must allow assignment through iterators (in practice, 00883 // must be a container that does not enforce ordering, such 00884 // as std::vector, std::list, or a c-style array) 00885 template <typename T1, typename T2> 00886 static inline T1 intersect( T1 set1_begin, T1 set1_end, 00887 T2 set2_begin, T2 set2_end ) 00888 { 00889 T1 set1_write = set1_begin; 00890 while (set1_begin != set1_end) { 00891 if (set2_begin == set2_end) 00892 return set1_write; 00893 while (*set2_begin < *set1_begin) 00894 if (++set2_begin == set2_end) 00895 return set1_write; 00896 if (!(*set1_begin < *set2_begin)) { 00897 *set1_write = *set1_begin; 00898 ++set1_write; 00899 ++set2_begin; 00900 } 00901 ++set1_begin; 00902 } 00903 return set1_write; 00904 } 00905 00906 00907 ErrorCode AEntityFactory::get_up_adjacency_elements( 00908 EntityHandle source_entity, 00909 const unsigned int target_dimension, 00910 std::vector<EntityHandle>& target_entities, 00911 const bool create_if_missing, 00912 const int option ) 00913 { 00914 ErrorCode rval; 00915 const std::vector<EntityHandle> *vtx_adj, *vtx2_adj; 00916 std::vector<EntityHandle> duplicates; 00917 00918 // Handle ranges 00919 const size_t in_size = target_entities.size(); 00920 const EntityType src_type = TYPE_FROM_HANDLE(source_entity); 00921 DimensionPair target_types = CN::TypeDimensionMap[target_dimension]; 00922 const EntityHandle src_beg_handle = CREATE_HANDLE( src_type, 0 ); 00923 const EntityHandle src_end_handle = CREATE_HANDLE( src_type+1, 0 ); 00924 const EntityHandle tgt_beg_handle = CREATE_HANDLE( target_types.first, 0 ); 00925 const EntityHandle tgt_end_handle = CREATE_HANDLE( target_types.second+1, 0 ); 00926 00927 // get vertices 00928 assert(TYPE_FROM_HANDLE(source_entity) != MBPOLYHEDRON); // can't go up from a region 00929 std::vector<EntityHandle> conn_storage; 00930 const EntityHandle* conn; 00931 int conn_len; 00932 rval = thisMB->get_connectivity( source_entity, conn, conn_len, true, &conn_storage ); 00933 if (MB_SUCCESS != rval) 00934 return rval; 00935 00936 // shouldn't be here if source entity is not an element 00937 assert(conn_len > 1); 00938 00939 // create necessary entities. this only makes sense if there exists of a 00940 // dimension greater than the target dimension. 00941 if (create_if_missing && target_dimension < 3 && CN::Dimension(src_type) < 2) { 00942 for (size_t i = 0; i < conn_len; ++i) { 00943 rval = get_adjacency_ptr( conn[i], vtx_adj ); 00944 if (MB_SUCCESS != rval) 00945 return rval; 00946 assert(vtx_adj != NULL); // should contain at least source_entity 00947 00948 std::vector<EntityHandle> tmp2, tmp(*vtx_adj); // copy in case adjacency vector is changed 00949 for (size_t j = 0; j < tmp.size(); ++j) { 00950 if (CN::Dimension(TYPE_FROM_HANDLE(tmp[j])) <= (int)target_dimension) 00951 continue; 00952 if (TYPE_FROM_HANDLE(tmp[j]) == MBENTITYSET) 00953 break; 00954 00955 tmp2.clear(); 00956 rval = get_down_adjacency_elements( tmp[j], target_dimension, tmp2, true, option ); 00957 if (MB_SUCCESS != rval) 00958 return rval; 00959 } 00960 } 00961 } 00962 00963 // get elements adjacent to first vertex 00964 rval = get_adjacency_ptr( conn[0], vtx_adj ); 00965 if (MB_SUCCESS != rval) 00966 return rval; 00967 assert(vtx_adj != NULL); // should contain at least source_entity 00968 // get elements adjacent to second vertex 00969 rval = get_adjacency_ptr( conn[1], vtx2_adj ); 00970 if (MB_SUCCESS != rval) 00971 return rval; 00972 assert(vtx2_adj != NULL); 00973 00974 // Put intersect of all entities except source entity with 00975 // the same type as the source entity in 'duplicates' 00976 std::vector<EntityHandle>::const_iterator it1, it2, end1, end2; 00977 it1 = std::lower_bound( vtx_adj->begin(), vtx_adj->end(), src_beg_handle ); 00978 it2 = std::lower_bound( vtx2_adj->begin(), vtx2_adj->end(), src_beg_handle ); 00979 end1 = std::lower_bound( it1, vtx_adj->end(), src_end_handle ); 00980 end2 = std::lower_bound( it2, vtx2_adj->end(), src_end_handle ); 00981 assert(end1 != it1); // should at least contain source entity 00982 duplicates.resize( end1 - it1 - 1 ); 00983 std::vector<EntityHandle>::iterator ins = duplicates.begin(); 00984 for (; it1 != end1; ++it1) { 00985 if (*it1 != source_entity) { 00986 *ins = *it1; 00987 ++ins; 00988 } 00989 } 00990 duplicates.erase( intersect( duplicates.begin(), duplicates.end(), it2, end2 ), duplicates.end() ); 00991 00992 // Append to input list any entities of the desired target dimension 00993 it1 = std::lower_bound( end1, vtx_adj->end(), tgt_beg_handle ); 00994 it2 = std::lower_bound( end2, vtx2_adj->end(), tgt_beg_handle ); 00995 end1 = std::lower_bound( it1, vtx_adj->end(), tgt_end_handle ); 00996 end2 = std::lower_bound( it2, vtx2_adj->end(), tgt_end_handle ); 00997 std::set_intersection( it1, end1, it2, end2, std::back_inserter( target_entities ) ); 00998 00999 // for each additional vertex 01000 for (int i = 2; i < conn_len; ++i) { 01001 rval = get_adjacency_ptr( conn[i], vtx_adj ); 01002 if (MB_SUCCESS != rval) 01003 return rval; 01004 assert(vtx_adj != NULL); // should contain at least source_entity 01005 01006 it1 = std::lower_bound( vtx_adj->begin(), vtx_adj->end(), src_beg_handle ); 01007 end1 = std::lower_bound( it1, vtx_adj->end(), src_end_handle ); 01008 duplicates.erase( intersect( duplicates.begin(), duplicates.end(), it1, end1 ), duplicates.end() ); 01009 01010 it1 = std::lower_bound( end1, vtx_adj->end(), tgt_beg_handle ); 01011 end1 = std::lower_bound( it1, vtx_adj->end(), tgt_end_handle ); 01012 target_entities.erase( intersect( target_entities.begin()+in_size, target_entities.end(), 01013 it1, end1 ), target_entities.end() ); 01014 } 01015 01016 // if no duplicates, we're done 01017 if (duplicates.empty()) 01018 return MB_SUCCESS; 01019 01020 // Check for explicit adjacencies. If an explicit adjacency 01021 // connects candidate target entity to an entity equivalent 01022 // to the source entity, then assume that source entity is *not* 01023 // adjacent 01024 const std::vector<EntityHandle>* adj_ptr; 01025 // check adjacencies from duplicate entities to candidate targets 01026 for (size_t i = 0; i < duplicates.size(); ++i) { 01027 rval = get_adjacency_ptr( duplicates[i], adj_ptr ); 01028 if (MB_SUCCESS != rval) 01029 return rval; 01030 if (!adj_ptr) 01031 continue; 01032 01033 for (size_t j = 0; j < adj_ptr->size(); ++j) { 01034 std::vector<EntityHandle>::iterator k = 01035 std::find( target_entities.begin()+in_size, target_entities.end(), (*adj_ptr)[j] ); 01036 if (k != target_entities.end()) 01037 target_entities.erase(k); 01038 } 01039 } 01040 01041 // If target dimension is 3 and source dimension is 1, also need to 01042 // check for explicit adjacencies to intermediate faces 01043 if (CN::Dimension(src_type) > 1 || target_dimension < 3) 01044 return MB_SUCCESS; 01045 01046 // Get faces adjacent to each element and check for explict 01047 // adjacencies from duplicate entities to faces 01048 for (size_t i = 0; i < duplicates.size(); ++i) { 01049 rval = get_adjacency_ptr( duplicates[i], adj_ptr ); 01050 if (MB_SUCCESS != rval) 01051 return rval; 01052 if (!adj_ptr) 01053 continue; 01054 01055 size_t j; 01056 for (j = 0; j < adj_ptr->size(); ++j) { 01057 const std::vector<EntityHandle>* adj_ptr2; 01058 rval = get_adjacency_ptr( (*adj_ptr)[j], adj_ptr2 ); 01059 if (MB_SUCCESS != rval) 01060 return rval; 01061 if (!adj_ptr2) 01062 continue; 01063 01064 for (size_t k = 0; k < adj_ptr2->size(); ++k) { 01065 std::vector<EntityHandle>::iterator it; 01066 it = std::find( target_entities.begin()+in_size, target_entities.end(), (*adj_ptr2)[k] ); 01067 if (it != target_entities.end()) { 01068 target_entities.erase(it); 01069 j = adj_ptr->size(); // break outer loop 01070 break; 01071 } 01072 } 01073 } 01074 } 01075 01076 return MB_SUCCESS; 01077 } 01078 #else 01079 ErrorCode AEntityFactory::get_up_adjacency_elements( EntityHandle source_entity, 01080 const unsigned int target_dimension, 01081 std::vector< EntityHandle >& target_entities, 01082 const bool create_if_missing, 01083 const int /*create_adjacency_option = -1*/ ) 01084 { 01085 01086 EntityType source_type = TYPE_FROM_HANDLE( source_entity ); 01087 01088 const EntityHandle* source_vertices = NULL; 01089 int num_source_vertices = 0; 01090 std::vector< EntityHandle > conn_storage; 01091 01092 // check to see whether there are any equivalent entities (same verts, different entity); 01093 // do this by calling get_element with a 0 source_entity, and look for a 01094 // MB_MULTIPLE_ENTITIES_FOUND return code 01095 01096 // NOTE: we only want corner vertices here, and for the code below which also uses 01097 // source_vertices 01098 ErrorCode result = 01099 thisMB->get_connectivity( source_entity, source_vertices, num_source_vertices, true, &conn_storage ); 01100 if( MB_SUCCESS != result ) return result; 01101 EntityHandle temp_entity; 01102 result = get_element( source_vertices, num_source_vertices, source_type, temp_entity, false, 0 ); 01103 01104 bool equiv_entities = ( result == MB_MULTIPLE_ENTITIES_FOUND ) ? true : false; 01105 01106 std::vector< EntityHandle > tmp_vec; 01107 if( !equiv_entities ) 01108 { 01109 // get elems adjacent to each node 01110 std::vector< std::vector< EntityHandle > > elems( num_source_vertices ); 01111 int i; 01112 for( i = 0; i < num_source_vertices; i++ ) 01113 { 01114 // get elements 01115 // see comment above pertaining to source_vertices; these are corner vertices only 01116 get_zero_to_n_elements( source_vertices[i], target_dimension, elems[i], create_if_missing, 0 ); 01117 // sort this element list 01118 std::sort( elems[i].begin(), elems[i].end() ); 01119 } 01120 01121 // perform an intersection between all the element lists 01122 // see comment above pertaining to source_vertices; these are corner vertices only 01123 for( i = 1; i < num_source_vertices; i++ ) 01124 { 01125 tmp_vec.clear(); 01126 01127 // intersection between first list and ith list, put result in tmp 01128 std::set_intersection( elems[0].begin(), elems[0].end(), elems[i].begin(), elems[i].end(), 01129 std::back_insert_iterator< std::vector< EntityHandle > >( tmp_vec ) ); 01130 // tmp has elems[0] contents and elems[0] contents has tmp's contents 01131 // so that elems[0] always has the intersection of previous operations 01132 elems[0].swap( tmp_vec ); 01133 } 01134 01135 // elems[0] contains the intersection, swap with target_entities 01136 target_entities.insert( target_entities.end(), elems[0].begin(), elems[0].end() ); 01137 } 01138 else if( source_type == MBPOLYGON ) 01139 { 01140 // get adjacencies using polyhedra's connectivity vectors 01141 // first get polyhedra neighboring vertices 01142 result = thisMB->get_adjacencies( source_vertices, num_source_vertices, 3, false, tmp_vec ); 01143 if( MB_SUCCESS != result ) return result; 01144 01145 // now filter according to whether each is adjacent to the polygon 01146 const EntityHandle* connect = NULL; 01147 int num_connect = 0; 01148 std::vector< EntityHandle > storage; 01149 for( unsigned int i = 0; i < tmp_vec.size(); i++ ) 01150 { 01151 result = thisMB->get_connectivity( tmp_vec[i], connect, num_connect, false, &storage ); 01152 if( MB_SUCCESS != result ) return result; 01153 if( std::find( connect, connect + num_connect, source_entity ) != connect + num_connect ) 01154 target_entities.push_back( tmp_vec[i] ); 01155 } 01156 } 01157 01158 else 01159 { 01160 // else get up-adjacencies directly; code copied from get_zero_to_n_elements 01161 01162 // get the adjacency vector 01163 AdjacencyVector* adj_vec = NULL; 01164 result = get_adjacencies( source_entity, adj_vec ); 01165 01166 if( result != MB_SUCCESS ) 01167 return result; 01168 else if( adj_vec == NULL ) 01169 return MB_SUCCESS; 01170 01171 DimensionPair dim_pair_dp1 = CN::TypeDimensionMap[CN::Dimension( source_type ) + 1], 01172 dim_pair_td = CN::TypeDimensionMap[target_dimension]; 01173 int dum; 01174 01175 Range tmp_ents, target_ents; 01176 01177 // get iterators for start handle of source_dim+1 and target_dim, and end handle 01178 // of target_dim 01179 AdjacencyVector::iterator start_ent_dp1 = 01180 std::lower_bound( adj_vec->begin(), adj_vec->end(), 01181 CREATE_HANDLE( dim_pair_dp1.first, MB_START_ID, dum ) ), 01182 01183 start_ent_td = 01184 std::lower_bound( adj_vec->begin(), adj_vec->end(), 01185 CREATE_HANDLE( dim_pair_td.first, MB_START_ID, dum ) ), 01186 01187 end_ent_td = std::lower_bound( adj_vec->begin(), adj_vec->end(), 01188 CREATE_HANDLE( dim_pair_td.second, MB_END_ID, dum ) ); 01189 01190 // get the adjacencies for source_dim+1 to target_dim-1, and the adjacencies from 01191 // those to target_dim 01192 std::copy( start_ent_dp1, start_ent_td, range_inserter( tmp_ents ) ); 01193 result = thisMB->get_adjacencies( tmp_ents, target_dimension, false, target_ents, Interface::UNION ); 01194 if( MB_SUCCESS != result ) return result; 01195 01196 // now copy the explicit adjacencies to target_dimension 01197 std::copy( start_ent_td, end_ent_td, range_inserter( target_ents ) ); 01198 01199 // now insert the whole thing into the argument vector 01200 #ifdef MOAB_NO_VECTOR_TEMPLATE_INSERT 01201 std::copy( target_ents.begin(), target_ents.end(), std::back_inserter( target_entities ) ); 01202 #else 01203 target_entities.insert( target_entities.end(), target_ents.begin(), target_ents.end() ); 01204 #endif 01205 } 01206 01207 return result; 01208 } 01209 #endif 01210 01211 ErrorCode AEntityFactory::notify_change_connectivity( EntityHandle entity, 01212 const EntityHandle* old_array, 01213 const EntityHandle* new_array, 01214 int number_verts ) 01215 { 01216 EntityType source_type = TYPE_FROM_HANDLE( entity ); 01217 if( source_type == MBPOLYHEDRON ) return MB_NOT_IMPLEMENTED; 01218 01219 // find out which ones to add and which to remove 01220 std::vector< EntityHandle > old_verts, new_verts; 01221 int i; 01222 for( i = 0; i < number_verts; i++ ) 01223 { 01224 if( old_array[i] != new_array[i] ) 01225 { 01226 old_verts.push_back( old_array[i] ); 01227 new_verts.push_back( new_array[i] ); 01228 } 01229 } 01230 01231 ErrorCode result; 01232 01233 if( mVertElemAdj == true ) 01234 { 01235 // update the vertex-entity adjacencies 01236 std::vector< EntityHandle >::iterator adj_iter; 01237 for( adj_iter = old_verts.begin(); adj_iter != old_verts.end(); ++adj_iter ) 01238 { 01239 if( std::find( new_verts.begin(), new_verts.end(), *adj_iter ) == new_verts.end() ) 01240 { 01241 result = remove_adjacency( *adj_iter, entity ); 01242 if( MB_SUCCESS != result ) return result; 01243 } 01244 } 01245 for( adj_iter = new_verts.begin(); adj_iter != new_verts.end(); ++adj_iter ) 01246 { 01247 if( std::find( old_verts.begin(), old_verts.end(), *adj_iter ) == old_verts.end() ) 01248 { 01249 result = add_adjacency( *adj_iter, entity ); 01250 if( MB_SUCCESS != result ) return result; 01251 } 01252 } 01253 } 01254 01255 return MB_SUCCESS; 01256 } 01257 01258 //! return true if 2 entities are explicitly adjacent 01259 bool AEntityFactory::explicitly_adjacent( const EntityHandle ent1, const EntityHandle ent2 ) 01260 { 01261 const EntityHandle* explicit_adjs; 01262 int num_exp; 01263 get_adjacencies( ent1, explicit_adjs, num_exp ); 01264 if( std::find( explicit_adjs, explicit_adjs + num_exp, ent2 ) != explicit_adjs + num_exp ) 01265 return true; 01266 else 01267 return false; 01268 } 01269 01270 ErrorCode AEntityFactory::merge_adjust_adjacencies( EntityHandle entity_to_keep, EntityHandle entity_to_remove ) 01271 { 01272 int ent_dim = CN::Dimension( TYPE_FROM_HANDLE( entity_to_keep ) ); 01273 ErrorCode result; 01274 01275 // check for newly-formed equivalent entities, and create explicit adjacencies 01276 // to distinguish them; this must be done before connectivity of higher-dimensional 01277 // entities is changed below, and only needs to be checked if merging vertices 01278 if( ent_dim == 0 ) 01279 { 01280 result = check_equiv_entities( entity_to_keep, entity_to_remove ); 01281 if( MB_SUCCESS != result ) return result; 01282 } 01283 01284 // check adjacencies TO removed entity 01285 for( int dim = 1; dim < ent_dim; dim++ ) 01286 { 01287 Range adjs; 01288 result = thisMB->get_adjacencies( &entity_to_remove, 1, dim, false, adjs ); 01289 if( result != MB_SUCCESS ) return result; 01290 // for any explicit ones, make them adjacent to keeper 01291 for( Range::iterator rit = adjs.begin(); rit != adjs.end(); ++rit ) 01292 { 01293 if( this->explicitly_adjacent( *rit, entity_to_remove ) ) 01294 { 01295 result = this->add_adjacency( *rit, entity_to_keep ); 01296 if( result != MB_SUCCESS ) return result; 01297 } 01298 } 01299 } 01300 01301 // check adjacencies FROM removed entity 01302 std::vector< EntityHandle > conn, adjs; 01303 result = this->get_adjacencies( entity_to_remove, adjs ); 01304 if( result != MB_SUCCESS ) return result; 01305 // set them all, and if to_entity is a set, add to that one too 01306 for( unsigned int i = 0; i < adjs.size(); i++ ) 01307 { 01308 if( TYPE_FROM_HANDLE( adjs[i] ) == MBENTITYSET ) 01309 { 01310 // result = this->add_adjacency(entity_to_keep, adjs[i]); 01311 // if(result != MB_SUCCESS) return result; 01312 // result = thisMB->add_entities(adjs[i], &entity_to_keep, 1); 01313 // if(result != MB_SUCCESS) return result; 01314 result = thisMB->replace_entities( adjs[i], &entity_to_remove, &entity_to_keep, 1 ); 01315 if( MB_SUCCESS != result ) return result; 01316 } 01317 else if( ent_dim == 0 ) 01318 { 01319 conn.clear(); 01320 result = thisMB->get_connectivity( &adjs[i], 1, conn ); 01321 01322 if( result == MB_SUCCESS ) 01323 { 01324 std::replace( conn.begin(), conn.end(), entity_to_remove, entity_to_keep ); 01325 result = thisMB->set_connectivity( adjs[i], &conn[0], conn.size() ); 01326 if( MB_SUCCESS != result ) return result; 01327 } 01328 else 01329 return result; 01330 } 01331 else 01332 { 01333 result = this->add_adjacency( entity_to_keep, adjs[i] ); 01334 if( result != MB_SUCCESS ) return result; 01335 } 01336 } 01337 01338 return MB_SUCCESS; 01339 } 01340 01341 // check for equivalent entities that may be formed when merging two entities, and 01342 // create explicit adjacencies accordingly 01343 ErrorCode AEntityFactory::check_equiv_entities( EntityHandle entity_to_keep, EntityHandle entity_to_remove ) 01344 { 01345 if( thisMB->dimension_from_handle( entity_to_keep ) > 0 ) return MB_SUCCESS; 01346 01347 // get all the adjacencies for both entities for all dimensions > 0 01348 Range adjs_keep, adjs_remove; 01349 ErrorCode result; 01350 01351 for( int dim = 1; dim <= 3; dim++ ) 01352 { 01353 result = thisMB->get_adjacencies( &entity_to_keep, 1, dim, false, adjs_keep, Interface::UNION ); 01354 if( MB_SUCCESS != result ) return result; 01355 result = thisMB->get_adjacencies( &entity_to_remove, 1, dim, false, adjs_remove, Interface::UNION ); 01356 if( MB_SUCCESS != result ) return result; 01357 } 01358 01359 // now look for equiv entities which will be formed 01360 // algorithm: 01361 // for each entity adjacent to removed entity: 01362 EntityHandle two_ents[2]; 01363 for( Range::iterator rit_rm = adjs_remove.begin(); rit_rm != adjs_remove.end(); ++rit_rm ) 01364 { 01365 two_ents[0] = *rit_rm; 01366 01367 // - for each entity of same dimension adjacent to kept entity: 01368 for( Range::iterator rit_kp = adjs_keep.begin(); rit_kp != adjs_keep.end(); ++rit_kp ) 01369 { 01370 if( TYPE_FROM_HANDLE( *rit_kp ) != TYPE_FROM_HANDLE( *rit_rm ) ) continue; 01371 01372 Range all_verts; 01373 two_ents[1] = *rit_kp; 01374 // . get union of adjacent vertices to two entities 01375 result = thisMB->get_adjacencies( two_ents, 2, 0, false, all_verts, Interface::UNION ); 01376 if( MB_SUCCESS != result ) return result; 01377 01378 assert( all_verts.find( entity_to_keep ) != all_verts.end() && 01379 all_verts.find( entity_to_remove ) != all_verts.end() ); 01380 01381 // . if # vertices != number of corner vertices + 1, continue 01382 if( CN::VerticesPerEntity( TYPE_FROM_HANDLE( *rit_rm ) ) + 1 != (int)all_verts.size() ) continue; 01383 01384 // . for the two entities adjacent to kept & removed entity: 01385 result = create_explicit_adjs( *rit_rm ); 01386 if( MB_SUCCESS != result ) return result; 01387 result = create_explicit_adjs( *rit_kp ); 01388 if( MB_SUCCESS != result ) return result; 01389 // . (end for) 01390 } 01391 // - (end for) 01392 } 01393 01394 return MB_SUCCESS; 01395 } 01396 01397 ErrorCode AEntityFactory::create_explicit_adjs( EntityHandle this_ent ) 01398 { 01399 // - get adjacent entities of next higher dimension 01400 Range all_adjs; 01401 ErrorCode result; 01402 result = thisMB->get_adjacencies( &this_ent, 1, thisMB->dimension_from_handle( this_ent ) + 1, false, all_adjs, 01403 Interface::UNION ); 01404 if( MB_SUCCESS != result ) return result; 01405 01406 // - create explicit adjacency to these entities 01407 for( Range::iterator rit = all_adjs.begin(); rit != all_adjs.end(); ++rit ) 01408 { 01409 result = add_adjacency( this_ent, *rit ); 01410 if( MB_SUCCESS != result ) return result; 01411 } 01412 01413 return MB_SUCCESS; 01414 } 01415 01416 ErrorCode AEntityFactory::get_adjacency_ptr( EntityHandle entity, std::vector< EntityHandle >*& ptr ) 01417 { 01418 ptr = 0; 01419 01420 EntitySequence* seq; 01421 ErrorCode rval = thisMB->sequence_manager()->find( entity, seq ); 01422 if( MB_SUCCESS != rval || !seq->data()->get_adjacency_data() ) return rval; 01423 01424 ptr = seq->data()->get_adjacency_data()[entity - seq->data()->start_handle()]; 01425 return MB_SUCCESS; 01426 } 01427 01428 ErrorCode AEntityFactory::get_adjacency_ptr( EntityHandle entity, const std::vector< EntityHandle >*& ptr ) const 01429 { 01430 ptr = 0; 01431 01432 EntitySequence* seq; 01433 ErrorCode rval = thisMB->sequence_manager()->find( entity, seq ); 01434 if( MB_SUCCESS != rval || !seq->data()->get_adjacency_data() ) return rval; 01435 01436 ptr = seq->data()->get_adjacency_data()[entity - seq->data()->start_handle()]; 01437 return MB_SUCCESS; 01438 } 01439 01440 ErrorCode AEntityFactory::set_adjacency_ptr( EntityHandle entity, std::vector< EntityHandle >* ptr ) 01441 { 01442 EntitySequence* seq; 01443 ErrorCode rval = thisMB->sequence_manager()->find( entity, seq ); 01444 if( MB_SUCCESS != rval ) return rval; 01445 01446 if( !seq->data()->get_adjacency_data() && !seq->data()->allocate_adjacency_data() ) 01447 return MB_MEMORY_ALLOCATION_FAILED; 01448 01449 const EntityHandle index = entity - seq->data()->start_handle(); 01450 std::vector< EntityHandle >*& ref = seq->data()->get_adjacency_data()[index]; 01451 delete ref; 01452 ref = ptr; 01453 return MB_SUCCESS; 01454 } 01455 01456 void AEntityFactory::get_memory_use( unsigned long long& entity_total, unsigned long long& memory_total ) 01457 { 01458 entity_total = memory_total = 0; 01459 01460 // iterate through each element type 01461 SequenceData* prev_data = 0; 01462 for( EntityType t = MBVERTEX; t != MBENTITYSET; t++ ) 01463 { 01464 TypeSequenceManager::iterator i; 01465 TypeSequenceManager& seqman = thisMB->sequence_manager()->entity_map( t ); 01466 for( i = seqman.begin(); i != seqman.end(); ++i ) 01467 { 01468 if( !( *i )->data()->get_adjacency_data() ) continue; 01469 01470 if( prev_data != ( *i )->data() ) 01471 { 01472 prev_data = ( *i )->data(); 01473 memory_total += prev_data->size() * sizeof( AdjacencyVector* ); 01474 } 01475 01476 const AdjacencyVector* vec; 01477 for( EntityHandle h = ( *i )->start_handle(); h <= ( *i )->end_handle(); ++h ) 01478 { 01479 get_adjacency_ptr( h, vec ); 01480 if( vec ) entity_total += vec->capacity() * sizeof( EntityHandle ) + sizeof( AdjacencyVector ); 01481 } 01482 } 01483 } 01484 01485 memory_total += sizeof( *this ) + entity_total; 01486 } 01487 01488 ErrorCode AEntityFactory::get_memory_use( const Range& ents_in, 01489 unsigned long long& min_per_ent, 01490 unsigned long long& amortized ) 01491 { 01492 min_per_ent = amortized = 0; 01493 SequenceData* prev_data = 0; 01494 RangeSeqIntersectIter iter( thisMB->sequence_manager() ); 01495 ErrorCode rval = iter.init( ents_in.begin(), ents_in.end() ); 01496 if( MB_SUCCESS != rval ) return rval; 01497 01498 do 01499 { 01500 AdjacencyVector** array = iter.get_sequence()->data()->get_adjacency_data(); 01501 if( !array ) continue; 01502 01503 EntityID count = iter.get_end_handle() - iter.get_start_handle() + 1; 01504 EntityID data_occ = thisMB->sequence_manager() 01505 ->entity_map( iter.get_sequence()->type() ) 01506 .get_occupied_size( iter.get_sequence()->data() ); 01507 01508 if( iter.get_sequence()->data() != prev_data ) 01509 { 01510 prev_data = iter.get_sequence()->data(); 01511 amortized += sizeof( AdjacencyVector* ) * iter.get_sequence()->data()->size() * count / data_occ; 01512 } 01513 01514 array += iter.get_start_handle() - iter.get_sequence()->data()->start_handle(); 01515 for( EntityID i = 0; i < count; ++i ) 01516 { 01517 if( array[i] ) min_per_ent += sizeof( EntityHandle ) * array[i]->capacity() + sizeof( AdjacencyVector ); 01518 } 01519 } while( MB_SUCCESS == ( rval = iter.step() ) ); 01520 01521 amortized += min_per_ent; 01522 return ( rval == MB_FAILURE ) ? MB_SUCCESS : rval; 01523 } 01524 01525 /*! 01526 calling code is notifying this that an entity is going to be deleted 01527 from the database 01528 */ 01529 ErrorCode AEntityFactory::notify_delete_entity( EntityHandle entity ) 01530 { 01531 if( TYPE_FROM_HANDLE( entity ) == MBVERTEX ) 01532 { 01533 std::vector< EntityHandle > adj_entities; 01534 for( int dim = 1; dim < 4; ++dim ) 01535 { 01536 ErrorCode rval = get_adjacencies( entity, dim, false, adj_entities ); 01537 if( rval != MB_SUCCESS && rval != MB_ENTITY_NOT_FOUND ) return rval; 01538 if( !adj_entities.empty() ) return MB_FAILURE; 01539 } 01540 } 01541 01542 // remove any references to this entity from other entities 01543 return remove_all_adjacencies( entity, true ); 01544 } 01545 01546 } // namespace moab