![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
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
00029 #include
00030 #include
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
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& target_entities,
00911 const bool create_if_missing,
00912 const int option )
00913 {
00914 ErrorCode rval;
00915 const std::vector *vtx_adj, *vtx2_adj;
00916 std::vector 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 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 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::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::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* 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::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* 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::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