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