Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
Methods to insert/remove range-based data from contents list. Templatized to operate on both Range and set-based MeshSets. More...
Static Public Member Functions | |
static ErrorCode | ranged_insert_entities (MeshSet::Count &count, MeshSet::CompactList &clist, pair_iter_t begin, pair_iter_t end, EntityHandle my_handle, AEntityFactory *adj) |
static ErrorCode | ranged_remove_entities (MeshSet::Count &count, MeshSet::CompactList &clist, pair_iter_t begin, pair_iter_t end, EntityHandle my_handle, AEntityFactory *adj) |
static ErrorCode | vector_insert_entities (MeshSet::Count &count, MeshSet::CompactList &clist, pair_iter_t begin, pair_iter_t end, EntityHandle my_handle, AEntityFactory *adj) |
Methods to insert/remove range-based data from contents list. Templatized to operate on both Range and set-based MeshSets.
Definition at line 37 of file MeshSet.cpp.
ErrorCode moab::range_tool< pair_iter_t >::ranged_insert_entities | ( | MeshSet::Count & | count, |
MeshSet::CompactList & | clist, | ||
pair_iter_t | begin, | ||
pair_iter_t | end, | ||
EntityHandle | my_handle, | ||
AEntityFactory * | adj | ||
) | [inline, static] |
Insert range-based data into range-based MeshSet
Definition at line 441 of file MeshSet.cpp.
References moab::AEntityFactory::add_adjacency(), moab::MeshSet::CompactList::hnd, moab::MeshSet::MANY, MB_SUCCESS, moab::MeshSet::CompactList::ptr, and moab::resize_compact_list().
{ // first pass: // 1) merge existing ranges // 2) count number of new ranges that must be inserted EntityHandle* list_ptr; size_t list_size; if( count < MeshSet::MANY ) { list_ptr = clist.hnd; list_size = count; } else { list_ptr = clist.ptr[0]; list_size = clist.ptr[1] - clist.ptr[0]; } MeshSetRange* list = reinterpret_cast< MeshSetRange* >( list_ptr ); assert( 0 == list_size % 2 ); assert( 2 * sizeof( EntityHandle ) == sizeof( MeshSetRange ) ); list_size /= 2; MeshSetRange* const list_end = list + list_size; MeshSetRange *list_read = list, *list_write = list; pair_iter_t i = begin; // count number of range pairs that are straight insertions // (don't overlap any range pair in the current set) that // could not be inserted during the first pass. size_t insert_count = 0; // merge lists while( i != end ) { // find first range that intersects the current input range // do binary search if no holes in current set contents if( list_read == list_write ) { // subtract one from i->first because if it is one greater // then the the last value of some block, then we want that // block to append to. MeshSetRange tmp; tmp.first = i->first - 1; tmp.second = i->second; list_write = std::lower_bound( list_read, list_end, tmp, MeshSetRComp() ); list_read = list_write; } // otherwise shift down until we find where we find a range block // that intersects else while( list_read != list_end && list_read->second + 1 < i->first ) { *list_write = *list_read; ++list_write; ++list_read; } // handle any straight insertions of range blocks for( ; i != end && ( list_read == list_end || i->second + 1 < list_read->first ); ++i ) { // If we haven't removed any range pairs, we don't have space to // insert here. Defer the insertion until later. if( list_read == list_write ) { ++insert_count; } else { if( adj ) for( EntityHandle j = i->first; j <= i->second; ++j ) adj->add_adjacency( j, my_handle, false ); list_write->first = i->first; list_write->second = i->second; ++list_write; } } // merge all the stuff that gets merged into a single range pair // from both the input list and the existing set data if( list_read != list_end ) { MeshSetRange working = *list_read; // copy because might be the same as list_write ++list_read; // Check if we need to prepend to the existing block. // We only need to check this for the first input range because // after this working.first will always be the first possible handle // in the merged set of ranges. if( i != end && i->first < working.first && i->second + 1 >= working.first ) { if( adj ) for( EntityHandle h = i->first; h < working.first; ++h ) adj->add_adjacency( h, my_handle, false ); working.first = i->first; } // Now append from the input list and the remaining set contents // until we've consolidated all overlapping/touching ranges. bool done = false; while( !done ) { // does next set contents range touch working range? bool set_overlap = list_read != list_end && list_read->first <= working.second + 1; // does next input range touch working range? bool inp_overlap = i != end && i->first <= working.second + 1; // if both ranges touch... if( inp_overlap && set_overlap ) { // if next set range is contained in working, skip it if( list_read->second <= working.second ) ++list_read; // if next input range is contained in working, skip it else if( i->second <= working.second ) ++i; // Otherwise set the working end to the smaller of the two // ends: either the next set end or the next input end. // We want the smaller of the two because the larger might // intersect additional ranges in the other list. else if( list_read->second <= i->second ) { working.second = list_read->second; ++list_read; } else { working.second = i->second; ++i; } } // If only the input range intersect the current working range... else if( inp_overlap ) { // Would it be more efficient to just extent 'working' to // the end of the current input range? We'd end up adding // adjacencies for for entities that are already in the tracking // set and therefore already have the adjacency. EntityHandle last = i->second; if( list_read != list_end && list_read->first < last ) last = list_read->first - 1; else ++i; if( last > working.second ) { if( adj ) for( EntityHandle h = working.second + 1; h <= last; ++h ) adj->add_adjacency( h, my_handle, false ); working.second = last; } } else if( set_overlap ) { if( working.second < list_read->second ) working.second = list_read->second; ++list_read; } else { done = true; } } assert( list_write < list_read ); *list_write = working; ++list_write; } } // shuffle down entries to fill holes if( list_read == list_write ) list_read = list_write = list_end; else while( list_read < list_end ) { *list_write = *list_read; ++list_read; ++list_write; } // adjust allocated array size const size_t occupied_size = list_write - list; const size_t new_list_size = occupied_size + insert_count; list_ptr = resize_compact_list( count, clist, 2 * new_list_size ); // done? if( !insert_count ) return MB_SUCCESS; list = reinterpret_cast< MeshSetRange* >( list_ptr ); // Second pass: insert non-mergable range pairs // All range pairs in the input are either completely disjoint from // the ones in the mesh set and must be inserted or are entirely contained // within a range pair in the mesh set. assert( begin != end ); // can't have items to insert if given empty input list pair_iter_t ri = end; --ri; list_write = list + new_list_size - 1; list_read = list + occupied_size - 1; for( ; list_write >= list; --list_write ) { if( list_read >= list ) { while( ri->first >= list_read->first && ri->second <= list_read->second ) { assert( ri != begin ); --ri; } if( list_read->first > ri->second ) { *list_write = *list_read; --list_read; continue; } } assert( insert_count > 0 ); if( adj ) for( EntityHandle h = ri->first; h <= ri->second; ++h ) adj->add_adjacency( h, my_handle, false ); list_write->first = ri->first; list_write->second = ri->second; // don't have reverse iterator, so check before decrement // if insert_count isn't zero, must be more in range if( 0 == --insert_count ) { assert( list_read == list_write - 1 ); break; } else { --ri; } } assert( !insert_count ); return MB_SUCCESS; }
ErrorCode moab::range_tool< pair_iter_t >::ranged_remove_entities | ( | MeshSet::Count & | count, |
MeshSet::CompactList & | clist, | ||
pair_iter_t | begin, | ||
pair_iter_t | end, | ||
EntityHandle | my_handle, | ||
AEntityFactory * | adj | ||
) | [inline, static] |
Remove range-based data from range-based MeshSet
Definition at line 687 of file MeshSet.cpp.
References moab::MeshSet::CompactList::hnd, moab::MeshSet::MANY, MB_SUCCESS, moab::MeshSet::CompactList::ptr, moab::AEntityFactory::remove_adjacency(), and moab::resize_compact_list().
{ // first pass: // 1) remove (from) existing ranges // 2) count number of ranges that must be split ptrdiff_t split_count = 0; EntityHandle* list; size_t list_size; if( count < MeshSet::MANY ) { list = clist.hnd; list_size = count; } else { list = clist.ptr[0]; list_size = clist.ptr[1] - clist.ptr[0]; } EntityHandle* list_write = list; EntityHandle *const list_end = list + list_size, *list_read = list; pair_iter_t i = begin; while( list_read != list_end && i != end ) { while( i != end && i->second < list_read[0] ) ++i; if( i == end ) break; // if there are holes in the current array, shuffle blocks // down until we find the next block to remove if( list_read != list_write ) { while( list_read != list_end && i->second < list_read[0] ) { list_write[0] = list_read[0]; list_write[1] = list_read[1]; list_write += 2; list_read += 2; } } // otherwise do a binary search else { list_write = std::lower_bound( list_write, list_end, i->first ); // if in middle of range block (odd index), back up to start of block list_write -= ( list_write - list ) % 2; list_read = list_write; } // if everything remaning is past end of set contents... if( list_read == list_end ) break; // skip any remove pairs that aren't in the list if( i->second < list_read[0] ) { ++i; continue; } // Begin by assuming that we will keep the entire block list_write[0] = list_read[0]; list_write[1] = list_read[1]; list_read += 2; for( ; i != end && i->first <= list_write[1]; ++i ) { if( i->first <= list_write[0] ) { // remove whole block if( i->second >= list_write[1] ) { if( adj ) for( EntityHandle h = list_write[0]; h <= list_write[1]; ++h ) adj->remove_adjacency( h, my_handle ); list_write -= 2; break; } // remove from start of block else if( i->second >= list_write[0] ) { if( adj ) for( EntityHandle h = list_write[0]; h <= i->second; ++h ) adj->remove_adjacency( h, my_handle ); list_write[0] = i->second + 1; } } else if( i->first <= list_write[1] ) { // remove from end of block if( i->second >= list_write[1] ) { if( adj ) for( EntityHandle h = i->first; h <= list_write[1]; ++h ) adj->remove_adjacency( h, my_handle ); list_write[1] = i->first - 1; // list_write += 2; break; } // split block else { if( adj ) for( EntityHandle h = i->first; h <= i->second; ++h ) adj->remove_adjacency( h, my_handle ); if( list_read - list_write <= 2 ) { ++split_count; continue; } else { list_write[3] = list_write[1]; list_write[1] = i->first - 1; list_write[2] = i->second + 1; list_write += 2; } } } } list_write += 2; } // shuffle down entries to fill holes if( list_read == list_write ) list_read = list_write = list_end; else while( list_read < list_end ) { list_write[0] = list_read[0]; list_write[1] = list_read[1]; list_read += 2; list_write += 2; } // adjust allocated array size const size_t occupied_size = list_write - list; const size_t new_list_size = occupied_size + 2 * split_count; list = resize_compact_list( count, clist, new_list_size ); // done? if( !split_count ) return MB_SUCCESS; // Second pass: split range pairs // All range pairs in the input are either already removed or // require one of the existing range pairs to be split assert( begin != end ); // can't have ranges to split if given empty input list pair_iter_t ri = end; --ri; list_write = list + new_list_size - 2; list_read = list + occupied_size - 2; for( ; list_write >= list; list_write -= 2 ) { if( list_read >= list ) { while( ri->second > list_read[1] ) { assert( ri != begin ); --ri; } if( list_read[0] > ri->second ) { list_write[0] = list_read[0]; list_write[1] = list_read[1]; list_read -= 2; continue; } } assert( split_count > 0 ); list_write[0] = ri->second + 1; list_write[1] = list_read[1]; list_read[1] = ri->first - 1; // don't have reverse iterator, so check before decrement // if insert_count isn't zero, must be more in range if( 0 == --split_count ) { assert( list_read == list_write - 2 ); break; } else { --ri; } } assert( !split_count ); return MB_SUCCESS; }
ErrorCode moab::range_tool< pair_iter_t >::vector_insert_entities | ( | MeshSet::Count & | count, |
MeshSet::CompactList & | clist, | ||
pair_iter_t | begin, | ||
pair_iter_t | end, | ||
EntityHandle | my_handle, | ||
AEntityFactory * | adj | ||
) | [inline, static] |
Insert range-based data into list-based MeshSet
Definition at line 886 of file MeshSet.cpp.
References moab::AEntityFactory::add_adjacency(), moab::MeshSet::MANY, MB_SUCCESS, moab::MeshSet::CompactList::ptr, and moab::resize_compact_list().
{ const size_t init_size = count < MeshSet::MANY ? (int)count : clist.ptr[1] - clist.ptr[0]; size_t add_size = 0; for( pair_iter_t i = begin; i != end; ++i ) add_size += i->second - i->first + 1; EntityHandle* list = resize_compact_list( count, clist, init_size + add_size ); EntityHandle* li = list + init_size; for( pair_iter_t i = begin; i != end; ++i ) { for( EntityHandle h = i->first; h <= i->second; ++h ) { if( adj ) adj->add_adjacency( h, my_handle, false ); *li = h; ++li; } } return MB_SUCCESS; }