moab
AEntityFactory.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines