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