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 <assert.h>
14 #include <vector>
15 #include <algorithm>
16 #include <iterator>
17 
18 namespace moab {
19 
20 class AEntityFactory;
21 
22 /** \brief Class to implement entity set functionality
23   * \author Jason Kraftcheck <kraftche@cae.wisc.edu>
24   */
25 class MeshSet
26 {
27 public:
28 
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 
39     //! get all children pointed to by this meshset
40   inline const EntityHandle* get_children( int& count_out ) const ;
41 
42     //! get all parents pointed to by this meshset
43   inline const EntityHandle* get_parents( int& count_out ) const;
44 
45     //! return the number of children pointed to by this meshset
46   inline int num_children() const ;
47 
48     //! return the number of parents pointed to by this meshset
49   inline int num_parents() const;
50 
51     //! add a parent to this meshset; returns true if parent was added, 0 if it was
52     //! already a parent of this meshset
53   int add_parent(EntityHandle parent);
54 
55     //! add a child to this meshset; returns true if child was added, 0 if it was
56     //! already a child of this meshset
57   int add_child(EntityHandle child);
58 
59     //! remove a parent from this meshset; returns true if parent was removed, 0 if it was
60     //! not a parent of this meshset
61   int remove_parent(EntityHandle parent);
62 
63     //! remove a child from this meshset; returns true if child was removed, 0 if it was
64     //! not a child of this meshset
65   int remove_child(EntityHandle child);
66 
flags() const67   unsigned flags() const { return mFlags; }
68   //! returns whether entities of meshsets know this meshset
tracking() const69   int tracking()     const { return mFlags & MESHSET_TRACK_OWNER; }
set() const70   int set()          const { return mFlags & MESHSET_SET; }
ordered() const71   int ordered()      const { return mFlags & MESHSET_ORDERED; }
vector_based() const72   int vector_based() const { return ordered(); }
73 
74     //! replace one entity with another in the set (contents and parent/child
75     //! lists); returns whether it was replaced or not
76   ErrorCode replace_entities(EntityHandle my_handle,
77                                const EntityHandle *old_entities,
78                                const EntityHandle *new_entities,
79                                size_t num_entities,
80                                AEntityFactory* mAdjFact);
81 
82     /** Clear *contents* of set (not parents or children) */
83   inline ErrorCode clear( EntityHandle myhandle, AEntityFactory* adjacencies );
84 
85     /** Clear all set lists (contents, parents, and children) */
86   inline ErrorCode clear_all( EntityHandle myhandle, AEntityFactory* adjacencies );
87 
88     /** Get contents data array.  NOTE: this may not contain what you expect if not vector_based */
89   inline const EntityHandle* get_contents( size_t& count_out ) const;
90     /** Get contents data array.  NOTE: this may not contain what you expect if not vector_based */
91   inline EntityHandle* get_contents( size_t& count_out );
92 
93     /** Get entities contained in set */
94   inline ErrorCode get_entities(std::vector<EntityHandle>& entities) const;
95 
96     /** Get entities contained in set */
97   inline ErrorCode get_entities( Range& entities ) const;
98 
99     //! get all entities in this MeshSet with the specified type
100   inline ErrorCode get_entities_by_type(EntityType entity_type, std::vector<EntityHandle> &entity_list) const;
101 
102   inline ErrorCode get_entities_by_type( EntityType type, Range& entity_list) const;
103 
104     //! return the number of entities with the given type contained in this meshset
105   inline unsigned int num_entities_by_type(EntityType type) const;
106 
107   inline ErrorCode get_entities_by_dimension( int dimension, std::vector<EntityHandle> &entity_list) const;
108 
109   inline ErrorCode get_entities_by_dimension( int dimension, Range& entity_list) const;
110 
111     //! return the number of entities with the given type contained in this meshset
112   inline unsigned int num_entities_by_dimension(int dimension) const;
113 
114   inline ErrorCode get_non_set_entities( Range& range ) const;
115 
116   /** Test of meshset contains some or all of passed entities
117    *
118    *\param entities Array of entities
119    *\param num_entities Length of array of entities.
120    *\param op - Interface::UNION     : Test if set contains any of the input entities
121    *          - Interface::INTERSECT : Test if set contains all of the input entities
122    */
123   inline bool contains_entities(const EntityHandle *entities, int num_entities, const int op) const;
124 
125 
126   //! subtract/intersect/unite meshset_2 from/with/into meshset_1; modifies meshset_1
127   inline ErrorCode subtract(const MeshSet *meshset_2,
128                                EntityHandle my_handle,
129                                AEntityFactory* adjacencies);
130 
131   ErrorCode intersect(const MeshSet *meshset_2,
132                                 EntityHandle my_handle,
133                                 AEntityFactory* adjacencies);
134 
135   inline ErrorCode unite(const MeshSet *meshset_2,
136                             EntityHandle my_handle,
137                             AEntityFactory* adjacencies);
138 
139   //! add these entities to this meshset
140   inline ErrorCode add_entities(const EntityHandle *entity_handles,
141                                    const int num_entities,
142                                    EntityHandle my_handle,
143                                    AEntityFactory* adjacencies);
144 
145     //! add these entities to this meshset
146   inline ErrorCode add_entities(const Range &entities,
147                                    EntityHandle my_handle,
148                                    AEntityFactory* adjacencies);
149 
150     //! add these entities to this meshset
151   inline ErrorCode remove_entities(const Range& entities,
152                                       EntityHandle my_handle,
153                                       AEntityFactory* adjacencies);
154 
155 
156     //! remove these entities from this meshset
157   inline ErrorCode remove_entities(const EntityHandle *entities,
158                                       const int num_entities,
159                                       EntityHandle my_handle,
160                                       AEntityFactory* adjacencies);
161 
162     //! return the number of entities contained in this meshset
163   inline unsigned int num_entities() const;
164 
empty() const165   inline bool empty() const { return mContentCount == ZERO; }
166 
167   unsigned long get_memory_use() const;
168 
169 protected:
170 
171   /** Convert for changing flag values */
172   ErrorCode convert( unsigned flags, EntityHandle my_handle, AEntityFactory* adj );
173 
174   /** Add explicit adjacencies from all contained entities to this (i.e. convert to tracking) */
175   ErrorCode create_adjacencies( EntityHandle myhandle, AEntityFactory* adjacencies );
176 
177   /** Remvoe explicit adjacencies from all contained entities to this (i.e. convert from tracking) */
178   ErrorCode remove_adjacencies( EntityHandle myhandle, AEntityFactory* adjacencies );
179 
180   /** Insert vector of handles into MeshSet */
181   ErrorCode insert_entity_vector( const EntityHandle* vect, size_t len, EntityHandle my_h, AEntityFactory* adj );
182 
183   /** Insert vector of handle range pairs into MeshSet */
184   ErrorCode insert_entity_ranges( const EntityHandle* range_vect, size_t len, EntityHandle my_h, AEntityFactory* adj );
185 
186   /** Insert Range of handles into MeshSet */
187   ErrorCode insert_entity_ranges( const Range& range, EntityHandle my_h, AEntityFactory* adj );
188 
189   /** Remove vector of handles from MeshSet */
190   ErrorCode remove_entity_vector( const EntityHandle* vect, size_t len, EntityHandle my_h, AEntityFactory* adj );
191 
192   /** Remove vector of handle range pairs from MeshSet */
193   ErrorCode remove_entity_ranges( const EntityHandle* range_vect, size_t len, EntityHandle my_h, AEntityFactory* adj );
194 
195   /** Remove Range of handles from MeshSet */
196   ErrorCode remove_entity_ranges( const Range& range, EntityHandle my_h, AEntityFactory* adj );
197 
198 public:
199     //! Possible values of mParentCount and mChildCount
200   enum Count { ZERO=0, ONE=1, TWO=2, MANY=3 };
201     //! If the number of entities is less than 3, store
202     //! the handles directly in the hnd member.  Otherwise
203     //! use the ptr member to hold the beginning and end
204     //! of a dynamically allocated array.
205   union CompactList {
206     EntityHandle hnd[2];  //!< Two handles
207     EntityHandle* ptr[2]; //!< begin and end pointers for array
208   };
209 
210 private:
211   //!Meshset propery flags
212   unsigned char mFlags;
213   //! If less than MANY, the number of parents stored inline in
214   //! parentMeshSets.hnd.  If MANY, then parentMeshSets.ptr contains
215   //! array begin and end pointers for a dynamically allocated array
216   //! of parent handles.
217   unsigned mParentCount : 2;
218   //! If less than MANY, the number of children stored inline in
219   //! childMeshSets.hnd.  If MANY, then childMeshSets.ptr contains
220   //! array begin and end pointers for a dynamically allocated array
221   //! of child handles.
222   unsigned mChildCount : 2;
223   //! If less than MANY, the number of children stored inline in
224   //! contentList.hnd.  If MANY, then contentList.ptr contains
225   //! array begin and end pointers for a dynamically allocated array..
226   unsigned mContentCount : 2;
227   //! Storage for data lists
228   CompactList parentMeshSets, childMeshSets, contentList;
229 
230 public:
231     /** get dimension of enity */
DIM_FROM_HANDLE(EntityHandle h)232   static inline int DIM_FROM_HANDLE( EntityHandle h )
233     { return CN::Dimension( TYPE_FROM_HANDLE( h ) ); }
234 
235     /** Get smallest possible handle with specified dimension (first handle for first type of dimension) */
FIRST_OF_DIM(int dim)236   static inline EntityHandle FIRST_OF_DIM( int dim )
237     { return FIRST_HANDLE( CN::TypeDimensionMap[dim].first ); }
238 
239     /** Get largest possible handle with specified dimension (largest handle for last type of dimension) */
LAST_OF_DIM(int dim)240   static inline EntityHandle LAST_OF_DIM( int dim )
241     { return LAST_HANDLE( CN::TypeDimensionMap[dim].second ); }
242 
243     /** functor: test if handle is not of type */
244   struct not_type_test {
not_type_testmoab::MeshSet::not_type_test245       inline not_type_test( EntityType type ) : mType(type) {}
operator ()moab::MeshSet::not_type_test246       inline bool operator()( EntityHandle handle )
247         { return TYPE_FROM_HANDLE(handle) != mType; }
248       EntityType mType;
249   };
250 
251     /** functor: test if handle is of type */
252   struct type_test {
type_testmoab::MeshSet::type_test253       inline type_test( EntityType type ) : mType(type) {}
operator ()moab::MeshSet::type_test254       inline bool operator()( EntityHandle handle )
255         { return TYPE_FROM_HANDLE(handle) == mType; }
256       EntityType mType;
257   };
258 
259     /** functor: test if handle is not of dimension */
260   struct not_dim_test {
not_dim_testmoab::MeshSet::not_dim_test261       inline not_dim_test( int dimension ) : mDim(dimension) {}
operator ()moab::MeshSet::not_dim_test262       inline bool operator()( EntityHandle handle ) const
263         { return DIM_FROM_HANDLE(handle) != mDim; }
264       int mDim;
265   };
266 
267     /** functor: test if handle is of dimension */
268   struct dim_test {
dim_testmoab::MeshSet::dim_test269       inline dim_test( int dimension ) : mDim(dimension) {}
operator ()moab::MeshSet::dim_test270       inline bool operator()( EntityHandle handle ) const
271         { return DIM_FROM_HANDLE(handle) == mDim; }
272       int mDim;
273   };
274 
275     /** Iterate over range of handles.  That is, given [first_handle,last_handle],
276      *  step through all contained values.
277      */
278   struct hdl_iter {
279     EntityHandle h;
hdl_itermoab::MeshSet::hdl_iter280     hdl_iter( EntityHandle val ) : h(val) {}
operator ++moab::MeshSet::hdl_iter281     hdl_iter& operator++() { ++h; return *this; }
operator --moab::MeshSet::hdl_iter282     hdl_iter& operator--() { --h; return *this; }
operator ++moab::MeshSet::hdl_iter283     hdl_iter operator++(int) { return hdl_iter(h++); }
operator --moab::MeshSet::hdl_iter284     hdl_iter operator--(int) { return hdl_iter(h--); }
operator +=moab::MeshSet::hdl_iter285     hdl_iter& operator+=(size_t s) { h += s; return *this; }
operator -=moab::MeshSet::hdl_iter286     hdl_iter& operator-=(size_t s) { h -= s; return *this; }
operator *moab::MeshSet::hdl_iter287     EntityHandle operator*() const { return h; }
operator ==moab::MeshSet::hdl_iter288     bool operator==(hdl_iter other) const { return h == other.h; }
operator !=moab::MeshSet::hdl_iter289     bool operator!=(hdl_iter other) const { return h != other.h; }
operator <moab::MeshSet::hdl_iter290     bool operator< (hdl_iter other) const { return h <  other.h; }
operator >moab::MeshSet::hdl_iter291     bool operator> (hdl_iter other) const { return h >  other.h; }
operator <=moab::MeshSet::hdl_iter292     bool operator<=(hdl_iter other) const { return h <= other.h; }
operator >=moab::MeshSet::hdl_iter293     bool operator>=(hdl_iter other) const { return h >= other.h; }
294 
295     struct iterator_category : public std::random_access_iterator_tag { };
296     typedef EntityID difference_type;
297     typedef EntityHandle value_type;
298     typedef EntityHandle* pointer;
299     typedef EntityHandle& reference;
300   };
301 
302 };
303 
304 inline MeshSet::hdl_iter::difference_type
operator -(const MeshSet::hdl_iter & a,const MeshSet::hdl_iter & b)305  operator-( const MeshSet::hdl_iter &a, const MeshSet::hdl_iter &b )
306   { return (MeshSet::hdl_iter::difference_type)a.h
307          - (MeshSet::hdl_iter::difference_type)b.h; }
308 
309 
310   //! create an empty meshset
MeshSet()311 MeshSet::MeshSet()
312   : mFlags(0), mParentCount(ZERO), mChildCount(ZERO), mContentCount(ZERO)
313 { }
314 
315   //! create an empty meshset
MeshSet(unsigned flg)316 MeshSet::MeshSet(unsigned flg)
317         : mFlags((unsigned char)flg), mParentCount(ZERO), mChildCount(ZERO), mContentCount(ZERO)
318 { }
319 
320   //! destructor
~MeshSet()321 MeshSet::~MeshSet()
322 {
323   if (mChildCount == MANY)
324     free( childMeshSets.ptr[0] );
325   if (mParentCount == MANY)
326     free( parentMeshSets.ptr[0] );
327   if (mContentCount == MANY)
328     free( contentList.ptr[0] );
329   mChildCount = mParentCount = mContentCount = ZERO;
330 }
331 
set_flags(unsigned flg,EntityHandle my_handle,AEntityFactory * adjacencies)332 ErrorCode MeshSet::set_flags( unsigned flg, EntityHandle my_handle, AEntityFactory* adjacencies )
333 {
334   if(ZERO != mContentCount) {
335     ErrorCode result = convert(flg, my_handle, adjacencies);
336     if(MB_SUCCESS != result) return result;
337   }
338   mFlags = (unsigned char)flg;
339   return MB_SUCCESS;
340 }
341 
342 
343 //! get all children pointed to by this meshset
get_children(int & count_out) const344 const EntityHandle* MeshSet::get_children( int& count_out ) const
345 {
346   count_out = mChildCount;
347   if (count_out < MANY)
348     return childMeshSets.hnd;
349 
350   count_out = childMeshSets.ptr[1] - childMeshSets.ptr[0];
351   return childMeshSets.ptr[0];
352 }
353 
354 //! get all parents pointed to by this meshset
get_parents(int & count_out) const355 const EntityHandle* MeshSet::get_parents( int& count_out ) const
356 {
357   count_out = mParentCount;
358   if (count_out < MANY)
359     return parentMeshSets.hnd;
360 
361   count_out = parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
362   return parentMeshSets.ptr[0];
363 }
364 
365 //! return the number of children pointed to by this meshset
num_children() const366 int MeshSet::num_children() const
367 {
368   if (mChildCount < MANY)
369     return mChildCount;
370   else
371     return childMeshSets.ptr[1] - childMeshSets.ptr[0];
372 }
373 
374 //! return the number of parents pointed to by this meshset
num_parents() const375 int MeshSet::num_parents() const
376 {
377   if (mParentCount < MANY)
378     return mParentCount;
379   else
380     return parentMeshSets.ptr[1] - parentMeshSets.ptr[0];
381 }
382 
clear(EntityHandle myhandle,AEntityFactory * adjacencies)383 inline ErrorCode MeshSet::clear( EntityHandle myhandle, AEntityFactory* adjacencies )
384 {
385   if (tracking())
386     remove_adjacencies( myhandle, adjacencies );
387   if (mContentCount == MANY)
388     free( contentList.ptr[0] );
389   mContentCount = ZERO;
390   return MB_SUCCESS;
391 }
392 
clear_all(EntityHandle myhandle,AEntityFactory * adjacencies)393 inline ErrorCode MeshSet::clear_all( EntityHandle myhandle, AEntityFactory* adjacencies )
394 {
395   ErrorCode rval = clear( myhandle, adjacencies );
396   if (mChildCount == MANY)
397     free( childMeshSets.ptr[0] );
398   mChildCount = ZERO;
399   if (mParentCount == MANY)
400     free( parentMeshSets.ptr[0] );
401   mParentCount = ZERO;
402   return rval;
403 }
404 
get_contents(size_t & count_out) const405 inline const EntityHandle* MeshSet::get_contents( size_t& count_out ) const
406 {
407   if (mContentCount == MANY) {
408     count_out = contentList.ptr[1] - contentList.ptr[0];
409     return contentList.ptr[0];
410   }
411   else {
412     count_out = mContentCount;
413     return contentList.hnd;
414   }
415 }
416 
get_contents(size_t & count_out)417 inline EntityHandle* MeshSet::get_contents( size_t& count_out )
418 {
419   if (mContentCount == MANY) {
420     count_out = contentList.ptr[1] - contentList.ptr[0];
421     return contentList.ptr[0];
422   }
423   else {
424     count_out = mContentCount;
425     return contentList.hnd;
426   }
427 }
428 
get_entities(std::vector<EntityHandle> & entities) const429 inline ErrorCode MeshSet::get_entities(std::vector<EntityHandle>& entities) const
430 {
431   size_t count;
432   const EntityHandle* ptr = get_contents( count );
433   if (vector_based()) {
434     size_t old_size = entities.size();
435     entities.resize( count+old_size );
436     std::copy( ptr, ptr+count, entities.begin()+old_size );
437   }
438   else {
439     assert(count%2 == 0);
440     for (size_t i = 0; i < count; i += 2)
441       std::copy( hdl_iter(ptr[i]), hdl_iter(ptr[i+1]+1), std::back_inserter(entities) );
442   }
443   return MB_SUCCESS;
444 }
445 
get_entities(Range & entities) const446 inline ErrorCode MeshSet::get_entities(Range& entities) const
447 {
448   size_t count;
449   const EntityHandle* ptr = get_contents( count );
450   if (vector_based()) {
451     std::copy( ptr, ptr+count, range_inserter(entities) );
452   }
453   else {
454     assert(count%2 == 0);
455     Range::iterator in = entities.begin();
456     for (size_t i = 0; i < count; i += 2)
457       in = entities.insert( in, ptr[i], ptr[i+1] );
458   }
459   return MB_SUCCESS;
460 }
461 
462 
463   //! get all entities in this MeshSet with the specified type
get_entities_by_type(EntityType type,std::vector<EntityHandle> & entity_list) const464 inline ErrorCode MeshSet::get_entities_by_type(EntityType type,
465                                                std::vector<EntityHandle> &entity_list
466                                                ) const
467 {
468   size_t count;
469   const EntityHandle* ptr = get_contents( count );
470   if (MBMAXTYPE == type) {
471     return get_entities( entity_list);
472   }
473   else if (vector_based()) {
474     std::remove_copy_if( ptr, ptr+count,
475                          std::back_inserter( entity_list ),
476                          not_type_test(type) );
477   }
478   else {
479     size_t idx = std::lower_bound( ptr, ptr+count, FIRST_HANDLE(type) ) - ptr;
480     if (idx < count && TYPE_FROM_HANDLE(ptr[idx]) == type) {
481       if (idx % 2) { // only part of first block is of type
482         std::copy( hdl_iter(FIRST_HANDLE(type)), hdl_iter(ptr[idx]+1), std::back_inserter( entity_list ) );
483         ++idx;
484       }
485       for (; idx < count; idx += 2) {
486         if (TYPE_FROM_HANDLE(ptr[idx+1]) == type) // whole block is of type
487           std::copy( hdl_iter(ptr[idx]), hdl_iter(ptr[idx+1]+1), std::back_inserter( entity_list ) );
488         else {
489           if (TYPE_FROM_HANDLE(ptr[idx]) == type) // part of last block is of type
490             std::copy( hdl_iter(ptr[idx]), hdl_iter(LAST_HANDLE(type)), std::back_inserter( entity_list ) );
491           break;
492         }
493       }
494     }
495   }
496 
497   return MB_SUCCESS;
498 }
499 
500 
get_entities_by_type(EntityType type,Range & entity_list) const501 inline ErrorCode MeshSet::get_entities_by_type( EntityType type,
502                                                     Range& entity_list) const
503 {
504   size_t count;
505   const EntityHandle* ptr = get_contents( count );
506   if (MBMAXTYPE == type) {
507     return get_entities( entity_list );
508   }
509   else if (vector_based()) {
510     std::remove_copy_if( ptr, ptr+count,
511                          range_inserter( entity_list ),
512                          not_type_test(type) );
513   }
514   else {
515     size_t idx = std::lower_bound( ptr, ptr+count, FIRST_HANDLE(type) ) - ptr;
516     Range::iterator in = entity_list.begin();
517     if (idx < count && TYPE_FROM_HANDLE(ptr[idx]) == type) {
518       if (idx % 2) { // only part of first block is of type
519         in = entity_list.insert( in, FIRST_HANDLE(type), ptr[idx] );
520         ++idx;
521       }
522       for (; idx < count; idx += 2) {
523         if (TYPE_FROM_HANDLE(ptr[idx+1]) == type) // whole block is of type
524           in = entity_list.insert( in, ptr[idx], ptr[idx+1] );
525         else {
526           if (TYPE_FROM_HANDLE(ptr[idx]) == type) // part of last block is of type
527             entity_list.insert( in, ptr[idx], LAST_HANDLE(type) );
528           break;
529         }
530       }
531     }
532   }
533 
534   return MB_SUCCESS;
535 }
536 
537   //! return the number of entities with the given type contained in this meshset
num_entities_by_type(EntityType type) const538 inline unsigned int MeshSet::num_entities_by_type(EntityType type) const
539 {
540   unsigned int result;
541   size_t count;
542   const EntityHandle* ptr = get_contents( count );
543   if (MBMAXTYPE == type) {
544     return num_entities( );
545   }
546   else if (vector_based()) {
547     #ifndef __SUNPRO_CC
548       result = std::count_if( ptr, ptr+count, type_test(type) );
549     #else
550       std::count_if( ptr, ptr+count, type_test(type), result );
551     #endif
552   }
553   else {
554     result = 0;
555     size_t idx = std::lower_bound( ptr, ptr+count, FIRST_HANDLE(type) ) - ptr;
556     if (idx < count && TYPE_FROM_HANDLE(ptr[idx]) == type) {
557       if (idx % 2) { // only part of first block is of type
558         result += ptr[idx] - FIRST_HANDLE(type) + 1;
559         ++idx;
560       }
561       for (; idx < count; idx += 2) {
562         if (TYPE_FROM_HANDLE(ptr[idx+1]) == type) // whole block is of type
563           result += ptr[idx+1] - ptr[idx] + 1;
564         else {
565           if (TYPE_FROM_HANDLE(ptr[idx]) == type) // part of last block is of type
566             result += LAST_HANDLE(type) - ptr[idx] + 1;
567           break;
568         }
569       }
570     }
571   }
572 
573   return result;
574 }
575 
get_entities_by_dimension(int dimension,std::vector<EntityHandle> & entity_list) const576 inline ErrorCode MeshSet::get_entities_by_dimension( int dimension,
577                                                          std::vector<EntityHandle> &entity_list
578                                                          ) const
579 {
580   size_t count;
581   const EntityHandle* ptr = get_contents( count );
582   if (vector_based()) {
583     std::remove_copy_if( ptr, ptr+count,
584                          std::back_inserter( entity_list ),
585                          not_dim_test(dimension) );
586   }
587   else {
588     size_t idx = std::lower_bound( ptr, ptr+count, FIRST_OF_DIM(dimension) ) - ptr;
589     if (idx < count && DIM_FROM_HANDLE(ptr[idx]) == dimension) {
590       if (idx % 2) { // only part of first block is of type
591         std::copy( hdl_iter(FIRST_OF_DIM(dimension)), hdl_iter(ptr[idx]+1), std::back_inserter( entity_list ) );
592         ++idx;
593       }
594       for (; idx < count; idx += 2) {
595         if (DIM_FROM_HANDLE(ptr[idx+1]) == dimension) // whole block is of type
596           std::copy( hdl_iter(ptr[idx]), hdl_iter(ptr[idx+1]+1), std::back_inserter( entity_list ) );
597         else {
598           if (DIM_FROM_HANDLE(ptr[idx]) == dimension) // part of last block is of type
599             std::copy( hdl_iter(ptr[idx]), hdl_iter(LAST_OF_DIM(dimension)), std::back_inserter( entity_list ) );
600           break;
601         }
602       }
603     }
604   }
605 
606   return MB_SUCCESS;
607 }
608 
609 
get_entities_by_dimension(int dimension,Range & entity_list) const610 inline ErrorCode MeshSet::get_entities_by_dimension( int dimension,
611                                                          Range& entity_list) const
612 {
613   size_t count;
614   const EntityHandle* ptr = get_contents( count );
615   if (vector_based()) {
616     std::remove_copy_if( ptr, ptr+count,
617                          range_inserter( entity_list ),
618                          not_dim_test(dimension) );
619   }
620   else {
621     size_t idx = std::lower_bound( ptr, ptr+count, FIRST_OF_DIM(dimension) ) - ptr;
622     Range::iterator in = entity_list.begin();
623     if (idx < count && DIM_FROM_HANDLE(ptr[idx]) == dimension) {
624       if (idx % 2) { // only part of first block is of type
625         in = entity_list.insert( in, FIRST_OF_DIM(dimension), ptr[idx] );
626         ++idx;
627       }
628       for (; idx < count; idx += 2) {
629         if (DIM_FROM_HANDLE(ptr[idx+1]) == dimension) // whole block is of type
630           in = entity_list.insert( in, ptr[idx], ptr[idx+1] );
631         else {
632           if (DIM_FROM_HANDLE(ptr[idx]) == dimension) // part of last block is of type
633             entity_list.insert( in, ptr[idx], LAST_OF_DIM(dimension) );
634           break;
635         }
636       }
637     }
638   }
639 
640   return MB_SUCCESS;
641 }
642 
643   //! return the number of entities with the given type contained in this meshset
num_entities_by_dimension(int dimension) const644 inline unsigned int MeshSet::num_entities_by_dimension(int dimension) const
645 {
646   unsigned int result;
647   size_t count;
648   const EntityHandle* ptr = get_contents( count );
649   if (vector_based()) {
650     #ifndef __SUNPRO_CC
651       result = std::count_if( ptr, ptr+count, dim_test(dimension) );
652     #else
653       std::count_if( ptr, ptr+count, dim_test(dimension), result );
654     #endif
655   }
656   else {
657     result = 0;
658     size_t idx = std::lower_bound( ptr, ptr+count, FIRST_OF_DIM(dimension) ) - ptr;
659     if (idx < count && DIM_FROM_HANDLE(ptr[idx]) == dimension) {
660       if (idx % 2) { // only part of first block is of type
661         result += ptr[idx] - FIRST_OF_DIM(dimension) + 1;
662         ++idx;
663       }
664       for (; idx < count; idx += 2) {
665         if (DIM_FROM_HANDLE(ptr[idx+1]) == dimension) // whole block is of type
666           result += ptr[idx+1] - ptr[idx] + 1;
667         else {
668           if (DIM_FROM_HANDLE(ptr[idx]) == dimension) // part of last block is of type
669             result += LAST_OF_DIM(dimension) - ptr[idx] + 1;
670           break;
671         }
672       }
673     }
674   }
675 
676   return result;
677 }
678 
get_non_set_entities(Range & range) const679 inline ErrorCode MeshSet::get_non_set_entities( Range& range ) const
680 {
681   size_t count;
682   const EntityHandle* ptr = get_contents( count );
683   if (vector_based()) {
684     std::remove_copy_if( ptr, ptr+count,
685                          range_inserter( range ),
686                          type_test(MBENTITYSET) );
687   }
688   else {
689     Range::iterator in = range.begin();
690     for (size_t idx = 0; idx < count; idx += 2) {
691       if (TYPE_FROM_HANDLE(ptr[idx+1]) != MBENTITYSET)
692         in = range.insert( in, ptr[idx], ptr[idx+1] );
693       else {
694         if (TYPE_FROM_HANDLE(ptr[idx]) != MBENTITYSET)
695           in = range.insert( in, ptr[idx], LAST_HANDLE( MBENTITYSET - 1 ) );
696         break;
697       }
698     }
699   }
700 
701   return MB_SUCCESS;
702 }
703 
contains_entities(const EntityHandle * entities,int num_ents,const int op) const704 inline bool MeshSet::contains_entities(const EntityHandle *entities,
705                                          int num_ents,
706                                          const int op) const
707 {
708   size_t count;
709   const EntityHandle* const ptr = get_contents( count );
710   const EntityHandle* const end = ptr + count;
711   size_t found_count = 0;
712   if (vector_based()) {
713     for (int i = 0; i < num_ents; ++i)
714       if (std::find( ptr, end, entities[i] ) < end)
715         ++found_count;
716   }
717   else {
718     assert(0 == count % 2);
719     for (int i = 0; i < num_ents; ++i) {
720       const unsigned long idx = std::lower_bound( ptr, end, entities[i] ) - ptr;
721       if (idx < count && (idx%2 != 0 || ptr[idx] == entities[i]))
722         ++found_count;
723     }
724   }
725 
726   return found_count >= ((Interface::INTERSECT == op) ? (unsigned)num_ents : 1u);
727 }
728 
729 
730 
731 //! subtract/intersect/unite meshset_2 from/with/into meshset_1; modifies meshset_1
subtract(const MeshSet * meshset_2,EntityHandle my_handle,AEntityFactory * adjacencies)732 inline ErrorCode MeshSet::subtract(const MeshSet *meshset_2,
733                                        EntityHandle my_handle,
734                                        AEntityFactory* adjacencies)
735 {
736   size_t count;
737   const EntityHandle* const ptr = meshset_2->get_contents( count );
738   if (meshset_2->vector_based())
739     return remove_entity_vector( ptr, count, my_handle, adjacencies );
740   else
741     return remove_entity_ranges( ptr, count, my_handle, adjacencies );
742 }
743 
unite(const MeshSet * meshset_2,EntityHandle my_handle,AEntityFactory * adjacencies)744 inline ErrorCode MeshSet::unite(const MeshSet *meshset_2,
745                                     EntityHandle my_handle,
746                                     AEntityFactory* adjacencies)
747 {
748   size_t count;
749   const EntityHandle* const ptr = meshset_2->get_contents( count );
750   if (meshset_2->vector_based())
751     return insert_entity_vector( ptr, count, my_handle, adjacencies );
752   else
753     return insert_entity_ranges( ptr, count, my_handle, adjacencies );
754 }
755 
756 //! add these entities to this meshset
add_entities(const EntityHandle * entity_handles,const int num_ents,EntityHandle my_handle,AEntityFactory * adjacencies)757 inline ErrorCode MeshSet::add_entities(const EntityHandle *entity_handles,
758                                            const int num_ents,
759                                            EntityHandle my_handle,
760                                            AEntityFactory* adjacencies)
761 {
762   return insert_entity_vector( entity_handles, num_ents, my_handle, adjacencies );
763 }
764 
765   //! add these entities to this meshset
add_entities(const Range & entities,EntityHandle my_handle,AEntityFactory * adjacencies)766 inline ErrorCode MeshSet::add_entities(const Range &entities,
767                                            EntityHandle my_handle,
768                                            AEntityFactory* adjacencies)
769 {
770   return insert_entity_ranges( entities, my_handle, adjacencies );
771 }
772 
773   //! add these entities to this meshset
remove_entities(const Range & entities,EntityHandle my_handle,AEntityFactory * adjacencies)774 inline ErrorCode MeshSet::remove_entities(const Range& entities,
775                                               EntityHandle my_handle,
776                                               AEntityFactory* adjacencies)
777 {
778   return remove_entity_ranges(  entities, my_handle, adjacencies );
779 }
780 
781 
782   //! remove these entities from this meshset
remove_entities(const EntityHandle * entities,const int num_ents,EntityHandle my_handle,AEntityFactory * adjacencies)783 inline ErrorCode MeshSet::remove_entities(const EntityHandle *entities,
784                                               const int num_ents,
785                                               EntityHandle my_handle,
786                                               AEntityFactory* adjacencies)
787 {
788   return remove_entity_vector( entities, num_ents, my_handle, adjacencies );
789 }
790 
791   //! return the number of entities contained in this meshset
num_entities() const792 unsigned int MeshSet::num_entities() const
793 {
794   size_t count;
795   const EntityHandle* list = get_contents( count );
796   if (vector_based())
797     return count;
798 
799   int result = 0;
800   const EntityHandle *const end = list + count;
801   for (; list < end; list += 2)
802     result += list[1] - list[0] + 1;
803   return result;
804 }
805 
806 } // namespace moab
807 
808 #endif
809