Version: 6.3.1

src/INTERP_KERNEL/SplitterTetra.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
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             // x1 is min
00106             sorted[0] = x1;
00107             sorted[1] = x2 < x3 ? x2 : x3;
00108             sorted[2] = x2 < x3 ? x3 : x2;
00109           }
00110         else
00111           {
00112             // x3, x1, x2
00113             sorted[0] = x3;
00114             sorted[1] = x1;
00115             sorted[2] = x2;
00116           }
00117       }
00118     else // x2 < x1
00119       {
00120         if(x2 < x3)
00121           {
00122             // x2 is min
00123             sorted[0] = x2;
00124             sorted[1] = x1 < x3 ? x1 : x3;
00125             sorted[2] = x1 < x3 ? x3 : x1;
00126           } 
00127         else
00128           {
00129             // x3, x2, x1
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     // member functions
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     // member variables
00203     TetraAffineTransform* _t;
00204     
00206     HashMap< int , double* > _nodes;
00207     
00209     HashMap< TriangleFaceKey, double
00210 // #ifdef WIN32
00211 //         , hash_compare<TriangleFaceKey,TriangleFaceKeyComparator> 
00212 // #endif
00213     > _volumes;
00214 
00216     const MyMeshType& _src_mesh;
00217                 
00218     // node id of the first node in target mesh in C mode.
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     // create AffineTransform from tetrahedron
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     //template<int n>
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   //template<int n>
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     // replace "at()" with [] for unsafe but faster access
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
Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS