moab
|
00001 00016 #ifndef SCD_ELEMENT_DATA_HPP 00017 #define SCD_ELEMENT_DATA_HPP 00018 00019 // 00020 // Class: ScdElementData 00021 // 00022 // Purpose: represent a rectangular element of mesh 00023 // 00024 // A ScdElement represents a rectangular element of mesh, including both vertices and 00025 // elements, and the parametric space used to address that element. Vertex data, 00026 // i.e. coordinates, may not be stored directly in the element, but the element returns 00027 // information about the vertex handles of vertices in the element. Vertex and element 00028 // handles associated with the element are each contiguous. 00029 00030 #include "SequenceData.hpp" 00031 #include "moab/HomXform.hpp" 00032 #include "moab/CN.hpp" 00033 #include "ScdVertexData.hpp" 00034 #include "Internals.hpp" 00035 #include "moab/Range.hpp" 00036 00037 #include <vector> 00038 #include <algorithm> 00039 00040 namespace moab { 00041 00042 class ScdElementData : public SequenceData 00043 { 00044 00046 class VertexDataRef 00047 { 00048 private: 00049 HomCoord minmax[2]; 00050 HomXform xform, invXform; 00051 ScdVertexData *srcSeq; 00052 public: 00053 friend class ScdElementData; 00054 00055 VertexDataRef(const HomCoord &min, const HomCoord &max, 00056 const HomXform &tmp_xform, ScdVertexData *this_seq); 00057 00058 bool contains(const HomCoord &coords) const; 00059 }; 00060 00061 private: 00062 00065 HomCoord boxParams[3]; 00066 00069 int dIJK[3]; 00070 00073 int dIJKm1[3]; 00074 00076 int isPeriodic[2]; 00077 00079 ScdElementData(); 00080 00082 std::vector<VertexDataRef> vertexSeqRefs; 00083 00084 public: 00085 00087 ScdElementData( EntityHandle start_handle, 00088 const int imin, const int jmin, const int kmin, 00089 const int imax, const int jmax, const int kmax, 00090 int *is_periodic); 00091 00092 virtual ~ScdElementData(); 00093 00095 inline EntityHandle get_vertex(const HomCoord &coords) const; 00096 inline EntityHandle get_vertex(int i, int j, int k) const 00097 { return get_vertex(HomCoord(i,j,k)); } 00098 00100 EntityHandle get_element(const int i, const int j, const int k) const; 00101 00103 const HomCoord &min_params() const; 00104 00106 const HomCoord &max_params() const; 00107 00109 void param_extents(int &di, int &dj, int &dk) const; 00110 00112 ErrorCode get_params(const EntityHandle ehandle, 00113 int &i, int &j, int &k) const; 00114 00116 inline int is_periodic_i() const {return isPeriodic[0];}; 00117 00119 inline int is_periodic_j() const {return isPeriodic[1];}; 00120 00121 inline void is_periodic(int is_p[2]) const 00122 {is_p[0] = isPeriodic[0]; is_p[1] = isPeriodic[1];} 00123 00125 int i_min() const {return (boxParams[0].hom_coord())[0];} 00126 int j_min() const {return (boxParams[0].hom_coord())[1];} 00127 int k_min() const {return (boxParams[0].hom_coord())[2];} 00128 int i_max() const {return (boxParams[1].hom_coord())[0];} 00129 int j_max() const {return (boxParams[1].hom_coord())[1];} 00130 int k_max() const {return (boxParams[1].hom_coord())[2];} 00131 00134 bool boundary_complete() const; 00135 00137 inline bool contains(const HomCoord &coords) const; 00138 00140 inline bool contains_vertex(const HomCoord &coords) const; 00141 00143 inline ErrorCode get_params_connectivity(const int i, const int j, const int k, 00144 std::vector<EntityHandle>& connectivity) const; 00145 00151 ErrorCode add_vsequence(ScdVertexData *vseq, 00152 const HomCoord &p1, const HomCoord &q1, 00153 const HomCoord &p2, const HomCoord &q2, 00154 const HomCoord &p3, const HomCoord &q3, 00155 bool bb_input = false, 00156 const HomCoord &bb_min = HomCoord::unitv[0], 00157 const HomCoord &bb_max = HomCoord::unitv[0]); 00158 00159 00160 SequenceData* subset( EntityHandle start, 00161 EntityHandle end, 00162 const int* sequence_data_sizes, 00163 const int* tag_data_sizes ) const; 00164 00165 static EntityID calc_num_entities( EntityHandle start_handle, 00166 int irange, 00167 int jrange, 00168 int krange, 00169 int *is_periodic = NULL); 00170 00171 unsigned long get_memory_use() const; 00172 }; 00173 00174 inline EntityHandle ScdElementData::get_element(const int i, const int j, const int k) const 00175 { 00176 return start_handle() + (i-i_min()) + (j-j_min())*dIJKm1[0] + (k-k_min())*dIJKm1[0]*dIJKm1[1]; 00177 } 00178 00179 inline const HomCoord &ScdElementData::min_params() const 00180 { 00181 return boxParams[0]; 00182 } 00183 00184 inline const HomCoord &ScdElementData::max_params() const 00185 { 00186 return boxParams[1]; 00187 } 00188 00190 inline void ScdElementData::param_extents(int &di, int &dj, int &dk) const 00191 { 00192 di = dIJK[0]; 00193 dj = dIJK[1]; 00194 dk = dIJK[2]; 00195 } 00196 00197 inline ErrorCode ScdElementData::get_params(const EntityHandle ehandle, 00198 int &i, int &j, int &k) const 00199 { 00200 if (TYPE_FROM_HANDLE(ehandle) != TYPE_FROM_HANDLE(start_handle())) return MB_FAILURE; 00201 00202 int hdiff = ehandle - start_handle(); 00203 00204 // use double ?: test below because on some platforms, both sides of the : are 00205 // evaluated, and if dIJKm1[1] is zero, that'll generate a divide-by-zero 00206 k = (dIJKm1[1] > 0 ? hdiff / (dIJKm1[1] > 0 ? dIJKm1[0]*dIJKm1[1] : 1) : 0); 00207 j = (hdiff - (k*dIJKm1[0]*dIJKm1[1])) / dIJKm1[0]; 00208 i = hdiff % dIJKm1[0]; 00209 00210 k += boxParams[0].k(); 00211 j += boxParams[0].j(); 00212 i += boxParams[0].i(); 00213 00214 return (ehandle >= start_handle() && 00215 ehandle < start_handle()+size() && 00216 i >= i_min() && i <= i_max() && 00217 j >= j_min() && j <= j_max() && 00218 k >= k_min() && k <= k_max()) ? MB_SUCCESS : MB_FAILURE; 00219 } 00220 00221 inline bool ScdElementData::contains(const HomCoord &temp) const 00222 { 00223 // upper bound is < instead of <= because element params max is one less 00224 // than vertex params max, except in case of 2d or 1d sequence 00225 return ((dIJKm1[0] && temp.i() >= boxParams[0].i() && temp.i() < boxParams[0].i()+dIJKm1[0]) && 00226 ((!dIJKm1[1] && temp.j() == boxParams[1].j()) || 00227 (dIJKm1[1] && temp.j() >= boxParams[0].j() && temp.j() < boxParams[0].j()+dIJKm1[1])) && 00228 ((!dIJKm1[2] && temp.k() == boxParams[1].k()) || 00229 (dIJKm1[2] && temp.k() >= boxParams[0].k() && temp.k() < boxParams[0].k()+dIJKm1[2]))); 00230 } 00231 00232 inline bool ScdElementData::contains_vertex(const HomCoord &temp) const 00233 { 00234 // upper bound is < instead of <= because element params max is one less 00235 // than vertex params max, except in case of 2d or 1d sequence 00236 return ((dIJK[0] && temp.i() >= boxParams[0].i() && temp.i() < boxParams[0].i()+dIJK[0]) && 00237 ((!dIJK[1] && temp.j() == boxParams[1].j()) || 00238 (dIJK[1] && temp.j() >= boxParams[0].j() && temp.j() < boxParams[0].j()+dIJK[1])) && 00239 ((!dIJK[2] && temp.k() == boxParams[1].k()) || 00240 (dIJK[2] && temp.k() >= boxParams[0].k() && temp.k() < boxParams[0].k()+dIJK[2]))); 00241 } 00242 00243 inline bool ScdElementData::VertexDataRef::contains(const HomCoord &coords) const 00244 { 00245 return (minmax[0] <= coords && minmax[1] >= coords); 00246 } 00247 00248 inline ScdElementData::VertexDataRef::VertexDataRef(const HomCoord &this_min, const HomCoord &this_max, 00249 const HomXform &tmp_xform, ScdVertexData *this_seq) 00250 : xform(tmp_xform), invXform(tmp_xform.inverse()), srcSeq(this_seq) 00251 { 00252 minmax[0] = HomCoord(this_min); 00253 minmax[1] = HomCoord(this_max); 00254 } 00255 00256 inline EntityHandle ScdElementData::get_vertex(const HomCoord &coords) const 00257 { 00258 assert(boundary_complete()); 00259 for (std::vector<VertexDataRef>::const_iterator it = vertexSeqRefs.begin(); 00260 it != vertexSeqRefs.end(); it++) { 00261 if ((*it).minmax[0] <= coords && (*it).minmax[1] >= coords) { 00262 // first get the vertex block-local parameters 00263 HomCoord local_coords = coords / (*it).xform; 00264 00265 assert((*it).srcSeq->contains(local_coords)); 00266 00267 // now get the vertex handle for those coords 00268 return (*it).srcSeq->get_vertex(local_coords); 00269 } 00270 } 00271 00272 // got here, it's an error 00273 return 0; 00274 } 00275 00276 inline ErrorCode ScdElementData::add_vsequence(ScdVertexData *vseq, 00277 const HomCoord &p1, const HomCoord &q1, 00278 const HomCoord &p2, const HomCoord &q2, 00279 const HomCoord &p3, const HomCoord &q3, 00280 bool bb_input, 00281 const HomCoord &bb_min, 00282 const HomCoord &bb_max) 00283 { 00284 // compute the transform given the vseq-local parameters and the mapping to 00285 // this element sequence's parameters passed in minmax 00286 HomXform M; 00287 M.three_pt_xform(p1, q1, p2, q2, p3, q3); 00288 00289 // min and max in element seq's parameter system may not be same as those in 00290 // vseq's system, so need to take min/max 00291 00292 HomCoord minmax[2]; 00293 if (bb_input) { 00294 minmax[0] = bb_min; 00295 minmax[1] = bb_max; 00296 } 00297 else { 00298 minmax[0] = vseq->min_params() * M; 00299 minmax[1] = vseq->max_params() * M; 00300 } 00301 00302 // check against other vseq's to make sure they don't overlap 00303 for (std::vector<VertexDataRef>::const_iterator vsit = vertexSeqRefs.begin(); 00304 vsit != vertexSeqRefs.end(); vsit++) 00305 if ((*vsit).contains(minmax[0]) || (*vsit).contains(minmax[1])) 00306 return MB_FAILURE; 00307 00308 HomCoord tmp_min(std::min(minmax[0].i(), minmax[1].i()), 00309 std::min(minmax[0].j(), minmax[1].j()), 00310 std::min(minmax[0].k(), minmax[1].k())); 00311 HomCoord tmp_max(std::max(minmax[0].i(), minmax[1].i()), 00312 std::max(minmax[0].j(), minmax[1].j()), 00313 std::max(minmax[0].k(), minmax[1].k())); 00314 00315 00316 // set up a new vertex sequence reference 00317 VertexDataRef tmp_seq_ref(tmp_min, tmp_max, M, vseq); 00318 00319 // add to the list 00320 vertexSeqRefs.push_back(tmp_seq_ref); 00321 00322 return MB_SUCCESS; 00323 } 00324 00325 inline ErrorCode ScdElementData::get_params_connectivity(const int i, const int j, const int k, 00326 std::vector<EntityHandle>& connectivity) const 00327 { 00328 if (contains(HomCoord(i, j, k)) == false) return MB_FAILURE; 00329 00330 int ip1 = (isPeriodic[0] ? (i+1)%dIJKm1[0] : i+1), 00331 jp1 = (isPeriodic[1] ? (j+1)%dIJKm1[1] : j+1); 00332 00333 connectivity.push_back(get_vertex(i, j, k)); 00334 connectivity.push_back(get_vertex(ip1, j, k)); 00335 if (CN::Dimension(TYPE_FROM_HANDLE(start_handle())) < 2) return MB_SUCCESS; 00336 connectivity.push_back(get_vertex(ip1, jp1, k)); 00337 connectivity.push_back(get_vertex(i, jp1, k)); 00338 if (CN::Dimension(TYPE_FROM_HANDLE(start_handle())) < 3) return MB_SUCCESS; 00339 connectivity.push_back(get_vertex(i, j, k+1)); 00340 connectivity.push_back(get_vertex(ip1, j, k+1)); 00341 connectivity.push_back(get_vertex(ip1, jp1, k+1)); 00342 connectivity.push_back(get_vertex(i, jp1, k+1)); 00343 return MB_SUCCESS; 00344 } 00345 00346 } // namespace moab 00347 00348 #endif