Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #ifndef __smoab_FaceSets_h 00002 #define __smoab_FaceSets_h 00003 00004 #include "CellSets.h" 00005 #include <set> 00006 00007 namespace smoab 00008 { 00009 //---------------------------------------------------------------------------- 00010 class FaceCellSet : public CellSet 00011 { 00012 public: 00013 FaceCellSet( int id, smoab::EntityHandle p, const smoab::Range& cells ) : CellSet( p, cells ), ID( id ) {} 00014 00015 int faceId() const 00016 { 00017 return ID; 00018 } 00019 void overrideFaceId( int i ) 00020 { 00021 ID = i; 00022 } //USE AT YOUR OWN RISK 00023 00024 private: 00025 int ID; 00026 }; 00027 00028 //---------------------------------------------------------------------------- 00029 typedef std::vector< FaceCellSet > FaceCellSets; 00030 00031 //---------------------------------------------------------------------------- 00032 //class that store the regions that a faces is adjacent too 00033 struct FacesAdjRegions 00034 { 00035 FacesAdjRegions( int f, smoab::EntityHandle r0, smoab::EntityHandle r1 ) : FaceId( f ), Region0( r0 ), Region1( r1 ) 00036 { 00037 if( r0 > r1 ) 00038 { 00039 std::swap( this->Region0, this->Region1 ); 00040 } 00041 } 00042 00043 FacesAdjRegions( int f ) : FaceId( f ), Region0( -3 ), Region1( -2 ) {} 00044 00045 bool operator<( const FacesAdjRegions& other ) const 00046 { 00047 return ( this->FaceId < other.FaceId ); 00048 } 00049 00050 smoab::EntityHandle otherId( smoab::EntityHandle other ) const 00051 { 00052 if( other == Region0 ) 00053 { 00054 return Region1; 00055 } 00056 return Region0; 00057 } 00058 00059 int FaceId; 00060 smoab::EntityHandle Region0; 00061 smoab::EntityHandle Region1; 00062 }; 00063 //---------------------------------------------------------------------------- 00064 smoab::FaceCellSets findFaceSets( smoab::CellSets shells, 00065 smoab::CellSets boundaries, 00066 std::set< smoab::FacesAdjRegions >& faceMaps ) 00067 { 00068 typedef smoab::CellSets::iterator iterator; 00069 typedef smoab::FaceCellSets::iterator faceIterator; 00070 typedef std::set< smoab::FacesAdjRegions >::const_iterator FaceAdjIterator; 00071 00072 //we need to properly label each unique face in shells 00073 //we do this by intersecting each shell with each other shell 00074 //to find shell on shell contact, and than we intersect each 00075 //resulting shell with the boundary conditions 00076 //the end result of these intersections will be the new modelfaces 00077 int faceId = 1; 00078 smoab::FaceCellSets shellFaces; 00079 00080 //first intersect each shell with each other shell 00081 std::set< smoab::FacesAdjRegions > shellFaceContacts; 00082 for( iterator i = shells.begin(); i != shells.end(); ++i ) 00083 { 00084 //copy the cells so we can add a face that represents 00085 //all the cells of the region that aren't shared with another region 00086 int numCells = i->cells().size(); //size() on range is slow, so cache it 00087 for( iterator j = i + 1; j != shells.end() && numCells > 0; ++j ) 00088 { 00089 //intersect i and j to make a new face 00090 smoab::Range intersection = smoab::intersect( i->cells(), j->cells() ); 00091 if( !intersection.empty() ) 00092 { 00093 //don't want to increment faceId when the intersection is empty 00094 smoab::FaceCellSet face( faceId++, i->entity(), intersection ); 00095 shellFaces.push_back( face ); 00096 i->erase( intersection ); 00097 j->erase( intersection ); 00098 numCells -= intersection.size(); 00099 00100 //add this to the face map 00101 smoab::FacesAdjRegions faceInfo( faceId - 1, i->entity(), j->entity() ); 00102 shellFaceContacts.insert( faceInfo ); 00103 } 00104 } 00105 //if all the cells for shell i are used, don't add a new 00106 //empty face 00107 if( numCells > 0 ) 00108 { 00109 smoab::FaceCellSet face( faceId++, i->entity(), i->cells() ); 00110 shellFaces.push_back( face ); 00111 00112 //add this to the face map 00113 smoab::FacesAdjRegions faceInfo( faceId - 1, -1, i->entity() ); 00114 shellFaceContacts.insert( faceInfo ); 00115 } 00116 } 00117 00118 //now we have all the faces that match shell on shell contact 00119 //we know process all the new faces to see if they intersect 00120 //with any boundary sets. A boundary set can span multiple 00121 //shells so we want to process it as a second loop 00122 00123 //store the end before we start adding boundary faces, which 00124 //we don't need to check agianst other boundaries 00125 faceId = 1; //reset the faced id 00126 00127 //store in a new face set, expanding the current one causes incorrect results 00128 smoab::FaceCellSets faces; 00129 for( faceIterator i = shellFaces.begin(); i != shellFaces.end(); ++i ) 00130 { 00131 //determine from the shell faces if the new face we are creating 00132 //is bounded by two regions or just one 00133 smoab::FacesAdjRegions idToSearchFor( i->faceId() ); 00134 FaceAdjIterator adjRegions = shellFaceContacts.find( idToSearchFor ); 00135 smoab::EntityHandle otherRegionId = adjRegions->otherId( i->entity() ); 00136 00137 int numCells = i->cells().size(); //size() on range is slow, so cache it 00138 for( iterator j = boundaries.begin(); j != boundaries.end(); ++j ) 00139 { 00140 smoab::Range intersect = smoab::intersect( i->cells(), j->cells() ); 00141 if( !intersect.empty() ) 00142 { 00143 //don't want to increment faceId when the intersection is empty 00144 smoab::FaceCellSet face( faceId++, j->entity(), intersect ); 00145 faces.push_back( face ); 00146 i->erase( intersect ); 00147 numCells -= intersect.size(); 00148 smoab::FacesAdjRegions faceInfo( faceId - 1, i->entity(), otherRegionId ); 00149 faceMaps.insert( faceInfo ); 00150 } 00151 } 00152 if( numCells > 0 ) 00153 { 00154 smoab::FaceCellSet face( faceId++, i->entity(), i->cells() ); 00155 faces.push_back( face ); 00156 smoab::FacesAdjRegions faceInfo( faceId - 1, i->entity(), otherRegionId ); 00157 faceMaps.insert( faceInfo ); 00158 } 00159 } 00160 return faces; 00161 } 00162 00163 //---------------------------------------------------------------------------- 00164 template < typename T > 00165 std::vector< T > faceIdsPerCell( const smoab::FaceCellSets& faces ) 00166 { 00167 typedef smoab::FaceCellSets::const_iterator iterator; 00168 typedef std::vector< smoab::EntityHandle >::const_iterator EntityHandleIterator; 00169 typedef smoab::Range::const_iterator RangeIterator; 00170 00171 //find all the cells that are in the faceCellSet, and than map 00172 //the proper face id to that relative position, here comes lower_bounds! 00173 std::vector< smoab::EntityHandle > searchableCells; 00174 smoab::Range faceRange = smoab::getAllCells( faces ); 00175 smoab::RangeToVector( faceRange, searchableCells ); 00176 00177 //faceIds will be the resulting array 00178 std::vector< T > faceIds( searchableCells.size() ); 00179 00180 //construct the start and end iterators for the lower bounds call 00181 00182 EntityHandleIterator s_begin = searchableCells.begin(); 00183 EntityHandleIterator s_end = searchableCells.end(); 00184 00185 //search the face cell sets 00186 for( iterator i = faces.begin(); i != faces.end(); ++i ) 00187 { 00188 T value = static_cast< T >( i->faceId() ); 00189 const smoab::Range& entitiesCells = i->cells(); 00190 for( RangeIterator j = entitiesCells.begin(); j != entitiesCells.end(); ++j ) 00191 { 00192 EntityHandleIterator result = std::lower_bound( s_begin, s_end, *j ); 00193 std::size_t newId = std::distance( s_begin, result ); 00194 faceIds[newId] = value; 00195 } 00196 } 00197 return faceIds; 00198 } 00199 00200 //---------------------------------------------------------------------------- 00201 //given a face adjacency, determine the regions spare tag values 00202 template < typename T > 00203 std::pair< T, T > FaceAdjRegionValues( const smoab::FacesAdjRegions& faceAdj, 00204 smoab::Tag* t, 00205 const smoab::Interface& interface ) 00206 { 00207 std::pair< T, T > returnValue; 00208 const int defaultValue = interface.getDefaultTagVaue< int >( *t ); 00209 00210 /* 00211 * IF A REGION IS SET TO -1 WE NEED TO PUSH THAT VALUE DOWN 00212 * AS THE MATERIAL, SINCE THE MOAB DEFAULT TAG VALUE WILL 00213 * BE CONSIDIERED A REGION, AND WE WANT TO SAY IT BOUNDS THE 00214 * VOID REGION 00215 */ 00216 int tagValue = defaultValue; //use tagValue to pass in default value 00217 if( faceAdj.Region0 != -1 ) 00218 { 00219 tagValue = interface.getTagData( *t, faceAdj.Region0, tagValue ); 00220 } 00221 else 00222 { 00223 tagValue = -1; 00224 } 00225 00226 //set the first region tag value into the pair we are returing 00227 returnValue.first = static_cast< T >( tagValue ); 00228 00229 tagValue = defaultValue; //use tagValue to pass in default value 00230 tagValue = interface.getTagData( *t, faceAdj.Region1, tagValue ); 00231 if( faceAdj.Region1 != -1 ) 00232 { 00233 tagValue = interface.getTagData( *t, faceAdj.Region1, tagValue ); 00234 } 00235 else 00236 { 00237 tagValue = -1; 00238 } 00239 returnValue.second = static_cast< T >( tagValue ); 00240 00241 return returnValue; 00242 } 00243 00244 } // namespace smoab 00245 00246 #endif