00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __SPLITTERTETRA_HXX__
00021 #define __SPLITTERTETRA_HXX__
00022
00023 #include "TransformedTriangle.hxx"
00024 #include "TetraAffineTransform.hxx"
00025 #include "InterpolationOptions.hxx"
00026 #include "InterpKernelHashMap.hxx"
00027
00028 #include <assert.h>
00029 #include <vector>
00030 #include <functional>
00031 #include <map>
00032
00033 namespace INTERP_KERNEL
00034 {
00039 class TriangleFaceKey
00040 {
00041 public:
00042
00052 TriangleFaceKey(int node1, int node2, int node3)
00053 {
00054 sort3Ints(_nodes, node1, node2, node3);
00055 _hashVal = ( _nodes[0] + _nodes[1] + _nodes[2] ) % 29;
00056 }
00057
00065 bool operator==(const TriangleFaceKey& key) const
00066 {
00067 return _nodes[0] == key._nodes[0] && _nodes[1] == key._nodes[1] && _nodes[2] == key._nodes[2];
00068 }
00069
00076 int hashVal() const
00077 {
00078 return _hashVal;
00079 }
00080
00081 inline void sort3Ints(int* sorted, int node1, int node2, int node3);
00082
00083 private:
00085 int _nodes[3];
00086
00088 int _hashVal;
00089 };
00090
00099 inline void TriangleFaceKey::sort3Ints(int* sorted, int x1, int x2, int x3)
00100 {
00101 if(x1 < x2)
00102 {
00103 if(x1 < x3)
00104 {
00105
00106 sorted[0] = x1;
00107 sorted[1] = x2 < x3 ? x2 : x3;
00108 sorted[2] = x2 < x3 ? x3 : x2;
00109 }
00110 else
00111 {
00112
00113 sorted[0] = x3;
00114 sorted[1] = x1;
00115 sorted[2] = x2;
00116 }
00117 }
00118 else
00119 {
00120 if(x2 < x3)
00121 {
00122
00123 sorted[0] = x2;
00124 sorted[1] = x1 < x3 ? x1 : x3;
00125 sorted[2] = x1 < x3 ? x3 : x1;
00126 }
00127 else
00128 {
00129
00130 sorted[0] = x3;
00131 sorted[1] = x2;
00132 sorted[2] = x1;
00133 }
00134 }
00135 }
00136
00142 template<> class hash<INTERP_KERNEL::TriangleFaceKey>
00143 {
00144 public:
00151 int operator()(const INTERP_KERNEL::TriangleFaceKey& key) const
00152 {
00153 return key.hashVal();
00154 }
00155 };
00156 }
00157
00158 namespace INTERP_KERNEL
00159 {
00160
00166 template<class MyMeshType>
00167 class SplitterTetra
00168 {
00169 public:
00170
00171 SplitterTetra(const MyMeshType& srcMesh, const double** tetraCorners, const typename MyMeshType::MyConnType *nodesId);
00172
00173 ~SplitterTetra();
00174
00175 double intersectSourceCell(typename MyMeshType::MyConnType srcCell, double* baryCentre=0);
00176
00177 double intersectTetra(const double** tetraCorners);
00178
00179 typename MyMeshType::MyConnType getId(int id) { return _conn[id]; }
00180
00181 void splitIntoDualCells(SplitterTetra<MyMeshType> **output);
00182
00183 void splitMySelfForDual(double* output, int i, typename MyMeshType::MyConnType& nodeId);
00184
00185 void clearVolumesCache();
00186
00187 private:
00188
00189 inline void createAffineTransform(const double** corners);
00190 inline void checkIsOutside(const double* pt, bool* isOutside) const;
00191 inline void calculateNode(typename MyMeshType::MyConnType globalNodeNum);
00192 inline void calculateVolume(TransformedTriangle& tri, const TriangleFaceKey& key);
00193
00194
00196 SplitterTetra(const SplitterTetra& t);
00197
00199 SplitterTetra& operator=(const SplitterTetra& t);
00200
00201
00203 TetraAffineTransform* _t;
00204
00206 HashMap< int , double* > _nodes;
00207
00209 HashMap< TriangleFaceKey, double
00210
00211
00212
00213 > _volumes;
00214
00216 const MyMeshType& _src_mesh;
00217
00218
00219 typename MyMeshType::MyConnType _conn[4];
00220
00221 double _coords[12];
00222 };
00223
00230 template<class MyMeshType>
00231 inline void SplitterTetra<MyMeshType>::createAffineTransform(const double** corners)
00232 {
00233
00234 _t = new TetraAffineTransform( corners );
00235 }
00236
00246 template<class MyMeshType>
00247 inline void SplitterTetra<MyMeshType>::checkIsOutside(const double* pt, bool* isOutside) const
00248 {
00249 isOutside[0] = isOutside[0] && (pt[0] <= 0.0);
00250 isOutside[1] = isOutside[1] && (pt[0] >= 1.0);
00251 isOutside[2] = isOutside[2] && (pt[1] <= 0.0);
00252 isOutside[3] = isOutside[3] && (pt[1] >= 1.0);
00253 isOutside[4] = isOutside[4] && (pt[2] <= 0.0);
00254 isOutside[5] = isOutside[5] && (pt[2] >= 1.0);
00255 isOutside[6] = isOutside[6] && (1.0 - pt[0] - pt[1] - pt[2] <= 0.0);
00256 isOutside[7] = isOutside[7] && (1.0 - pt[0] - pt[1] - pt[2] >= 1.0);
00257 }
00258
00268 template<class MyMeshType>
00269 inline void SplitterTetra<MyMeshType>::calculateNode(typename MyMeshType::MyConnType globalNodeNum)
00270 {
00271 const double* node = _src_mesh.getCoordinatesPtr()+MyMeshType::MY_SPACEDIM*globalNodeNum;
00272 double* transformedNode = new double[MyMeshType::MY_SPACEDIM];
00273 assert(transformedNode != 0);
00274 _t->apply(transformedNode, node);
00275 _nodes[globalNodeNum] = transformedNode;
00276 }
00277
00285 template<class MyMeshType>
00286 inline void SplitterTetra<MyMeshType>::calculateVolume(TransformedTriangle& tri, const TriangleFaceKey& key)
00287 {
00288 const double vol = tri.calculateIntersectionVolume();
00289 _volumes.insert(std::make_pair(key, vol));
00290 }
00291
00292 template<class MyMeshTypeT, class MyMeshTypeS=MyMeshTypeT>
00293 class SplitterTetra2
00294 {
00295 public:
00296 SplitterTetra2(const MyMeshTypeT& targetMesh, const MyMeshTypeS& srcMesh, SplittingPolicy policy);
00297 ~SplitterTetra2();
00298 void releaseArrays();
00299 void splitTargetCell(typename MyMeshTypeT::MyConnType targetCell, typename MyMeshTypeT::MyConnType nbOfNodesT,
00300 typename std::vector< SplitterTetra<MyMeshTypeS>* >& tetra);
00301 void fiveSplit(const int* const subZone, typename std::vector< SplitterTetra<MyMeshTypeS>* >& tetra);
00302 void sixSplit(const int* const subZone, typename std::vector< SplitterTetra<MyMeshTypeS>* >& tetra);
00303 void calculateGeneral24Tetra(typename std::vector< SplitterTetra<MyMeshTypeS>* >& tetra);
00304 void calculateGeneral48Tetra(typename std::vector< SplitterTetra<MyMeshTypeS>* >& tetra);
00305 void splitPyram5(typename std::vector< SplitterTetra<MyMeshTypeS>* >& tetra);
00306 void splitConvex(typename MyMeshTypeT::MyConnType targetCell,
00307 typename std::vector< SplitterTetra<MyMeshTypeS>* >& tetra);
00308 void calculateSubNodes(const MyMeshTypeT& targetMesh, typename MyMeshTypeT::MyConnType targetCell);
00309 inline const double* getCoordsOfSubNode(typename MyMeshTypeT::MyConnType node);
00310 inline const double* getCoordsOfSubNode2(typename MyMeshTypeT::MyConnType node, typename MyMeshTypeT::MyConnType& nodeId);
00311
00312 inline void calcBarycenter(int n, double* barycenter, const typename MyMeshTypeT::MyConnType* pts);
00313 private:
00314 const MyMeshTypeT& _target_mesh;
00315 const MyMeshTypeS& _src_mesh;
00316 SplittingPolicy _splitting_pol;
00319 std::vector<const double*> _nodes;
00320 std::vector<typename MyMeshTypeT::MyConnType> _node_ids;
00321 };
00322
00330 template<class MyMeshTypeT, class MyMeshTypeS>
00331
00332 inline void SplitterTetra2<MyMeshTypeT, MyMeshTypeS>::calcBarycenter(int n, double* barycenter, const typename MyMeshTypeT::MyConnType* pts)
00333 {
00334 barycenter[0] = barycenter[1] = barycenter[2] = 0.0;
00335 for(int i = 0; i < n ; ++i)
00336 {
00337 const double* pt = getCoordsOfSubNode(pts[i]);
00338 barycenter[0] += pt[0];
00339 barycenter[1] += pt[1];
00340 barycenter[2] += pt[2];
00341 }
00342
00343 barycenter[0] /= n;
00344 barycenter[1] /= n;
00345 barycenter[2] /= n;
00346 }
00347
00354 template<class MyMeshTypeT, class MyMeshTypeS>
00355 inline const double* SplitterTetra2<MyMeshTypeT, MyMeshTypeS>::getCoordsOfSubNode(typename MyMeshTypeT::MyConnType node)
00356 {
00357
00358 return _nodes.at(node);
00359 }
00360
00368 template<class MyMeshTypeT, class MyMeshTypeS>
00369 const double* SplitterTetra2<MyMeshTypeT, MyMeshTypeS>::getCoordsOfSubNode2(typename MyMeshTypeT::MyConnType node, typename MyMeshTypeT::MyConnType& nodeId)
00370 {
00371 const double *ret=_nodes.at(node);
00372 if(node<8)
00373 nodeId=_node_ids[node];
00374 else
00375 nodeId=-1;
00376 return ret;
00377 }
00378 }
00379
00380 #endif