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