Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
AEntityFactory.cpp
Go to the documentation of this file.
1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation. Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 #include "AEntityFactory.hpp"
17 #include "Internals.hpp"
18 #include "moab/Core.hpp"
19 #include "moab/Range.hpp"
20 #include "moab/Error.hpp"
21 #include "moab/CN.hpp"
22 #include "moab/MeshTopoUtil.hpp"
23 #include "EntitySequence.hpp"
24 #include "SequenceData.hpp"
25 #include "SequenceManager.hpp"
27 
28 #include <cassert>
29 #include <algorithm>
30 #include <set>
31 
32 namespace moab
33 {
34 
36  const EntityHandle*& vect_out,
37  int& count_out,
38  std::vector< EntityHandle >& storage )
39 {
40  ErrorCode result;
41  if( MBPOLYHEDRON == TYPE_FROM_HANDLE( h ) )
42  {
43  storage.clear();
44  result = thisMB->get_adjacencies( &h, 1, 0, false, storage );
45  vect_out = &storage[0];
46  count_out = storage.size();
47  }
48  else
49  {
50  result = thisMB->get_connectivity( h, vect_out, count_out, false, &storage );
51  }
52  return result;
53 }
54 
56 {
57  assert( NULL != mdb );
58  thisMB = mdb;
59  mVertElemAdj = false;
60 }
61 
63 {
64  // clean up all the adjacency information that was created
65  EntityType ent_type;
66 
67  // iterate through each element type
68  for( ent_type = MBVERTEX; ent_type <= MBENTITYSET; ent_type++ )
69  {
71  TypeSequenceManager& seqman = thisMB->sequence_manager()->entity_map( ent_type );
72  for( i = seqman.begin(); i != seqman.end(); ++i )
73  {
74  std::vector< EntityHandle >** adj_list = ( *i )->data()->get_adjacency_data();
75  if( !adj_list ) continue;
76  adj_list += ( *i )->start_handle() - ( *i )->data()->start_handle();
77 
78  for( EntityID j = 0; j < ( *i )->size(); ++j )
79  {
80  delete adj_list[j];
81  adj_list[j] = 0;
82  }
83  }
84  }
85 }
86 
87 //! get the elements contained by source_entity, of
88 //! type target_type, passing back in target_entities; if create_if_missing
89 //! is true and no entity is found, one is created; if create_adjacency_option
90 //! is >= 0, adjacencies from entities of that dimension to each target_entity
91 //! are created (this function uses AEntityFactory::get_element for each element)
93  const unsigned int target_dimension,
94  std::vector< EntityHandle >& target_entities,
95  const bool create_if_missing,
96  const int create_adjacency_option )
97 {
98  // check for trivial case first
99  const EntityType source_type = TYPE_FROM_HANDLE( source_entity );
100  const unsigned source_dimension = CN::Dimension( source_type );
101 
102  if( source_type >= MBENTITYSET || target_dimension < 1 || target_dimension > 3 )
103  {
104  return MB_TYPE_OUT_OF_RANGE;
105  }
106  else if( source_dimension == target_dimension )
107  {
108  target_entities.push_back( source_entity );
109  return MB_SUCCESS;
110  }
111 
112  ErrorCode result;
113  if( mVertElemAdj == false )
114  {
115  result = create_vert_elem_adjacencies();
116  if( MB_SUCCESS != result ) return result;
117  }
118 
119  if( source_dimension == 0 )
120  {
121  result = get_zero_to_n_elements( source_entity, target_dimension, target_entities, create_if_missing,
122  create_adjacency_option );
123  }
124  else if( source_dimension > target_dimension )
125  {
126  result = get_down_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing,
127  create_adjacency_option );
128  }
129  else // if(source_dimension < target_dimension)
130  {
131  result = get_up_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing,
132  create_adjacency_option );
133  }
134 
135  return result;
136 }
137 
139  std::vector< EntityHandle >& target_entities )
140 {
141  // get the connectivity array pointer
142  const EntityHandle* connect = NULL;
143  int num_connect = 0;
144  ErrorCode result = thisMB->get_connectivity( source_entity, connect, num_connect );
145  if( MB_SUCCESS != result ) return result;
146 
147  // now get the union of those polygons' vertices
148  result = thisMB->get_adjacencies( connect, num_connect, 0, false, target_entities, Interface::UNION );
149  return result;
150 }
151 
153  std::vector< EntityHandle >& target_entities )
154 {
155 
156  ErrorCode result;
157 
158  const EntityHandle* adj_vec;
159  int num_adj;
160  result = get_adjacencies( source_entity, adj_vec, num_adj );
161  if( result != MB_SUCCESS || adj_vec == NULL ) return result;
162 
163  // find the meshsets in this vector
164  DimensionPair dim_pair = CN::TypeDimensionMap[4];
165  int dum;
166  const EntityHandle* start_ent =
167  std::lower_bound( adj_vec, adj_vec + num_adj, CREATE_HANDLE( dim_pair.first, MB_START_ID, dum ) );
168  const EntityHandle* end_ent =
169  std::lower_bound( start_ent, adj_vec + num_adj, CREATE_HANDLE( dim_pair.second, MB_END_ID, dum ) );
170 
171  // copy the the meshsets
172  target_entities.insert( target_entities.end(), start_ent, end_ent );
173 
174  return result;
175 }
176 
177 //! get the element defined by the vertices in vertex_list, of the
178 //! type target_type, passing back in target_entity; if create_if_missing
179 //! is true and no entity is found, one is created; if create_adjacency_option
180 //! is >= 0, adjacencies from entities of that dimension to target_entity
181 //! are created (only create_adjacency_option=0 is supported right now,
182 //! so that never creates other ancillary entities)
184  const int vertex_list_size,
185  const EntityType target_type,
186  EntityHandle& target_entity,
187  const bool create_if_missing,
188  const EntityHandle source_entity,
189  const int /*create_adjacency_option*/ )
190 {
191 
192  // look over nodes to see if this entity already exists
193  target_entity = 0;
194  ErrorCode result;
195  const EntityHandle *i_adj, *end_adj;
196 
197  // need vertex adjacencies, so create if necessary
199 
200  // get the adjacency list
201  const EntityHandle* adj_vec;
202  int num_adj;
203  result = get_adjacencies( vertex_list[0], adj_vec, num_adj );
204  if( result != MB_SUCCESS || adj_vec == NULL ) return result;
205 
206  // check to see if any of these are equivalent to the vertex list
207  int dum;
208 
209  // use a fixed-size array, for speed; there should never be more than 5 equivalent entities
210  EntityHandle temp_vec[15];
211  int temp_vec_size = 0;
212 
213  i_adj = std::lower_bound( adj_vec, adj_vec + num_adj, CREATE_HANDLE( target_type, MB_START_ID, dum ) );
214  end_adj = std::lower_bound( i_adj, adj_vec + num_adj, CREATE_HANDLE( target_type, MB_END_ID, dum ) );
215  for( ; i_adj != end_adj; ++i_adj )
216  {
217  if( TYPE_FROM_HANDLE( *i_adj ) != target_type ) continue;
218 
219  if( true == entities_equivalent( *i_adj, vertex_list, vertex_list_size, target_type ) )
220  {
221  temp_vec[temp_vec_size++] = *i_adj;
222  }
223  }
224 
225  if( temp_vec_size == 0 && !create_if_missing ) return result;
226 
227  // test for size against fixed-size array
228  assert( temp_vec_size <= 15 );
229 
230  // test for empty first, 'cuz it's cheap
231  if( temp_vec_size == 0 && true == create_if_missing )
232  {
233 
234  // Create the element with this handle (handle is a return type and should be the last
235  // parameter)
236  result = thisMB->create_element( target_type, vertex_list, vertex_list_size, target_entity );
237  }
238 
239  // next most likely is one entity
240  else if( temp_vec_size == 1 )
241  target_entity = temp_vec[0];
242 
243  // least likely, most work - leave for last test
244  else
245  {
246  // multiple entities found - look for direct adjacencies
247  if( 0 != source_entity )
248  {
249 
250  int num_adjs;
251  for( dum = 0; dum < temp_vec_size; dum++ )
252  {
253  result = get_adjacencies( temp_vec[dum], adj_vec, num_adjs );
254  if( std::find( adj_vec, ( adj_vec + num_adjs ), source_entity ) != ( adj_vec + num_adjs ) )
255  {
256  // found it, return it
257  target_entity = temp_vec[dum];
258  break;
259  }
260  }
261 
262  if( 0 == target_entity &&
263  thisMB->dimension_from_handle( source_entity ) > CN::Dimension( target_type ) + 1 )
264  {
265  // still have multiple entities, and source dimension is two greater than target,
266  // so there may not be any explicit adjacencies between the two; look for common
267  // entities of the intermediate dimension
268  MeshTopoUtil mtu( thisMB );
269  int intermed_dim = CN::Dimension( target_type ) + 1;
270  for( dum = 0; dum < temp_vec_size; dum++ )
271  {
272  if( 0 != mtu.common_entity( temp_vec[dum], source_entity, intermed_dim ) )
273  {
274  target_entity = temp_vec[dum];
275  break;
276  }
277  }
278  }
279  }
280 
281  if( target_entity == 0 )
282  {
283  // if we get here, we didn't find a matching adjacency; just take the first one, but
284  // return a non-success result
285  target_entity = temp_vec[0];
287  }
288  }
289 
290  return result;
291 }
292 
294  const EntityHandle* vertex_list,
295  const int vertex_list_size,
296  const EntityType target_type )
297 {
298  // compare vertices of this_entity with those in the list, returning true if they
299  // represent the same element
300  EntityType this_type = TYPE_FROM_HANDLE( this_entity );
301 
302  if( this_type != target_type )
303  return false;
304 
305  else if( this_type == MBVERTEX && ( vertex_list_size > 1 || vertex_list[0] != this_entity ) )
306  return false;
307 
308  // need to compare the actual vertices
309  const EntityHandle* this_vertices = NULL;
310  int num_this_vertices = 0;
311  std::vector< EntityHandle > storage;
312  thisMB->get_connectivity( this_entity, this_vertices, num_this_vertices, false, &storage );
313 
314  // see if we can get one node id to match
315  assert( vertex_list_size > 0 );
316  int num_corner_verts =
317  ( ( this_type == MBPOLYGON || this_type == MBPOLYHEDRON ) ? num_this_vertices
318  : CN::VerticesPerEntity( target_type ) );
319  const EntityHandle* iter = std::find( this_vertices, ( this_vertices + num_corner_verts ), vertex_list[0] );
320  if( iter == ( this_vertices + num_corner_verts ) ) return false;
321 
322  // now lets do connectivity matching
323  bool they_match = true;
324 
325  // line up our vectors
326  int i;
327  int offset = iter - this_vertices;
328 
329  // first compare forward
330  for( i = 1; i < num_corner_verts; ++i )
331  {
332  if( i >= vertex_list_size )
333  {
334  they_match = false;
335  break;
336  }
337 
338  if( vertex_list[i] != this_vertices[( offset + i ) % num_corner_verts] )
339  {
340  they_match = false;
341  break;
342  }
343  }
344 
345  if( they_match == true ) return true;
346 
347  they_match = true;
348 
349  // then compare reverse
350  // offset iter to avoid addition inside loop; this just makes sure we don't
351  // go off beginning of this_vertices with an index < 0
352  offset += num_corner_verts;
353  for( i = 1; i < num_corner_verts; i++ )
354  {
355  if( vertex_list[i] != this_vertices[( offset - i ) % num_corner_verts] )
356  {
357  they_match = false;
358  break;
359  }
360  }
361  return they_match;
362 }
363 
364 //! add an adjacency from from_ent to to_ent; if both_ways is true, add one
365 //! in reverse too
366 //! NOTE: this function is defined even though we may only be implementing
367 //! vertex-based up-adjacencies
368 ErrorCode AEntityFactory::add_adjacency( EntityHandle from_ent, EntityHandle to_ent, const bool both_ways )
369 {
370  EntityType to_type = TYPE_FROM_HANDLE( to_ent );
371 
372  if( to_type == MBVERTEX ) return MB_ALREADY_ALLOCATED;
373 
374  AdjacencyVector* adj_list_ptr = NULL;
375  ErrorCode result = get_adjacencies( from_ent, adj_list_ptr, true );
376  if( MB_SUCCESS != result ) return result;
377 
378  // get an iterator to the right spot in this sorted vector
379  AdjacencyVector::iterator adj_iter;
380  if( !adj_list_ptr->empty() )
381  {
382  adj_iter = std::lower_bound( adj_list_ptr->begin(), adj_list_ptr->end(), to_ent );
383 
384  if( adj_iter == adj_list_ptr->end() || to_ent != *adj_iter )
385  {
386  adj_list_ptr->insert( adj_iter, to_ent );
387  }
388  }
389  else
390  adj_list_ptr->push_back( to_ent );
391 
392  // if both_ways is true, recursively call this function
393  if( true == both_ways && to_type != MBVERTEX ) result = add_adjacency( to_ent, from_ent, false );
394 
395  return result;
396 }
397 
398 //! remove an adjacency from from the base_entity.
400 {
401  ErrorCode result;
402 
403  if( TYPE_FROM_HANDLE( base_entity ) == MBENTITYSET )
404  return thisMB->remove_entities( base_entity, &adj_to_remove, 1 );
405 
406  // get the adjacency tag
407  AdjacencyVector* adj_list = NULL;
408  result = get_adjacencies( base_entity, adj_list );
409  if( adj_list == NULL || MB_SUCCESS != result ) return result;
410 
411  // remove the specified entity from the adjacency list and truncate
412  // the list to the new length
413  adj_list->erase( std::remove( adj_list->begin(), adj_list->end(), adj_to_remove ), adj_list->end() );
414 
415  return result;
416 }
417 
418 //! remove all adjacencies from from the base_entity.
419 ErrorCode AEntityFactory::remove_all_adjacencies( EntityHandle base_entity, const bool delete_adj_list )
420 {
421  ErrorCode result;
422  EntityType base_type = TYPE_FROM_HANDLE( base_entity );
423 
424  if( base_type == MBENTITYSET ) return thisMB->clear_meshset( &base_entity, 1 );
425  const int base_ent_dim = CN::Dimension( base_type );
426 
427  // Remove adjacencies from element vertices back to
428  // this element. Also check any elements adjacent
429  // to the vertex and of higher dimension than this
430  // element for downward adjacencies to this element.
431  if( vert_elem_adjacencies() && base_type != MBVERTEX )
432  {
433  EntityHandle const *connvect = 0, *adjvect = 0;
434  int numconn = 0, numadj = 0;
435  std::vector< EntityHandle > connstorage;
436  result = get_vertices( base_entity, connvect, numconn, connstorage );
437  if( MB_SUCCESS != result ) return result;
438 
439  for( int i = 0; i < numconn; ++i )
440  {
441  result = get_adjacencies( connvect[i], adjvect, numadj );
442  if( MB_SUCCESS != result ) return result;
443 
444  bool remove_this = false;
445  for( int j = 0; j < numadj; ++j )
446  {
447  if( adjvect[j] == base_entity ) remove_this = true;
448 
449  if( CN::Dimension( TYPE_FROM_HANDLE( adjvect[j] ) ) != base_ent_dim &&
450  explicitly_adjacent( adjvect[j], base_entity ) )
451  remove_adjacency( adjvect[j], base_entity );
452  }
453 
454  if( remove_this ) remove_adjacency( connvect[i], base_entity );
455  }
456  }
457 
458  // get the adjacency tag
459  AdjacencyVector* adj_list = 0;
460  result = get_adjacencies( base_entity, adj_list );
461  if( MB_SUCCESS != result || !adj_list ) return result;
462 
463  // check adjacent entities for references back to this entity
464  for( AdjacencyVector::reverse_iterator it = adj_list->rbegin(); it != adj_list->rend(); ++it )
465  remove_adjacency( *it, base_entity );
466 
467  if( delete_adj_list )
468  result = set_adjacency_ptr( base_entity, NULL );
469  else
470  adj_list->clear();
471 
472  return MB_SUCCESS;
473 }
474 
476 {
477 
478  mVertElemAdj = true;
479 
480  EntityType ent_type;
481  Range::iterator i_range;
482  const EntityHandle* connectivity;
483  std::vector< EntityHandle > aux_connect;
484  int number_nodes;
485  ErrorCode result;
486  Range handle_range;
487 
488  // 1. over all element types, for each element, create vertex-element adjacencies
489  for( ent_type = MBEDGE; ent_type != MBENTITYSET; ent_type++ )
490  {
491  handle_range.clear();
492 
493  // get this type of entity
494  result = thisMB->get_entities_by_type( 0, ent_type, handle_range );
495  if( result != MB_SUCCESS ) return result;
496 
497  for( i_range = handle_range.begin(); i_range != handle_range.end(); ++i_range )
498  {
499  result = get_vertices( *i_range, connectivity, number_nodes, aux_connect );
500  if( MB_SUCCESS != result ) return result;
501 
502  // add the adjacency
503  for( int k = 0; k < number_nodes; k++ )
504  if( ( result = add_adjacency( connectivity[k], *i_range ) ) != MB_SUCCESS ) return result;
505  }
506  }
507 
508  return MB_SUCCESS;
509 }
510 
512  const EntityHandle*& adjacent_entities,
513  int& num_entities ) const
514 {
515  AdjacencyVector const* vec_ptr = 0;
516  ErrorCode result = get_adjacency_ptr( entity, vec_ptr );
517  if( MB_SUCCESS != result || !vec_ptr )
518  {
519  adjacent_entities = 0;
520  num_entities = 0;
521  return result;
522  }
523 
524  num_entities = vec_ptr->size();
525  adjacent_entities = ( vec_ptr->empty() ) ? NULL : &( ( *vec_ptr )[0] );
526  return MB_SUCCESS;
527 }
528 
529 ErrorCode AEntityFactory::get_adjacencies( EntityHandle entity, std::vector< EntityHandle >& adjacent_entities ) const
530 {
531  AdjacencyVector const* vec_ptr = 0;
532  ErrorCode result = get_adjacency_ptr( entity, vec_ptr );
533  if( MB_SUCCESS != result || !vec_ptr )
534  {
535  adjacent_entities.clear();
536  return result;
537  }
538 
539  adjacent_entities = *vec_ptr;
540  return MB_SUCCESS;
541 }
542 
543 ErrorCode AEntityFactory::get_adjacencies( EntityHandle entity, std::vector< EntityHandle >*& adj_vec, bool create )
544 {
545  adj_vec = 0;
546  ErrorCode result = get_adjacency_ptr( entity, adj_vec );
547  if( MB_SUCCESS == result && !adj_vec && create )
548  {
549  adj_vec = new AdjacencyVector;
550  result = set_adjacency_ptr( entity, adj_vec );
551  if( MB_SUCCESS != result )
552  {
553  delete adj_vec;
554  adj_vec = 0;
555  }
556  }
557  return result;
558 }
559 
561  const unsigned int target_dimension,
562  bool create_if_missing,
563  std::vector< EntityHandle >& target_entities )
564 {
565  const EntityType source_type = TYPE_FROM_HANDLE( source_entity );
566  const unsigned source_dimension = CN::Dimension( source_type );
567 
568  ErrorCode result;
569  if( target_dimension == 4 )
570  { // get meshsets 'source' is in
571  result = get_associated_meshsets( source_entity, target_entities );
572  }
573  else if( target_dimension == ( source_type != MBPOLYHEDRON ? 0 : 2 ) )
574  {
575  std::vector< EntityHandle > tmp_storage;
576  const EntityHandle* conn = NULL;
577  int len = 0;
578  result = thisMB->get_connectivity( source_entity, conn, len, false, &tmp_storage );
579  target_entities.insert( target_entities.end(), conn, conn + len );
580  }
581  else if( target_dimension == 0 && source_type == MBPOLYHEDRON )
582  {
583  result = get_polyhedron_vertices( source_entity, target_entities );
584  }
585  else if( source_dimension == target_dimension )
586  {
587  target_entities.push_back( source_entity );
588  result = MB_SUCCESS;
589  }
590  else
591  {
592  if( mVertElemAdj == false )
593  {
594  result = create_vert_elem_adjacencies();
595  if( MB_SUCCESS != result ) return result;
596  }
597 
598  if( source_dimension == 0 )
599  {
600  result = get_zero_to_n_elements( source_entity, target_dimension, target_entities, create_if_missing );
601  }
602  else if( source_dimension > target_dimension )
603  {
604  result = get_down_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing );
605  }
606  else // if(source_dimension < target_dimension)
607  {
608  result = get_up_adjacency_elements( source_entity, target_dimension, target_entities, create_if_missing );
609  }
610  }
611 
612  return result;
613 }
614 
616  const EntityHandle* node_array,
617  const int number_nodes )
618 {
619  ErrorCode result = MB_SUCCESS, tmp_result;
620  if( vert_elem_adjacencies() )
621  {
622  // iterate through nodes and add adjacency information
623  if( TYPE_FROM_HANDLE( entity ) == MBPOLYHEDRON )
624  {
625  // polyhedron - get real vertex connectivity
626  std::vector< EntityHandle > verts;
627  tmp_result = get_adjacencies( entity, 0, false, verts );
628  if( MB_SUCCESS != tmp_result ) return tmp_result;
629  for( std::vector< EntityHandle >::iterator vit = verts.begin(); vit != verts.end(); ++vit )
630  {
631  tmp_result = add_adjacency( *vit, entity );
632  if( MB_SUCCESS != tmp_result ) result = tmp_result;
633  }
634  }
635  else
636  {
637  for( unsigned int i = number_nodes; i--; )
638  {
639  tmp_result = add_adjacency( node_array[i], entity );
640  if( MB_SUCCESS != tmp_result ) result = tmp_result;
641  }
642  }
643  }
644 
645  return result;
646 }
647 
649  const unsigned int target_dimension,
650  std::vector< EntityHandle >& target_entities,
651  const bool create_if_missing,
652  const int /*create_adjacency_option = -1*/ )
653 {
654  AdjacencyVector::iterator start_ent, end_ent;
655 
656  // get the adjacency vector
657  AdjacencyVector* adj_vec = NULL;
658  ErrorCode result = get_adjacencies( source_entity, adj_vec );
659  if( result != MB_SUCCESS || adj_vec == NULL ) return result;
660 
661  if( target_dimension < 3 && create_if_missing )
662  {
663  std::vector< EntityHandle > tmp_ents;
664 
665  start_ent = std::lower_bound( adj_vec->begin(), adj_vec->end(),
666  FIRST_HANDLE( CN::TypeDimensionMap[target_dimension + 1].first ) );
667 
668  end_ent = std::lower_bound( start_ent, adj_vec->end(), LAST_HANDLE( CN::TypeDimensionMap[3].second ) );
669 
670  std::vector< EntityHandle > elems( start_ent, end_ent );
671 
672  // make target_dimension elements from all adjacient higher-dimension elements
673  for( start_ent = elems.begin(); start_ent != elems.end(); ++start_ent )
674  {
675  tmp_ents.clear();
676  get_down_adjacency_elements( *start_ent, target_dimension, tmp_ents, create_if_missing, 0 );
677  }
678  }
679 
680  DimensionPair dim_pair = CN::TypeDimensionMap[target_dimension];
681  start_ent = std::lower_bound( adj_vec->begin(), adj_vec->end(), FIRST_HANDLE( dim_pair.first ) );
682  end_ent = std::lower_bound( start_ent, adj_vec->end(), LAST_HANDLE( dim_pair.second ) );
683  target_entities.insert( target_entities.end(), start_ent, end_ent );
684  return MB_SUCCESS;
685 }
686 
688  const unsigned int target_dimension,
689  std::vector< EntityHandle >& target_entities,
690  const bool create_if_missing,
691  const int create_adjacency_option )
692 {
693 
694  EntityType source_type = TYPE_FROM_HANDLE( source_entity );
695 
696  if( source_type == MBPOLYHEDRON || source_type == MBPOLYGON )
697  return get_down_adjacency_elements_poly( source_entity, target_dimension, target_entities, create_if_missing,
698  create_adjacency_option );
699 
700  // make this a fixed size to avoid cost of working with STL vectors
701  EntityHandle vertex_array[27] = {};
702  ErrorCode temp_result;
703 
704  const EntityHandle* vertices = NULL;
705  int num_verts = 0;
706 
707  // I know there are already vertex adjacencies for this - call
708  // another function to get them
709  std::vector< EntityHandle > storage;
710  ErrorCode result = thisMB->get_connectivity( source_entity, vertices, num_verts, false, &storage );
711  if( MB_SUCCESS != result ) return result;
712 
713  int has_mid_nodes[4];
714  CN::HasMidNodes( source_type, num_verts, has_mid_nodes );
715 
716  std::vector< int > index_list;
717  int num_sub_ents = CN::NumSubEntities( source_type, target_dimension );
718 
719  for( int j = 0; j < num_sub_ents; j++ )
720  {
721  const CN::ConnMap& cmap = CN::mConnectivityMap[source_type][target_dimension - 1];
722 
723  int verts_per_sub = cmap.num_corners_per_sub_element[j];
724 
725  // get the corner vertices
726  for( int i = 0; i < verts_per_sub; i++ )
727  vertex_array[i] = vertices[cmap.conn[j][i]];
728 
729  // get the ho nodes for sub-subfacets
730  if( has_mid_nodes[1] && target_dimension > 1 )
731  {
732  // has edge mid-nodes; for each edge, get the right mid-node and put in vertices
733  // first get the edge indices
734  index_list.clear();
735  int int_result = CN::AdjacentSubEntities( source_type, &j, 1, target_dimension, 1, index_list );
736  if( 0 != int_result ) return MB_FAILURE;
737  for( unsigned int k = 0; k < index_list.size(); k++ )
738  {
739  int tmp_index = CN::HONodeIndex( source_type, num_verts, 1, index_list[k] );
740  if( tmp_index >= (int)num_verts ) return MB_INDEX_OUT_OF_RANGE;
741 
742  // put this vertex on the end; reuse verts_per_sub as an index
743  vertex_array[verts_per_sub++] = vertices[tmp_index];
744  }
745  }
746  // get the ho nodes for the target dimension
747  if( has_mid_nodes[target_dimension] )
748  {
749  // get the ho node index for this subfacet
750  int tmp_index = CN::HONodeIndex( source_type, num_verts, target_dimension, j );
751  if( tmp_index >= num_verts ) return MB_INDEX_OUT_OF_RANGE;
752  vertex_array[verts_per_sub++] = vertices[tmp_index];
753  }
754 
755  EntityHandle tmp_target = 0;
756  temp_result = get_element( vertex_array, verts_per_sub, cmap.target_type[j], tmp_target, create_if_missing,
757  source_entity, create_adjacency_option );
758 
759  if( temp_result != MB_SUCCESS )
760  result = temp_result;
761  else if( 0 != tmp_target )
762  target_entities.push_back( tmp_target );
763 
764  // make sure we're not writing past the end of our fixed-size array
765  if( verts_per_sub > 27 ) return MB_INDEX_OUT_OF_RANGE;
766  }
767 
768  return result;
769 }
770 
772  const unsigned int target_dimension,
773  std::vector< EntityHandle >& target_entities,
774  const bool create_if_missing,
775  const int /*create_adjacency_option*/ )
776 {
777 
778  EntityType source_type = TYPE_FROM_HANDLE( source_entity );
779 
780  if( !( source_type == MBPOLYHEDRON && target_dimension > 0 && target_dimension < 3 ) &&
781  !( source_type == MBPOLYGON && target_dimension == 1 ) )
782  return MB_TYPE_OUT_OF_RANGE;
783 
784  // make this a fixed size to avoid cost of working with STL vectors
785  std::vector< EntityHandle > vertex_array;
786 
787  // I know there are already vertex adjacencies for this - call
788  // another function to get them
789  ErrorCode result = get_adjacencies( source_entity, 0, false, vertex_array );
790  if( MB_SUCCESS != result ) return result;
791 
792  ErrorCode tmp_result;
793  if( source_type == MBPOLYGON )
794  {
795  result = MB_SUCCESS;
796  // put the first vertex on the end so we have a ring
797  vertex_array.push_back( *vertex_array.begin() );
798  for( unsigned int i = 0; i < vertex_array.size() - 1; i++ )
799  {
800  Range vrange, adj_edges;
801  vrange.insert( vertex_array[i] );
802  vrange.insert( vertex_array[i + 1] );
803  // account for padded polygons; if the vertices are the same, skip
804  if( vrange.size() == 1 ) continue;
805  tmp_result = thisMB->get_adjacencies( vrange, 1, false, adj_edges );
806  if( MB_SUCCESS != tmp_result ) result = tmp_result;
807  if( adj_edges.size() == 1 )
808  {
809  // single edge - don't check adjacencies
810  target_entities.push_back( *adj_edges.begin() );
811  }
812  else if( adj_edges.size() != 0 )
813  {
814  // multiple ones - need to check for explicit adjacencies
815  unsigned int start_sz = target_entities.size();
816  const EntityHandle* explicit_adjs;
817  int num_exp;
818  for( Range::iterator rit = adj_edges.begin(); rit != adj_edges.end(); ++rit )
819  {
820  // TODO check return value
821  this->get_adjacencies( *rit, explicit_adjs, num_exp );
822  if( NULL != explicit_adjs &&
823  std::find( explicit_adjs, explicit_adjs + num_exp, source_entity ) != explicit_adjs + num_exp )
824  target_entities.push_back( *rit );
825  }
826  if( target_entities.size() == start_sz )
827  {
829  target_entities.push_back( *adj_edges.begin() );
830  }
831  }
832  else
833  {
834  // we have no adjacent edge yet; we need to create one and also add
835  // them to the adjacency of the vertices
836  if( create_if_missing )
837  {
838  EntityHandle newEdge;
839  EntityHandle v[2] = { vertex_array[i], vertex_array[i + 1] };
840  result = thisMB->create_element( MBEDGE, v, 2, newEdge );
841  if( MB_SUCCESS != result ) return result;
842  // we also need to add explicit adjacency, so next time we do not
843  // create again (because we do not find the edge if it is not adjacent to the
844  // vertices
845  // if (create_adjacency_option >= 0)
846  //{
847  result = add_adjacency( v[0], newEdge );
848  if( MB_SUCCESS != result ) return result;
849  result = add_adjacency( v[1], newEdge );
850  if( MB_SUCCESS != result ) return result;
851  target_entities.push_back( newEdge );
852  //}
853  }
854  }
855  }
856  return result;
857  }
858 
859  else
860  {
861  if( target_dimension == 2 )
862  {
863  result = thisMB->get_connectivity( &source_entity, 1, target_entities );
864  }
865  else
866  {
867  std::vector< EntityHandle > dum_vec;
868  result = thisMB->get_connectivity( &source_entity, 1, dum_vec );
869  if( MB_SUCCESS != result ) return result;
870  result = thisMB->get_adjacencies( &dum_vec[0], dum_vec.size(), 1, create_if_missing, target_entities,
872  return result;
873  }
874  }
875 
876  return MB_SUCCESS;
877 }
878 
879 #if 0
880 // Do in-place set intersect of two *sorted* containers.
881 // First container is modifed. Second is not.
882 // First container must allow assignment through iterators (in practice,
883 // must be a container that does not enforce ordering, such
884 // as std::vector, std::list, or a c-style array)
885 template <typename T1, typename T2>
886 static inline T1 intersect( T1 set1_begin, T1 set1_end,
887  T2 set2_begin, T2 set2_end )
888 {
889  T1 set1_write = set1_begin;
890  while (set1_begin != set1_end) {
891  if (set2_begin == set2_end)
892  return set1_write;
893  while (*set2_begin < *set1_begin)
894  if (++set2_begin == set2_end)
895  return set1_write;
896  if (!(*set1_begin < *set2_begin)) {
897  *set1_write = *set1_begin;
898  ++set1_write;
899  ++set2_begin;
900  }
901  ++set1_begin;
902  }
903  return set1_write;
904 }
905 
906 
908  EntityHandle source_entity,
909  const unsigned int target_dimension,
910  std::vector<EntityHandle>& target_entities,
911  const bool create_if_missing,
912  const int option )
913 {
914  ErrorCode rval;
915  const std::vector<EntityHandle> *vtx_adj, *vtx2_adj;
916  std::vector<EntityHandle> duplicates;
917 
918  // Handle ranges
919  const size_t in_size = target_entities.size();
920  const EntityType src_type = TYPE_FROM_HANDLE(source_entity);
921  DimensionPair target_types = CN::TypeDimensionMap[target_dimension];
922  const EntityHandle src_beg_handle = CREATE_HANDLE( src_type, 0 );
923  const EntityHandle src_end_handle = CREATE_HANDLE( src_type+1, 0 );
924  const EntityHandle tgt_beg_handle = CREATE_HANDLE( target_types.first, 0 );
925  const EntityHandle tgt_end_handle = CREATE_HANDLE( target_types.second+1, 0 );
926 
927  // get vertices
928  assert(TYPE_FROM_HANDLE(source_entity) != MBPOLYHEDRON); // can't go up from a region
929  std::vector<EntityHandle> conn_storage;
930  const EntityHandle* conn;
931  int conn_len;
932  rval = thisMB->get_connectivity( source_entity, conn, conn_len, true, &conn_storage );
933  if (MB_SUCCESS != rval)
934  return rval;
935 
936  // shouldn't be here if source entity is not an element
937  assert(conn_len > 1);
938 
939  // create necessary entities. this only makes sense if there exists of a
940  // dimension greater than the target dimension.
941  if (create_if_missing && target_dimension < 3 && CN::Dimension(src_type) < 2) {
942  for (size_t i = 0; i < conn_len; ++i) {
943  rval = get_adjacency_ptr( conn[i], vtx_adj );
944  if (MB_SUCCESS != rval)
945  return rval;
946  assert(vtx_adj != NULL); // should contain at least source_entity
947 
948  std::vector<EntityHandle> tmp2, tmp(*vtx_adj); // copy in case adjacency vector is changed
949  for (size_t j = 0; j < tmp.size(); ++j) {
950  if (CN::Dimension(TYPE_FROM_HANDLE(tmp[j])) <= (int)target_dimension)
951  continue;
952  if (TYPE_FROM_HANDLE(tmp[j]) == MBENTITYSET)
953  break;
954 
955  tmp2.clear();
956  rval = get_down_adjacency_elements( tmp[j], target_dimension, tmp2, true, option );
957  if (MB_SUCCESS != rval)
958  return rval;
959  }
960  }
961  }
962 
963  // get elements adjacent to first vertex
964  rval = get_adjacency_ptr( conn[0], vtx_adj );
965  if (MB_SUCCESS != rval)
966  return rval;
967  assert(vtx_adj != NULL); // should contain at least source_entity
968  // get elements adjacent to second vertex
969  rval = get_adjacency_ptr( conn[1], vtx2_adj );
970  if (MB_SUCCESS != rval)
971  return rval;
972  assert(vtx2_adj != NULL);
973 
974  // Put intersect of all entities except source entity with
975  // the same type as the source entity in 'duplicates'
976  std::vector<EntityHandle>::const_iterator it1, it2, end1, end2;
977  it1 = std::lower_bound( vtx_adj->begin(), vtx_adj->end(), src_beg_handle );
978  it2 = std::lower_bound( vtx2_adj->begin(), vtx2_adj->end(), src_beg_handle );
979  end1 = std::lower_bound( it1, vtx_adj->end(), src_end_handle );
980  end2 = std::lower_bound( it2, vtx2_adj->end(), src_end_handle );
981  assert(end1 != it1); // should at least contain source entity
982  duplicates.resize( end1 - it1 - 1 );
983  std::vector<EntityHandle>::iterator ins = duplicates.begin();
984  for (; it1 != end1; ++it1) {
985  if (*it1 != source_entity) {
986  *ins = *it1;
987  ++ins;
988  }
989  }
990  duplicates.erase( intersect( duplicates.begin(), duplicates.end(), it2, end2 ), duplicates.end() );
991 
992  // Append to input list any entities of the desired target dimension
993  it1 = std::lower_bound( end1, vtx_adj->end(), tgt_beg_handle );
994  it2 = std::lower_bound( end2, vtx2_adj->end(), tgt_beg_handle );
995  end1 = std::lower_bound( it1, vtx_adj->end(), tgt_end_handle );
996  end2 = std::lower_bound( it2, vtx2_adj->end(), tgt_end_handle );
997  std::set_intersection( it1, end1, it2, end2, std::back_inserter( target_entities ) );
998 
999  // for each additional vertex
1000  for (int i = 2; i < conn_len; ++i) {
1001  rval = get_adjacency_ptr( conn[i], vtx_adj );
1002  if (MB_SUCCESS != rval)
1003  return rval;
1004  assert(vtx_adj != NULL); // should contain at least source_entity
1005 
1006  it1 = std::lower_bound( vtx_adj->begin(), vtx_adj->end(), src_beg_handle );
1007  end1 = std::lower_bound( it1, vtx_adj->end(), src_end_handle );
1008  duplicates.erase( intersect( duplicates.begin(), duplicates.end(), it1, end1 ), duplicates.end() );
1009 
1010  it1 = std::lower_bound( end1, vtx_adj->end(), tgt_beg_handle );
1011  end1 = std::lower_bound( it1, vtx_adj->end(), tgt_end_handle );
1012  target_entities.erase( intersect( target_entities.begin()+in_size, target_entities.end(),
1013  it1, end1 ), target_entities.end() );
1014  }
1015 
1016  // if no duplicates, we're done
1017  if (duplicates.empty())
1018  return MB_SUCCESS;
1019 
1020  // Check for explicit adjacencies. If an explicit adjacency
1021  // connects candidate target entity to an entity equivalent
1022  // to the source entity, then assume that source entity is *not*
1023  // adjacent
1024  const std::vector<EntityHandle>* adj_ptr;
1025  // check adjacencies from duplicate entities to candidate targets
1026  for (size_t i = 0; i < duplicates.size(); ++i) {
1027  rval = get_adjacency_ptr( duplicates[i], adj_ptr );
1028  if (MB_SUCCESS != rval)
1029  return rval;
1030  if (!adj_ptr)
1031  continue;
1032 
1033  for (size_t j = 0; j < adj_ptr->size(); ++j) {
1034  std::vector<EntityHandle>::iterator k =
1035  std::find( target_entities.begin()+in_size, target_entities.end(), (*adj_ptr)[j] );
1036  if (k != target_entities.end())
1037  target_entities.erase(k);
1038  }
1039  }
1040 
1041  // If target dimension is 3 and source dimension is 1, also need to
1042  // check for explicit adjacencies to intermediate faces
1043  if (CN::Dimension(src_type) > 1 || target_dimension < 3)
1044  return MB_SUCCESS;
1045 
1046  // Get faces adjacent to each element and check for explict
1047  // adjacencies from duplicate entities to faces
1048  for (size_t i = 0; i < duplicates.size(); ++i) {
1049  rval = get_adjacency_ptr( duplicates[i], adj_ptr );
1050  if (MB_SUCCESS != rval)
1051  return rval;
1052  if (!adj_ptr)
1053  continue;
1054 
1055  size_t j;
1056  for (j = 0; j < adj_ptr->size(); ++j) {
1057  const std::vector<EntityHandle>* adj_ptr2;
1058  rval = get_adjacency_ptr( (*adj_ptr)[j], adj_ptr2 );
1059  if (MB_SUCCESS != rval)
1060  return rval;
1061  if (!adj_ptr2)
1062  continue;
1063 
1064  for (size_t k = 0; k < adj_ptr2->size(); ++k) {
1065  std::vector<EntityHandle>::iterator it;
1066  it = std::find( target_entities.begin()+in_size, target_entities.end(), (*adj_ptr2)[k] );
1067  if (it != target_entities.end()) {
1068  target_entities.erase(it);
1069  j = adj_ptr->size(); // break outer loop
1070  break;
1071  }
1072  }
1073  }
1074  }
1075 
1076  return MB_SUCCESS;
1077 }
1078 #else
1080  const unsigned int target_dimension,
1081  std::vector< EntityHandle >& target_entities,
1082  const bool create_if_missing,
1083  const int /*create_adjacency_option = -1*/ )
1084 {
1085 
1086  EntityType source_type = TYPE_FROM_HANDLE( source_entity );
1087 
1088  const EntityHandle* source_vertices = NULL;
1089  int num_source_vertices = 0;
1090  std::vector< EntityHandle > conn_storage;
1091 
1092  // check to see whether there are any equivalent entities (same verts, different entity);
1093  // do this by calling get_element with a 0 source_entity, and look for a
1094  // MB_MULTIPLE_ENTITIES_FOUND return code
1095 
1096  // NOTE: we only want corner vertices here, and for the code below which also uses
1097  // source_vertices
1098  ErrorCode result =
1099  thisMB->get_connectivity( source_entity, source_vertices, num_source_vertices, true, &conn_storage );
1100  if( MB_SUCCESS != result ) return result;
1101  EntityHandle temp_entity;
1102  result = get_element( source_vertices, num_source_vertices, source_type, temp_entity, false, 0 );
1103 
1104  bool equiv_entities = ( result == MB_MULTIPLE_ENTITIES_FOUND ) ? true : false;
1105 
1106  std::vector< EntityHandle > tmp_vec;
1107  if( !equiv_entities )
1108  {
1109  // get elems adjacent to each node
1110  std::vector< std::vector< EntityHandle > > elems( num_source_vertices );
1111  int i;
1112  for( i = 0; i < num_source_vertices; i++ )
1113  {
1114  // get elements
1115  // see comment above pertaining to source_vertices; these are corner vertices only
1116  get_zero_to_n_elements( source_vertices[i], target_dimension, elems[i], create_if_missing, 0 );
1117  // sort this element list
1118  std::sort( elems[i].begin(), elems[i].end() );
1119  }
1120 
1121  // perform an intersection between all the element lists
1122  // see comment above pertaining to source_vertices; these are corner vertices only
1123  for( i = 1; i < num_source_vertices; i++ )
1124  {
1125  tmp_vec.clear();
1126 
1127  // intersection between first list and ith list, put result in tmp
1128  std::set_intersection( elems[0].begin(), elems[0].end(), elems[i].begin(), elems[i].end(),
1129  std::back_insert_iterator< std::vector< EntityHandle > >( tmp_vec ) );
1130  // tmp has elems[0] contents and elems[0] contents has tmp's contents
1131  // so that elems[0] always has the intersection of previous operations
1132  elems[0].swap( tmp_vec );
1133  }
1134 
1135  // elems[0] contains the intersection, swap with target_entities
1136  target_entities.insert( target_entities.end(), elems[0].begin(), elems[0].end() );
1137  }
1138  else if( source_type == MBPOLYGON )
1139  {
1140  // get adjacencies using polyhedra's connectivity vectors
1141  // first get polyhedra neighboring vertices
1142  result = thisMB->get_adjacencies( source_vertices, num_source_vertices, 3, false, tmp_vec );
1143  if( MB_SUCCESS != result ) return result;
1144 
1145  // now filter according to whether each is adjacent to the polygon
1146  const EntityHandle* connect = NULL;
1147  int num_connect = 0;
1148  std::vector< EntityHandle > storage;
1149  for( unsigned int i = 0; i < tmp_vec.size(); i++ )
1150  {
1151  result = thisMB->get_connectivity( tmp_vec[i], connect, num_connect, false, &storage );
1152  if( MB_SUCCESS != result ) return result;
1153  if( std::find( connect, connect + num_connect, source_entity ) != connect + num_connect )
1154  target_entities.push_back( tmp_vec[i] );
1155  }
1156  }
1157 
1158  else
1159  {
1160  // else get up-adjacencies directly; code copied from get_zero_to_n_elements
1161 
1162  // get the adjacency vector
1163  AdjacencyVector* adj_vec = NULL;
1164  result = get_adjacencies( source_entity, adj_vec );
1165 
1166  if( result != MB_SUCCESS )
1167  return result;
1168  else if( adj_vec == NULL )
1169  return MB_SUCCESS;
1170 
1171  DimensionPair dim_pair_dp1 = CN::TypeDimensionMap[CN::Dimension( source_type ) + 1],
1172  dim_pair_td = CN::TypeDimensionMap[target_dimension];
1173  int dum;
1174 
1175  Range tmp_ents, target_ents;
1176 
1177  // get iterators for start handle of source_dim+1 and target_dim, and end handle
1178  // of target_dim
1179  AdjacencyVector::iterator start_ent_dp1 =
1180  std::lower_bound( adj_vec->begin(), adj_vec->end(),
1181  CREATE_HANDLE( dim_pair_dp1.first, MB_START_ID, dum ) ),
1182 
1183  start_ent_td =
1184  std::lower_bound( adj_vec->begin(), adj_vec->end(),
1185  CREATE_HANDLE( dim_pair_td.first, MB_START_ID, dum ) ),
1186 
1187  end_ent_td = std::lower_bound( adj_vec->begin(), adj_vec->end(),
1188  CREATE_HANDLE( dim_pair_td.second, MB_END_ID, dum ) );
1189 
1190  // get the adjacencies for source_dim+1 to target_dim-1, and the adjacencies from
1191  // those to target_dim
1192  std::copy( start_ent_dp1, start_ent_td, range_inserter( tmp_ents ) );
1193  result = thisMB->get_adjacencies( tmp_ents, target_dimension, false, target_ents, Interface::UNION );
1194  if( MB_SUCCESS != result ) return result;
1195 
1196  // now copy the explicit adjacencies to target_dimension
1197  std::copy( start_ent_td, end_ent_td, range_inserter( target_ents ) );
1198 
1199  // now insert the whole thing into the argument vector
1200 #ifdef MOAB_NO_VECTOR_TEMPLATE_INSERT
1201  std::copy( target_ents.begin(), target_ents.end(), std::back_inserter( target_entities ) );
1202 #else
1203  target_entities.insert( target_entities.end(), target_ents.begin(), target_ents.end() );
1204 #endif
1205  }
1206 
1207  return result;
1208 }
1209 #endif
1210 
1212  const EntityHandle* old_array,
1213  const EntityHandle* new_array,
1214  int number_verts )
1215 {
1216  EntityType source_type = TYPE_FROM_HANDLE( entity );
1217  if( source_type == MBPOLYHEDRON ) return MB_NOT_IMPLEMENTED;
1218 
1219  // find out which ones to add and which to remove
1220  std::vector< EntityHandle > old_verts, new_verts;
1221  int i;
1222  for( i = 0; i < number_verts; i++ )
1223  {
1224  if( old_array[i] != new_array[i] )
1225  {
1226  old_verts.push_back( old_array[i] );
1227  new_verts.push_back( new_array[i] );
1228  }
1229  }
1230 
1231  ErrorCode result;
1232 
1233  if( mVertElemAdj == true )
1234  {
1235  // update the vertex-entity adjacencies
1236  std::vector< EntityHandle >::iterator adj_iter;
1237  for( adj_iter = old_verts.begin(); adj_iter != old_verts.end(); ++adj_iter )
1238  {
1239  if( std::find( new_verts.begin(), new_verts.end(), *adj_iter ) == new_verts.end() )
1240  {
1241  result = remove_adjacency( *adj_iter, entity );
1242  if( MB_SUCCESS != result ) return result;
1243  }
1244  }
1245  for( adj_iter = new_verts.begin(); adj_iter != new_verts.end(); ++adj_iter )
1246  {
1247  if( std::find( old_verts.begin(), old_verts.end(), *adj_iter ) == old_verts.end() )
1248  {
1249  result = add_adjacency( *adj_iter, entity );
1250  if( MB_SUCCESS != result ) return result;
1251  }
1252  }
1253  }
1254 
1255  return MB_SUCCESS;
1256 }
1257 
1258 //! return true if 2 entities are explicitly adjacent
1260 {
1261  const EntityHandle* explicit_adjs;
1262  int num_exp;
1263  get_adjacencies( ent1, explicit_adjs, num_exp );
1264  if( std::find( explicit_adjs, explicit_adjs + num_exp, ent2 ) != explicit_adjs + num_exp )
1265  return true;
1266  else
1267  return false;
1268 }
1269 
1271 {
1272  int ent_dim = CN::Dimension( TYPE_FROM_HANDLE( entity_to_keep ) );
1273  ErrorCode result;
1274 
1275  // check for newly-formed equivalent entities, and create explicit adjacencies
1276  // to distinguish them; this must be done before connectivity of higher-dimensional
1277  // entities is changed below, and only needs to be checked if merging vertices
1278  if( ent_dim == 0 )
1279  {
1280  result = check_equiv_entities( entity_to_keep, entity_to_remove );
1281  if( MB_SUCCESS != result ) return result;
1282  }
1283 
1284  // check adjacencies TO removed entity
1285  for( int dim = 1; dim < ent_dim; dim++ )
1286  {
1287  Range adjs;
1288  result = thisMB->get_adjacencies( &entity_to_remove, 1, dim, false, adjs );
1289  if( result != MB_SUCCESS ) return result;
1290  // for any explicit ones, make them adjacent to keeper
1291  for( Range::iterator rit = adjs.begin(); rit != adjs.end(); ++rit )
1292  {
1293  if( this->explicitly_adjacent( *rit, entity_to_remove ) )
1294  {
1295  result = this->add_adjacency( *rit, entity_to_keep );
1296  if( result != MB_SUCCESS ) return result;
1297  }
1298  }
1299  }
1300 
1301  // check adjacencies FROM removed entity
1302  std::vector< EntityHandle > conn, adjs;
1303  result = this->get_adjacencies( entity_to_remove, adjs );
1304  if( result != MB_SUCCESS ) return result;
1305  // set them all, and if to_entity is a set, add to that one too
1306  for( unsigned int i = 0; i < adjs.size(); i++ )
1307  {
1308  if( TYPE_FROM_HANDLE( adjs[i] ) == MBENTITYSET )
1309  {
1310  // result = this->add_adjacency(entity_to_keep, adjs[i]);
1311  // if(result != MB_SUCCESS) return result;
1312  // result = thisMB->add_entities(adjs[i], &entity_to_keep, 1);
1313  // if(result != MB_SUCCESS) return result;
1314  result = thisMB->replace_entities( adjs[i], &entity_to_remove, &entity_to_keep, 1 );
1315  if( MB_SUCCESS != result ) return result;
1316  }
1317  else if( ent_dim == 0 )
1318  {
1319  conn.clear();
1320  result = thisMB->get_connectivity( &adjs[i], 1, conn );
1321 
1322  if( result == MB_SUCCESS )
1323  {
1324  std::replace( conn.begin(), conn.end(), entity_to_remove, entity_to_keep );
1325  result = thisMB->set_connectivity( adjs[i], &conn[0], conn.size() );
1326  if( MB_SUCCESS != result ) return result;
1327  }
1328  else
1329  return result;
1330  }
1331  else
1332  {
1333  result = this->add_adjacency( entity_to_keep, adjs[i] );
1334  if( result != MB_SUCCESS ) return result;
1335  }
1336  }
1337 
1338  return MB_SUCCESS;
1339 }
1340 
1341 // check for equivalent entities that may be formed when merging two entities, and
1342 // create explicit adjacencies accordingly
1344 {
1345  if( thisMB->dimension_from_handle( entity_to_keep ) > 0 ) return MB_SUCCESS;
1346 
1347  // get all the adjacencies for both entities for all dimensions > 0
1348  Range adjs_keep, adjs_remove;
1349  ErrorCode result;
1350 
1351  for( int dim = 1; dim <= 3; dim++ )
1352  {
1353  result = thisMB->get_adjacencies( &entity_to_keep, 1, dim, false, adjs_keep, Interface::UNION );
1354  if( MB_SUCCESS != result ) return result;
1355  result = thisMB->get_adjacencies( &entity_to_remove, 1, dim, false, adjs_remove, Interface::UNION );
1356  if( MB_SUCCESS != result ) return result;
1357  }
1358 
1359  // now look for equiv entities which will be formed
1360  // algorithm:
1361  // for each entity adjacent to removed entity:
1362  EntityHandle two_ents[2];
1363  for( Range::iterator rit_rm = adjs_remove.begin(); rit_rm != adjs_remove.end(); ++rit_rm )
1364  {
1365  two_ents[0] = *rit_rm;
1366 
1367  // - for each entity of same dimension adjacent to kept entity:
1368  for( Range::iterator rit_kp = adjs_keep.begin(); rit_kp != adjs_keep.end(); ++rit_kp )
1369  {
1370  if( TYPE_FROM_HANDLE( *rit_kp ) != TYPE_FROM_HANDLE( *rit_rm ) ) continue;
1371 
1372  Range all_verts;
1373  two_ents[1] = *rit_kp;
1374  // . get union of adjacent vertices to two entities
1375  result = thisMB->get_adjacencies( two_ents, 2, 0, false, all_verts, Interface::UNION );
1376  if( MB_SUCCESS != result ) return result;
1377 
1378  assert( all_verts.find( entity_to_keep ) != all_verts.end() &&
1379  all_verts.find( entity_to_remove ) != all_verts.end() );
1380 
1381  // . if # vertices != number of corner vertices + 1, continue
1382  if( CN::VerticesPerEntity( TYPE_FROM_HANDLE( *rit_rm ) ) + 1 != (int)all_verts.size() ) continue;
1383 
1384  // . for the two entities adjacent to kept & removed entity:
1385  result = create_explicit_adjs( *rit_rm );
1386  if( MB_SUCCESS != result ) return result;
1387  result = create_explicit_adjs( *rit_kp );
1388  if( MB_SUCCESS != result ) return result;
1389  // . (end for)
1390  }
1391  // - (end for)
1392  }
1393 
1394  return MB_SUCCESS;
1395 }
1396 
1398 {
1399  // - get adjacent entities of next higher dimension
1400  Range all_adjs;
1401  ErrorCode result;
1402  result = thisMB->get_adjacencies( &this_ent, 1, thisMB->dimension_from_handle( this_ent ) + 1, false, all_adjs,
1403  Interface::UNION );
1404  if( MB_SUCCESS != result ) return result;
1405 
1406  // - create explicit adjacency to these entities
1407  for( Range::iterator rit = all_adjs.begin(); rit != all_adjs.end(); ++rit )
1408  {
1409  result = add_adjacency( this_ent, *rit );
1410  if( MB_SUCCESS != result ) return result;
1411  }
1412 
1413  return MB_SUCCESS;
1414 }
1415 
1416 ErrorCode AEntityFactory::get_adjacency_ptr( EntityHandle entity, std::vector< EntityHandle >*& ptr )
1417 {
1418  ptr = 0;
1419 
1420  EntitySequence* seq;
1421  ErrorCode rval = thisMB->sequence_manager()->find( entity, seq );
1422  if( MB_SUCCESS != rval || !seq->data()->get_adjacency_data() ) return rval;
1423 
1424  ptr = seq->data()->get_adjacency_data()[entity - seq->data()->start_handle()];
1425  return MB_SUCCESS;
1426 }
1427 
1428 ErrorCode AEntityFactory::get_adjacency_ptr( EntityHandle entity, const std::vector< EntityHandle >*& ptr ) const
1429 {
1430  ptr = 0;
1431 
1432  EntitySequence* seq;
1433  ErrorCode rval = thisMB->sequence_manager()->find( entity, seq );
1434  if( MB_SUCCESS != rval || !seq->data()->get_adjacency_data() ) return rval;
1435 
1436  ptr = seq->data()->get_adjacency_data()[entity - seq->data()->start_handle()];
1437  return MB_SUCCESS;
1438 }
1439 
1440 ErrorCode AEntityFactory::set_adjacency_ptr( EntityHandle entity, std::vector< EntityHandle >* ptr )
1441 {
1442  EntitySequence* seq;
1443  ErrorCode rval = thisMB->sequence_manager()->find( entity, seq );
1444  if( MB_SUCCESS != rval ) return rval;
1445 
1446  if( !seq->data()->get_adjacency_data() && !seq->data()->allocate_adjacency_data() )
1448 
1449  const EntityHandle index = entity - seq->data()->start_handle();
1450  std::vector< EntityHandle >*& ref = seq->data()->get_adjacency_data()[index];
1451  delete ref;
1452  ref = ptr;
1453  return MB_SUCCESS;
1454 }
1455 
1456 void AEntityFactory::get_memory_use( unsigned long long& entity_total, unsigned long long& memory_total )
1457 {
1458  entity_total = memory_total = 0;
1459 
1460  // iterate through each element type
1461  SequenceData* prev_data = 0;
1462  for( EntityType t = MBVERTEX; t != MBENTITYSET; t++ )
1463  {
1466  for( i = seqman.begin(); i != seqman.end(); ++i )
1467  {
1468  if( !( *i )->data()->get_adjacency_data() ) continue;
1469 
1470  if( prev_data != ( *i )->data() )
1471  {
1472  prev_data = ( *i )->data();
1473  memory_total += prev_data->size() * sizeof( AdjacencyVector* );
1474  }
1475 
1476  const AdjacencyVector* vec;
1477  for( EntityHandle h = ( *i )->start_handle(); h <= ( *i )->end_handle(); ++h )
1478  {
1479  get_adjacency_ptr( h, vec );
1480  if( vec ) entity_total += vec->capacity() * sizeof( EntityHandle ) + sizeof( AdjacencyVector );
1481  }
1482  }
1483  }
1484 
1485  memory_total += sizeof( *this ) + entity_total;
1486 }
1487 
1489  unsigned long long& min_per_ent,
1490  unsigned long long& amortized )
1491 {
1492  min_per_ent = amortized = 0;
1493  SequenceData* prev_data = 0;
1495  ErrorCode rval = iter.init( ents_in.begin(), ents_in.end() );
1496  if( MB_SUCCESS != rval ) return rval;
1497 
1498  do
1499  {
1500  AdjacencyVector** array = iter.get_sequence()->data()->get_adjacency_data();
1501  if( !array ) continue;
1502 
1503  EntityID count = iter.get_end_handle() - iter.get_start_handle() + 1;
1504  EntityID data_occ = thisMB->sequence_manager()
1505  ->entity_map( iter.get_sequence()->type() )
1506  .get_occupied_size( iter.get_sequence()->data() );
1507 
1508  if( iter.get_sequence()->data() != prev_data )
1509  {
1510  prev_data = iter.get_sequence()->data();
1511  amortized += sizeof( AdjacencyVector* ) * iter.get_sequence()->data()->size() * count / data_occ;
1512  }
1513 
1514  array += iter.get_start_handle() - iter.get_sequence()->data()->start_handle();
1515  for( EntityID i = 0; i < count; ++i )
1516  {
1517  if( array[i] ) min_per_ent += sizeof( EntityHandle ) * array[i]->capacity() + sizeof( AdjacencyVector );
1518  }
1519  } while( MB_SUCCESS == ( rval = iter.step() ) );
1520 
1521  amortized += min_per_ent;
1522  return ( rval == MB_FAILURE ) ? MB_SUCCESS : rval;
1523 }
1524 
1525 /*!
1526  calling code is notifying this that an entity is going to be deleted
1527  from the database
1528 */
1530 {
1531  if( TYPE_FROM_HANDLE( entity ) == MBVERTEX )
1532  {
1533  std::vector< EntityHandle > adj_entities;
1534  for( int dim = 1; dim < 4; ++dim )
1535  {
1536  ErrorCode rval = get_adjacencies( entity, dim, false, adj_entities );
1537  if( rval != MB_SUCCESS && rval != MB_ENTITY_NOT_FOUND ) return rval;
1538  if( !adj_entities.empty() ) return MB_FAILURE;
1539  }
1540  }
1541 
1542  // remove any references to this entity from other entities
1543  return remove_all_adjacencies( entity, true );
1544 }
1545 
1546 } // namespace moab