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