Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #ifndef __smoab_LinearCellConnectivity_h 00002 #define __smoab_LinearCellConnectivity_h 00003 00004 #include "CellTypeToType.h" 00005 #include "ContinousCellInfo.h" 00006 00007 #include <algorithm> 00008 #include <vector> 00009 00010 namespace smoab 00011 { 00012 namespace detail 00013 { 00014 00015 namespace internal 00016 { 00017 //we want a subset of the real connetivity array, 00018 //this does that for use with a super easy wrapper 00019 struct SubsetArray 00020 { 00021 SubsetArray( EntityHandle* realConn, int numCells, int currentVertsPerCell, int newVertsPerCell ) : Array() 00022 { 00023 const int size = numCells * newVertsPerCell; 00024 this->Array.reserve( size ); 00025 if( currentVertsPerCell == newVertsPerCell ) 00026 { 00027 std::copy( realConn, realConn + size, std::back_inserter( this->Array ) ); 00028 } 00029 else 00030 { 00031 //skip copy only the first N points which we want 00032 //since moab stores linear points first per cell 00033 EntityHandle* pos = realConn; 00034 for( int i = 0; i < numCells; ++i ) 00035 { 00036 std::copy( pos, pos + newVertsPerCell, std::back_inserter( this->Array ) ); 00037 pos += currentVertsPerCell; 00038 } 00039 } 00040 } 00041 typedef std::vector< EntityHandle >::const_iterator const_iterator; 00042 typedef std::vector< EntityHandle >::iterator iterator; 00043 00044 const_iterator begin() const 00045 { 00046 return this->Array.begin(); 00047 } 00048 iterator begin() 00049 { 00050 return this->Array.begin(); 00051 } 00052 00053 const_iterator end() const 00054 { 00055 return this->Array.end(); 00056 } 00057 iterator end() 00058 { 00059 return this->Array.end(); 00060 } 00061 00062 private: 00063 std::vector< EntityHandle > Array; 00064 }; 00065 } // namespace internal 00066 00067 class LinearCellConnectivity 00068 { 00069 public: 00070 LinearCellConnectivity( smoab::Range const& cells, moab::Interface* moab ) 00071 : Connectivity(), UniquePoints(), Info() 00072 { 00073 int count = 0; 00074 const std::size_t cellSize = cells.size(); 00075 while( count != cellSize ) 00076 { 00077 EntityHandle* connectivity; 00078 int numVerts = 0, iterationCount = 0; 00079 //use the highly efficent calls, since we know that are of the same dimension 00080 moab->connect_iterate( cells.begin() + count, cells.end(), connectivity, numVerts, iterationCount ); 00081 //if we didn't read anything, break! 00082 if( iterationCount == 0 ) 00083 { 00084 break; 00085 } 00086 00087 //identify the cell type that we currently have, 00088 //store that along with the connectivity in a temp storage vector 00089 const moab::EntityType type = moab->type_from_handle( *cells.begin() + count ); 00090 00091 int vtkNumVerts; 00092 int vtkCellType = smoab::detail::vtkLinearCellType( type, vtkNumVerts ); 00093 00094 ContinousCellInfo info = { vtkCellType, vtkNumVerts, 0, iterationCount }; 00095 this->Info.push_back( info ); 00096 00097 //we need to copy only a subset of the connectivity array 00098 internal::SubsetArray conn( connectivity, iterationCount, numVerts, vtkNumVerts ); 00099 this->Connectivity.push_back( conn ); 00100 00101 count += iterationCount; 00102 } 00103 } 00104 00105 //---------------------------------------------------------------------------- 00106 void compactIds( vtkIdType& numCells, vtkIdType& connectivityLength ) 00107 { 00108 //converts all the ids to be ordered starting at zero, and also 00109 //keeping the orginal logical ordering. Stores the result of this 00110 //operation in the unstrucutred grid that is passed in 00111 00112 //lets determine the total length of the connectivity 00113 connectivityLength = 0; 00114 numCells = 0; 00115 for( InfoConstIterator i = this->Info.begin(); i != this->Info.end(); ++i ) 00116 { 00117 connectivityLength += ( *i ).numCells * ( *i ).numVerts; 00118 numCells += ( *i ).numCells; 00119 } 00120 00121 this->UniquePoints.reserve( connectivityLength ); 00122 00123 this->copyConnectivity( this->UniquePoints ); 00124 std::sort( this->UniquePoints.begin(), this->UniquePoints.end() ); 00125 00126 typedef std::vector< EntityHandle >::iterator EntityIterator; 00127 EntityIterator newEnd = std::unique( this->UniquePoints.begin(), this->UniquePoints.end() ); 00128 00129 const std::size_t newSize = std::distance( this->UniquePoints.begin(), newEnd ); 00130 this->UniquePoints.resize( newSize ); 00131 } 00132 00133 //---------------------------------------------------------------------------- 00134 void moabPoints( smoab::Range& range ) const 00135 { 00136 //from the documentation a reverse iterator is the fastest way 00137 //to insert into a range. 00138 std::copy( this->UniquePoints.rbegin(), this->UniquePoints.rend(), moab::range_inserter( range ) ); 00139 } 00140 00141 //---------------------------------------------------------------------------- 00142 //copy the connectivity from the moab held arrays to the user input vector 00143 void copyConnectivity( std::vector< EntityHandle >& output ) const 00144 { 00145 //walk the info to find the length of each sub connectivity array, 00146 //and insert them into the vector, ordering is implied by the order 00147 //the connecitivy sub array are added to this class 00148 ConnConstIterator c = this->Connectivity.begin(); 00149 for( InfoConstIterator i = this->Info.begin(); i != this->Info.end(); ++i, ++c ) 00150 { 00151 //remember our Connectivity is a vector of pointers whose 00152 //length is held in the info vector. 00153 const int numUnusedPoints = ( *i ).numUnusedVerts; 00154 const int connLength = ( *i ).numCells * ( *i ).numVerts; 00155 std::copy( c->begin(), c->end(), std::back_inserter( output ) ); 00156 } 00157 } 00158 00159 //copy the information from this contianer to a vtk cell array, and 00160 //related lookup information 00161 void copyToVtkCellInfo( vtkIdType* cellArray ) const 00162 { 00163 ConnConstIterator c = this->Connectivity.begin(); 00164 for( InfoConstIterator i = this->Info.begin(); i != this->Info.end(); ++i, ++c ) 00165 { 00166 //for this group of the same cell type we need to fill the cellTypes 00167 const int numCells = ( *i ).numCells; 00168 const int numVerts = ( *i ).numVerts; 00169 00170 //for each cell in this collection that have the same type 00171 //grab the raw array now, so we can properly increment for each vert in each cell 00172 internal::SubsetArray::const_iterator moabConnectivity = c->begin(); 00173 for( int j = 0; j < numCells; ++j ) 00174 { 00175 //cell arrays start and end are different, since we 00176 //have to account for element that states the length of each cell 00177 cellArray[0] = numVerts; 00178 00179 for( int k = 0; k < numVerts; ++k, ++moabConnectivity ) 00180 { 00181 //this is going to be a root of some failures when we start 00182 //reading really large datasets under 32bit. 00183 00184 //fyi, don't use a range ds for unique points, distance 00185 //function is horribly slow they need to override it 00186 EntityConstIterator result = 00187 std::lower_bound( this->UniquePoints.begin(), this->UniquePoints.end(), *moabConnectivity ); 00188 std::size_t newId = std::distance( this->UniquePoints.begin(), result ); 00189 cellArray[k + 1] = static_cast< vtkIdType >( newId ); 00190 } 00191 cellArray += numVerts + 1; 00192 } 00193 } 00194 } 00195 00196 private: 00197 std::vector< internal::SubsetArray > Connectivity; 00198 std::vector< EntityHandle > UniquePoints; 00199 00200 std::vector< detail::ContinousCellInfo > Info; 00201 00202 typedef std::vector< EntityHandle >::const_iterator EntityConstIterator; 00203 typedef std::vector< internal::SubsetArray >::const_iterator ConnConstIterator; 00204 typedef std::vector< detail::ContinousCellInfo >::const_iterator InfoConstIterator; 00205 }; 00206 } // namespace detail 00207 } // namespace smoab 00208 00209 #endif // __smoab_LinearCellConnectivity_h