Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
MeshSet.hpp
Go to the documentation of this file.
1 #ifndef MB_MESHSET_HPP
2 #define MB_MESHSET_HPP
3 
4 #ifndef IS_BUILDING_MB
5 #error "MB_MeshSet.hpp isn't supposed to be included into an application"
6 #endif
7 
8 #include "moab/Interface.hpp"
9 #include "Internals.hpp"
10 #include "moab/Range.hpp"
11 #include "moab/CN.hpp"
12 
13 #include <cassert>
14 #include <vector>
15 #include <algorithm>
16 #include <iterator>
17 
18 namespace moab
19 {
20 
21 class AEntityFactory;
22 
23 /** \brief Class to implement entity set functionality
24  * \author Jason Kraftcheck <[email protected]>
25  */
26 class MeshSet
27 {
28  public:
29  //! create an empty meshset
30  inline MeshSet();
31  inline MeshSet( unsigned flags );
32 
33  //! destructor
34  inline ~MeshSet();
35 
36  inline ErrorCode set_flags( unsigned flags, EntityHandle my_handle, AEntityFactory* adjacencies );
37 
38  //! get all children pointed to by this meshset
39  inline const EntityHandle* get_children( int& count_out ) const;
40 
41  //! get all parents pointed to by this meshset
42  inline const EntityHandle* get_parents( int& count_out ) const;
43 
44  //! return the number of children pointed to by this meshset
45  inline int num_children() const;
46 
47  //! return the number of parents pointed to by this meshset
48  inline int num_parents() const;
49 
50  //! add a parent to this meshset; returns true if parent was added, 0 if it was
51  //! already a parent of this meshset
52  int add_parent( EntityHandle parent );
53 
54  //! add a child to this meshset; returns true if child was added, 0 if it was
55  //! already a child of this meshset
57 
58  //! remove a parent from this meshset; returns true if parent was removed, 0 if it was
59  //! not a parent of this meshset
60  int remove_parent( EntityHandle parent );
61 
62  //! remove a child from this meshset; returns true if child was removed, 0 if it was
63  //! not a child of this meshset
65 
66  unsigned flags() const
67  {
68  return mFlags;
69  }
70  //! returns whether entities of meshsets know this meshset
71  int tracking() const
72  {
73  return mFlags & MESHSET_TRACK_OWNER;
74  }
75  int set() const
76  {
77  return mFlags & MESHSET_SET;
78  }
79  int ordered() const
80  {
81  return mFlags & MESHSET_ORDERED;
82  }
83  int vector_based() const
84  {
85  return ordered();
86  }
87 
88  //! replace one entity with another in the set (contents and parent/child
89  //! lists); returns whether it was replaced or not
91  const EntityHandle* old_entities,
92  const EntityHandle* new_entities,
93  size_t num_entities,
94  AEntityFactory* mAdjFact );
95 
96  /** Clear *contents* of set (not parents or children) */
97  inline ErrorCode clear( EntityHandle myhandle, AEntityFactory* adjacencies );
98 
99  /** Clear all set lists (contents, parents, and children) */
100  inline ErrorCode clear_all( EntityHandle myhandle, AEntityFactory* adjacencies );
101 
102  /** Get contents data array. NOTE: this may not contain what you expect if not vector_based */
103  inline const EntityHandle* get_contents( size_t& count_out ) const;
104  /** Get contents data array. NOTE: this may not contain what you expect if not vector_based */
105  inline EntityHandle* get_contents( size_t& count_out );
106 
107  /** Get entities contained in set */
108  inline ErrorCode get_entities( std::vector< EntityHandle >& entities ) const;
109 
110  /** Get entities contained in set */
111  inline ErrorCode get_entities( Range& entities ) const;
112 
113  //! get all entities in this MeshSet with the specified type
114  inline ErrorCode get_entities_by_type( EntityType entity_type, std::vector< EntityHandle >& entity_list ) const;
115 
116  inline ErrorCode get_entities_by_type( EntityType type, Range& entity_list ) const;
117 
118  //! return the number of entities with the given type contained in this meshset
119  inline unsigned int num_entities_by_type( EntityType type ) const;
120 
121  inline ErrorCode get_entities_by_dimension( int dimension, std::vector< EntityHandle >& entity_list ) const;
122 
123  inline ErrorCode get_entities_by_dimension( int dimension, Range& entity_list ) const;
124 
125  //! return the number of entities with the given type contained in this meshset
126  inline unsigned int num_entities_by_dimension( int dimension ) const;
127 
128  inline ErrorCode get_non_set_entities( Range& range ) const;
129 
130  /** Test of meshset contains some or all of passed entities
131  *
132  *\param entities Array of entities
133  *\param num_entities Length of array of entities.
134  *\param op - Interface::UNION : Test if set contains any of the input entities
135  * - Interface::INTERSECT : Test if set contains all of the input entities
136  */
137  inline bool contains_entities( const EntityHandle* entities, int num_entities, const int op ) const;
138 
139  //! subtract/intersect/unite meshset_2 from/with/into meshset_1; modifies meshset_1
140  inline ErrorCode subtract( const MeshSet* meshset_2, EntityHandle my_handle, AEntityFactory* adjacencies );
141 
142  ErrorCode intersect( const MeshSet* meshset_2, EntityHandle my_handle, AEntityFactory* adjacencies );
143 
144  inline ErrorCode unite( const MeshSet* meshset_2, EntityHandle my_handle, AEntityFactory* adjacencies );
145 
146  //! add these entities to this meshset
147  inline ErrorCode add_entities( const EntityHandle* entity_handles,
148  const int num_entities,
149  EntityHandle my_handle,
150  AEntityFactory* adjacencies );
151 
152  //! add these entities to this meshset
153  inline ErrorCode add_entities( const Range& entities, EntityHandle my_handle, AEntityFactory* adjacencies );
154 
155  //! add these entities to this meshset
156  inline ErrorCode remove_entities( const Range& entities, EntityHandle my_handle, AEntityFactory* adjacencies );
157 
158  //! remove these entities from this meshset
160  const int num_entities,
161  EntityHandle my_handle,
162  AEntityFactory* adjacencies );
163 
164  //! return the number of entities contained in this meshset
165  inline unsigned int num_entities() const;
166 
167  inline bool empty() const
168  {
169  return mContentCount == ZERO;
170  }
171 
172  unsigned long get_memory_use() const;
173 
174  protected:
175  /** Convert for changing flag values */
176  ErrorCode convert( unsigned flags, EntityHandle my_handle, AEntityFactory* adj );
177 
178  /** Add explicit adjacencies from all contained entities to this (i.e. convert to tracking) */
179  ErrorCode create_adjacencies( EntityHandle myhandle, AEntityFactory* adjacencies );
180 
181  /** Remvoe explicit adjacencies from all contained entities to this (i.e. convert from tracking)
182  */
183  ErrorCode remove_adjacencies( EntityHandle myhandle, AEntityFactory* adjacencies );
184 
185  /** Insert vector of handles into MeshSet */
186  ErrorCode insert_entity_vector( const EntityHandle* vect, size_t len, EntityHandle my_h, AEntityFactory* adj );
187 
188  /** Insert vector of handle range pairs into MeshSet */
189  ErrorCode insert_entity_ranges( const EntityHandle* range_vect,
190  size_t len,
191  EntityHandle my_h,
192  AEntityFactory* adj );
193 
194  /** Insert Range of handles into MeshSet */
195  ErrorCode insert_entity_ranges( const Range& range, EntityHandle my_h, AEntityFactory* adj );
196 
197  /** Remove vector of handles from MeshSet */
198  ErrorCode remove_entity_vector( const EntityHandle* vect, size_t len, EntityHandle my_h, AEntityFactory* adj );
199 
200  /** Remove vector of handle range pairs from MeshSet */
201  ErrorCode remove_entity_ranges( const EntityHandle* range_vect,
202  size_t len,
203  EntityHandle my_h,
204  AEntityFactory* adj );
205 
206  /** Remove Range of handles from MeshSet */
207  ErrorCode remove_entity_ranges( const Range& range, EntityHandle my_h, AEntityFactory* adj );
208 
209  public:
210  //! Possible values of mParentCount and mChildCount
211  enum Count
212  {
213  ZERO = 0,
214  ONE = 1,
215  TWO = 2,
216  MANY = 3
217  };
218  //! If the number of entities is less than 3, store
219  //! the handles directly in the hnd member. Otherwise
220  //! use the ptr member to hold the beginning and end
221  //! of a dynamically allocated array.
223  {
224  EntityHandle hnd[2]; //!< Two handles
225  EntityHandle* ptr[2]; //!< begin and end pointers for array
226  };
227 
228  private:
229  //! Meshset propery flags
230  unsigned char mFlags;
231  //! If less than MANY, the number of parents stored inline in
232  //! parentMeshSets.hnd. If MANY, then parentMeshSets.ptr contains
233  //! array begin and end pointers for a dynamically allocated array
234  //! of parent handles.
235  unsigned mParentCount : 2;
236  //! If less than MANY, the number of children stored inline in
237  //! childMeshSets.hnd. If MANY, then childMeshSets.ptr contains
238  //! array begin and end pointers for a dynamically allocated array
239  //! of child handles.
240  unsigned mChildCount : 2;
241  //! If less than MANY, the number of children stored inline in
242  //! contentList.hnd. If MANY, then contentList.ptr contains
243  //! array begin and end pointers for a dynamically allocated array..
244  unsigned mContentCount : 2;
245  //! Storage for data lists
247 
248  public:
249  /** get dimension of enity */
250  static inline int DIM_FROM_HANDLE( EntityHandle h )
251  {
252  return CN::Dimension( TYPE_FROM_HANDLE( h ) );
253  }
254 
255  /** Get smallest possible handle with specified dimension (first handle for first type of
256  * dimension) */
257  static inline EntityHandle FIRST_OF_DIM( int dim )
258  {
260  }
261 
262  /** Get largest possible handle with specified dimension (largest handle for last type of
263  * dimension) */
264  static inline EntityHandle LAST_OF_DIM( int dim )
265  {
266  return LAST_HANDLE( CN::TypeDimensionMap[dim].second );
267  }
268 
269  /** functor: test if handle is not of type */
271  {
272  inline not_type_test( EntityType type ) : mType( type ) {}
273  inline bool operator()( EntityHandle handle )
274  {
275  return TYPE_FROM_HANDLE( handle ) != mType;
276  }
277  EntityType mType;
278  };
279 
280  /** functor: test if handle is of type */
281  struct type_test
282  {
283  inline type_test( EntityType type ) : mType( type ) {}
284  inline bool operator()( EntityHandle handle )
285  {
286  return TYPE_FROM_HANDLE( handle ) == mType;
287  }
288  EntityType mType;
289  };
290 
291  /** functor: test if handle is not of dimension */
293  {
294  inline not_dim_test( int dimension ) : mDim( dimension ) {}
295  inline bool operator()( EntityHandle handle ) const
296  {
297  return DIM_FROM_HANDLE( handle ) != mDim;
298  }
299  int mDim;
300  };
301 
302  /** functor: test if handle is of dimension */
303  struct dim_test
304  {
305  inline dim_test( int dimension ) : mDim( dimension ) {}
306  inline bool operator()( EntityHandle handle ) const
307  {
308  return DIM_FROM_HANDLE( handle ) == mDim;
309  }
310  int mDim;
311  };
312 
313  /** Iterate over range of handles. That is, given [first_handle,last_handle],
314  * step through all contained values.
315  */
316  struct hdl_iter
317  {
319  hdl_iter( EntityHandle val ) : h( val ) {}
321  {
322  ++h;
323  return *this;
324  }
326  {
327  --h;
328  return *this;
329  }
331  {
332  return hdl_iter( h++ );
333  }
335  {
336  return hdl_iter( h-- );
337  }
338  hdl_iter& operator+=( size_t s )
339  {
340  h += s;
341  return *this;
342  }
343  hdl_iter& operator-=( size_t s )
344  {
345  h -= s;
346  return *this;
347  }
349  {
350  return h;
351  }
352  bool operator==( hdl_iter other ) const
353  {
354  return h == other.h;
355  }
356  bool operator!=( hdl_iter other ) const
357  {
358  return h != other.h;
359  }
360  bool operator<( hdl_iter other ) const
361  {
362  return h < other.h;
363  }
364  bool operator>( hdl_iter other ) const
365  {
366  return h > other.h;
367  }
368  bool operator<=( hdl_iter other ) const
369  {
370  return h <= other.h;
371  }
372  bool operator>=( hdl_iter other ) const
373  {
374  return h >= other.h;
375  }
376 
377  struct iterator_category : public std::random_access_iterator_tag
378  {
379  };
384  };
385 };
386 
388 {
390 }
391 
392 //! create an empty meshset
393 MeshSet::MeshSet() : mFlags( 0 ), mParentCount( ZERO ), mChildCount( ZERO ), mContentCount( ZERO ) {}
394 
395 //! create an empty meshset
396 MeshSet::MeshSet( unsigned flg )
397  : mFlags( (unsigned char)flg ), mParentCount( ZERO ), mChildCount( ZERO ), mContentCount( ZERO )
398 {
399 }
400 
401 //! destructor
403 {
404  if( mChildCount == MANY ) free( childMeshSets.ptr[0] );
405  if( mParentCount == MANY ) free( parentMeshSets.ptr[0] );
406  if( mContentCount == MANY ) free( contentList.ptr[0] );
408 }
409 
410 ErrorCode MeshSet::set_flags( unsigned flg, EntityHandle my_handle, AEntityFactory* adjacencies )
411 {
412  if( ZERO != mContentCount )
413  {
414  ErrorCode result = convert( flg, my_handle, adjacencies );
415  if( MB_SUCCESS != result ) return result;
416  }
417  mFlags = (unsigned char)flg;
418  return MB_SUCCESS;
419 }
420 
421 //! get all children pointed to by this meshset
422 const EntityHandle* MeshSet::get_children( int& count_out ) const
423 {
424  count_out = mChildCount;
425  if( count_out < MANY ) return childMeshSets.hnd;
426 
427  count_out = childMeshSets.ptr[1] - childMeshSets.ptr[0];
428  return childMeshSets.ptr[0];
429 }
430 
431 //! get all parents pointed to by this meshset
432 const EntityHandle* MeshSet::get_parents( int& count_out ) const
433 {
434  count_out = mParentCount;
435  if( count_out < MANY ) return parentMeshSets.hnd;
436 
437  count_out = parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
438  return parentMeshSets.ptr[0];
439 }
440 
441 //! return the number of children pointed to by this meshset
443 {
444  if( mChildCount < MANY )
445  return mChildCount;
446  else
447  return childMeshSets.ptr[1] - childMeshSets.ptr[0];
448 }
449 
450 //! return the number of parents pointed to by this meshset
452 {
453  if( mParentCount < MANY )
454  return mParentCount;
455  else
456  return parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
457 }
458 
459 inline ErrorCode MeshSet::clear( EntityHandle myhandle, AEntityFactory* adjacencies )
460 {
461  if( tracking() ) remove_adjacencies( myhandle, adjacencies );
462  if( mContentCount == MANY ) free( contentList.ptr[0] );
464  return MB_SUCCESS;
465 }
466 
467 inline ErrorCode MeshSet::clear_all( EntityHandle myhandle, AEntityFactory* adjacencies )
468 {
469  ErrorCode rval = clear( myhandle, adjacencies );
470  if( mChildCount == MANY ) free( childMeshSets.ptr[0] );
471  mChildCount = ZERO;
472  if( mParentCount == MANY ) free( parentMeshSets.ptr[0] );
473  mParentCount = ZERO;
474  return rval;
475 }
476 
477 inline const EntityHandle* MeshSet::get_contents( size_t& count_out ) const
478 {
479  if( mContentCount == MANY )
480  {
481  count_out = contentList.ptr[1] - contentList.ptr[0];
482  return contentList.ptr[0];
483  }
484  else
485  {
486  count_out = mContentCount;
487  return contentList.hnd;
488  }
489 }
490 
491 inline EntityHandle* MeshSet::get_contents( size_t& count_out )
492 {
493  if( mContentCount == MANY )
494  {
495  count_out = contentList.ptr[1] - contentList.ptr[0];
496  return contentList.ptr[0];
497  }
498  else
499  {
500  count_out = mContentCount;
501  return contentList.hnd;
502  }
503 }
504 
505 inline ErrorCode MeshSet::get_entities( std::vector< EntityHandle >& entities ) const
506 {
507  size_t count;
508  const EntityHandle* ptr = get_contents( count );
509  if( vector_based() )
510  {
511  size_t old_size = entities.size();
512  entities.resize( count + old_size );
513  std::copy( ptr, ptr + count, entities.begin() + old_size );
514  }
515  else
516  {
517  assert( count % 2 == 0 );
518  for( size_t i = 0; i < count; i += 2 )
519  std::copy( hdl_iter( ptr[i] ), hdl_iter( ptr[i + 1] + 1 ), std::back_inserter( entities ) );
520  }
521  return MB_SUCCESS;
522 }
523 
525 {
526  size_t count;
527  const EntityHandle* ptr = get_contents( count );
528  if( vector_based() )
529  {
530  std::copy( ptr, ptr + count, range_inserter( entities ) );
531  }
532  else
533  {
534  assert( count % 2 == 0 );
535  Range::iterator in = entities.begin();
536  for( size_t i = 0; i < count; i += 2 )
537  in = entities.insert( in, ptr[i], ptr[i + 1] );
538  }
539  return MB_SUCCESS;
540 }
541 
542 //! get all entities in this MeshSet with the specified type
543 inline ErrorCode MeshSet::get_entities_by_type( EntityType type, std::vector< EntityHandle >& entity_list ) const
544 {
545  size_t count;
546  const EntityHandle* ptr = get_contents( count );
547  if( MBMAXTYPE == type )
548  {
549  return get_entities( entity_list );
550  }
551  else if( vector_based() )
552  {
553  std::remove_copy_if( ptr, ptr + count, std::back_inserter( entity_list ), not_type_test( type ) );
554  }
555  else
556  {
557  size_t idx = std::lower_bound( ptr, ptr + count, FIRST_HANDLE( type ) ) - ptr;
558  if( idx < count && TYPE_FROM_HANDLE( ptr[idx] ) == type )
559  {
560  if( idx % 2 )
561  { // only part of first block is of type
562  std::copy( hdl_iter( FIRST_HANDLE( type ) ), hdl_iter( ptr[idx] + 1 ),
563  std::back_inserter( entity_list ) );
564  ++idx;
565  }
566  for( ; idx < count; idx += 2 )
567  {
568  if( TYPE_FROM_HANDLE( ptr[idx + 1] ) == type ) // whole block is of type
569  std::copy( hdl_iter( ptr[idx] ), hdl_iter( ptr[idx + 1] + 1 ), std::back_inserter( entity_list ) );
570  else
571  {
572  if( TYPE_FROM_HANDLE( ptr[idx] ) == type ) // part of last block is of type
573  std::copy( hdl_iter( ptr[idx] ), hdl_iter( LAST_HANDLE( type ) ),
574  std::back_inserter( entity_list ) );
575  break;
576  }
577  }
578  }
579  }
580 
581  return MB_SUCCESS;
582 }
583 
584 inline ErrorCode MeshSet::get_entities_by_type( EntityType type, Range& entity_list ) const
585 {
586  size_t count;
587  const EntityHandle* ptr = get_contents( count );
588  if( MBMAXTYPE == type )
589  {
590  return get_entities( entity_list );
591  }
592  else if( vector_based() )
593  {
594  std::remove_copy_if( ptr, ptr + count, range_inserter( entity_list ), not_type_test( type ) );
595  }
596  else
597  {
598  size_t idx = std::lower_bound( ptr, ptr + count, FIRST_HANDLE( type ) ) - ptr;
599  Range::iterator in = entity_list.begin();
600  if( idx < count && TYPE_FROM_HANDLE( ptr[idx] ) == type )
601  {
602  if( idx % 2 )
603  { // only part of first block is of type
604  in = entity_list.insert( in, FIRST_HANDLE( type ), ptr[idx] );
605  ++idx;
606  }
607  for( ; idx < count; idx += 2 )
608  {
609  if( TYPE_FROM_HANDLE( ptr[idx + 1] ) == type ) // whole block is of type
610  in = entity_list.insert( in, ptr[idx], ptr[idx + 1] );
611  else
612  {
613  if( TYPE_FROM_HANDLE( ptr[idx] ) == type ) // part of last block is of type
614  entity_list.insert( in, ptr[idx], LAST_HANDLE( type ) );
615  break;
616  }
617  }
618  }
619  }
620 
621  return MB_SUCCESS;
622 }
623 
624 //! return the number of entities with the given type contained in this meshset
625 inline unsigned int MeshSet::num_entities_by_type( EntityType type ) const
626 {
627  unsigned int result;
628  size_t count;
629  const EntityHandle* ptr = get_contents( count );
630  if( MBMAXTYPE == type )
631  {
632  return num_entities();
633  }
634  else if( vector_based() )
635  {
636 #ifndef __SUNPRO_CC
637  result = std::count_if( ptr, ptr + count, type_test( type ) );
638 #else
639  std::count_if( ptr, ptr + count, type_test( type ), result );
640 #endif
641  }
642  else
643  {
644  result = 0;
645  size_t idx = std::lower_bound( ptr, ptr + count, FIRST_HANDLE( type ) ) - ptr;
646  if( idx < count && TYPE_FROM_HANDLE( ptr[idx] ) == type )
647  {
648  if( idx % 2 )
649  { // only part of first block is of type
650  result += ptr[idx] - FIRST_HANDLE( type ) + 1;
651  ++idx;
652  }
653  for( ; idx < count; idx += 2 )
654  {
655  if( TYPE_FROM_HANDLE( ptr[idx + 1] ) == type ) // whole block is of type
656  result += ptr[idx + 1] - ptr[idx] + 1;
657  else
658  {
659  if( TYPE_FROM_HANDLE( ptr[idx] ) == type ) // part of last block is of type
660  result += LAST_HANDLE( type ) - ptr[idx] + 1;
661  break;
662  }
663  }
664  }
665  }
666 
667  return result;
668 }
669 
670 inline ErrorCode MeshSet::get_entities_by_dimension( int dimension, std::vector< EntityHandle >& entity_list ) const
671 {
672  size_t count;
673  const EntityHandle* ptr = get_contents( count );
674  if( vector_based() )
675  {
676  std::remove_copy_if( ptr, ptr + count, std::back_inserter( entity_list ), not_dim_test( dimension ) );
677  }
678  else
679  {
680  size_t idx = std::lower_bound( ptr, ptr + count, FIRST_OF_DIM( dimension ) ) - ptr;
681  if( idx < count && DIM_FROM_HANDLE( ptr[idx] ) == dimension )
682  {
683  if( idx % 2 )
684  { // only part of first block is of type
685  std::copy( hdl_iter( FIRST_OF_DIM( dimension ) ), hdl_iter( ptr[idx] + 1 ),
686  std::back_inserter( entity_list ) );
687  ++idx;
688  }
689  for( ; idx < count; idx += 2 )
690  {
691  if( DIM_FROM_HANDLE( ptr[idx + 1] ) == dimension ) // whole block is of type
692  std::copy( hdl_iter( ptr[idx] ), hdl_iter( ptr[idx + 1] + 1 ), std::back_inserter( entity_list ) );
693  else
694  {
695  if( DIM_FROM_HANDLE( ptr[idx] ) == dimension ) // part of last block is of type
696  std::copy( hdl_iter( ptr[idx] ), hdl_iter( LAST_OF_DIM( dimension ) ),
697  std::back_inserter( entity_list ) );
698  break;
699  }
700  }
701  }
702  }
703 
704  return MB_SUCCESS;
705 }
706 
707 inline ErrorCode MeshSet::get_entities_by_dimension( int dimension, Range& entity_list ) const
708 {
709  size_t count;
710  const EntityHandle* ptr = get_contents( count );
711  if( vector_based() )
712  {
713  std::remove_copy_if( ptr, ptr + count, range_inserter( entity_list ), not_dim_test( dimension ) );
714  }
715  else
716  {
717  size_t idx = std::lower_bound( ptr, ptr + count, FIRST_OF_DIM( dimension ) ) - ptr;
718  Range::iterator in = entity_list.begin();
719  if( idx < count && DIM_FROM_HANDLE( ptr[idx] ) == dimension )
720  {
721  if( idx % 2 )
722  { // only part of first block is of type
723  in = entity_list.insert( in, FIRST_OF_DIM( dimension ), ptr[idx] );
724  ++idx;
725  }
726  for( ; idx < count; idx += 2 )
727  {
728  if( DIM_FROM_HANDLE( ptr[idx + 1] ) == dimension ) // whole block is of type
729  in = entity_list.insert( in, ptr[idx], ptr[idx + 1] );
730  else
731  {
732  if( DIM_FROM_HANDLE( ptr[idx] ) == dimension ) // part of last block is of type
733  entity_list.insert( in, ptr[idx], LAST_OF_DIM( dimension ) );
734  break;
735  }
736  }
737  }
738  }
739 
740  return MB_SUCCESS;
741 }
742 
743 //! return the number of entities with the given type contained in this meshset
744 inline unsigned int MeshSet::num_entities_by_dimension( int dimension ) const
745 {
746  unsigned int result;
747  size_t count;
748  const EntityHandle* ptr = get_contents( count );
749  if( vector_based() )
750  {
751 #ifndef __SUNPRO_CC
752  result = std::count_if( ptr, ptr + count, dim_test( dimension ) );
753 #else
754  std::count_if( ptr, ptr + count, dim_test( dimension ), result );
755 #endif
756  }
757  else
758  {
759  result = 0;
760  size_t idx = std::lower_bound( ptr, ptr + count, FIRST_OF_DIM( dimension ) ) - ptr;
761  if( idx < count && DIM_FROM_HANDLE( ptr[idx] ) == dimension )
762  {
763  if( idx % 2 )
764  { // only part of first block is of type
765  result += ptr[idx] - FIRST_OF_DIM( dimension ) + 1;
766  ++idx;
767  }
768  for( ; idx < count; idx += 2 )
769  {
770  if( DIM_FROM_HANDLE( ptr[idx + 1] ) == dimension ) // whole block is of type
771  result += ptr[idx + 1] - ptr[idx] + 1;
772  else
773  {
774  if( DIM_FROM_HANDLE( ptr[idx] ) == dimension ) // part of last block is of type
775  result += LAST_OF_DIM( dimension ) - ptr[idx] + 1;
776  break;
777  }
778  }
779  }
780  }
781 
782  return result;
783 }
784 
786 {
787  size_t count;
788  const EntityHandle* ptr = get_contents( count );
789  if( vector_based() )
790  {
791  std::remove_copy_if( ptr, ptr + count, range_inserter( range ), type_test( MBENTITYSET ) );
792  }
793  else
794  {
795  Range::iterator in = range.begin();
796  for( size_t idx = 0; idx < count; idx += 2 )
797  {
798  if( TYPE_FROM_HANDLE( ptr[idx + 1] ) != MBENTITYSET )
799  in = range.insert( in, ptr[idx], ptr[idx + 1] );
800  else
801  {
802  if( TYPE_FROM_HANDLE( ptr[idx] ) != MBENTITYSET )
803  in = range.insert( in, ptr[idx], LAST_HANDLE( MBENTITYSET - 1 ) );
804  break;
805  }
806  }
807  }
808 
809  return MB_SUCCESS;
810 }
811 
812 inline bool MeshSet::contains_entities( const EntityHandle* entities, int num_ents, const int op ) const
813 {
814  size_t count;
815  const EntityHandle* const ptr = get_contents( count );
816  const EntityHandle* const end = ptr + count;
817  size_t found_count = 0;
818  if( vector_based() )
819  {
820  for( int i = 0; i < num_ents; ++i )
821  if( std::find( ptr, end, entities[i] ) < end ) ++found_count;
822  }
823  else
824  {
825  assert( 0 == count % 2 );
826  for( int i = 0; i < num_ents; ++i )
827  {
828  const unsigned long idx = std::lower_bound( ptr, end, entities[i] ) - ptr;
829  if( idx < count && ( idx % 2 != 0 || ptr[idx] == entities[i] ) ) ++found_count;
830  }
831  }
832 
833  return found_count >= ( ( Interface::INTERSECT == op ) ? (unsigned)num_ents : 1u );
834 }
835 
836 //! subtract/intersect/unite meshset_2 from/with/into meshset_1; modifies meshset_1
837 inline ErrorCode MeshSet::subtract( const MeshSet* meshset_2, EntityHandle my_handle, AEntityFactory* adjacencies )
838 {
839  size_t count;
840  const EntityHandle* const ptr = meshset_2->get_contents( count );
841  if( meshset_2->vector_based() )
842  return remove_entity_vector( ptr, count, my_handle, adjacencies );
843  else
844  return remove_entity_ranges( ptr, count, my_handle, adjacencies );
845 }
846 
847 inline ErrorCode MeshSet::unite( const MeshSet* meshset_2, EntityHandle my_handle, AEntityFactory* adjacencies )
848 {
849  size_t count;
850  const EntityHandle* const ptr = meshset_2->get_contents( count );
851  if( meshset_2->vector_based() )
852  return insert_entity_vector( ptr, count, my_handle, adjacencies );
853  else
854  return insert_entity_ranges( ptr, count, my_handle, adjacencies );
855 }
856 
857 //! add these entities to this meshset
858 inline ErrorCode MeshSet::add_entities( const EntityHandle* entity_handles,
859  const int num_ents,
860  EntityHandle my_handle,
861  AEntityFactory* adjacencies )
862 {
863  return insert_entity_vector( entity_handles, num_ents, my_handle, adjacencies );
864 }
865 
866 //! add these entities to this meshset
867 inline ErrorCode MeshSet::add_entities( const Range& entities, EntityHandle my_handle, AEntityFactory* adjacencies )
868 {
869  return insert_entity_ranges( entities, my_handle, adjacencies );
870 }
871 
872 //! add these entities to this meshset
874 {
875  return remove_entity_ranges( entities, my_handle, adjacencies );
876 }
877 
878 //! remove these entities from this meshset
880  const int num_ents,
881  EntityHandle my_handle,
882  AEntityFactory* adjacencies )
883 {
884  return remove_entity_vector( entities, num_ents, my_handle, adjacencies );
885 }
886 
887 //! return the number of entities contained in this meshset
888 unsigned int MeshSet::num_entities() const
889 {
890  size_t count;
891  const EntityHandle* list = get_contents( count );
892  if( vector_based() ) return count;
893 
894  int result = 0;
895  const EntityHandle* const end = list + count;
896  for( ; list < end; list += 2 )
897  result += list[1] - list[0] + 1;
898  return result;
899 }
900 
901 } // namespace moab
902 
903 #endif