Back to index

salome-smesh  6.5.0
DriverMED_W_SMESHDS_Mesh.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH DriverMED : driver to read and write 'med' files
00024 //  File   : DriverMED_W_SMESHDS_Mesh.cxx
00025 //  Module : SMESH
00026 //
00027 #include <sstream>
00028 
00029 #include "DriverMED_W_SMESHDS_Mesh.h"
00030 #include "DriverMED_Family.h"
00031 
00032 #include "SMESHDS_Mesh.hxx"
00033 #include "SMDS_MeshElement.hxx"
00034 #include "SMDS_MeshNode.hxx"
00035 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
00036 
00037 #include "utilities.h"
00038 
00039 #include "MED_Utilities.hxx"
00040 
00041 #define _EDF_NODE_IDS_
00042 //#define _ELEMENTS_BY_DIM_
00043 
00044 using namespace std;
00045 using namespace MED;
00046 
00047 
00048 DriverMED_W_SMESHDS_Mesh::DriverMED_W_SMESHDS_Mesh():
00049   myAllSubMeshes (false),
00050   myDoGroupOfNodes (false),
00051   myDoGroupOfEdges (false),
00052   myDoGroupOfFaces (false),
00053   myDoGroupOfVolumes (false)
00054 {}
00055 
00056 void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName, 
00057                                        MED::EVersion theId)
00058 {
00059   myMed = CrWrapper(theFileName,theId);
00060   Driver_SMESHDS_Mesh::SetFile(theFileName);
00061 }
00062 
00063 void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName)
00064 {
00065   return SetFile(theFileName,MED::eV2_2);
00066 }
00067 
00068 string DriverMED_W_SMESHDS_Mesh::GetVersionString(const MED::EVersion theVersion, int theNbDigits)
00069 {
00070   TInt majeur, mineur, release;
00071   majeur =  mineur = release = 0;
00072 //   if ( theVersion == eV2_1 )
00073 //     MED::GetVersionRelease<eV2_1>(majeur, mineur, release);
00074 //   else
00075     MED::GetVersionRelease<eV2_2>(majeur, mineur, release);
00076   ostringstream name;
00077   if ( theNbDigits > 0 )
00078     name << majeur;
00079   if ( theNbDigits > 1 )
00080     name << "." << mineur;
00081   if ( theNbDigits > 2 )
00082     name << "." << release;
00083   return name.str();
00084 }
00085 
00086 void DriverMED_W_SMESHDS_Mesh::AddGroup(SMESHDS_GroupBase* theGroup)
00087 {
00088   myGroups.push_back(theGroup);
00089 }
00090 
00091 void DriverMED_W_SMESHDS_Mesh::AddAllSubMeshes()
00092 {
00093   myAllSubMeshes = true;
00094 }
00095 
00096 void DriverMED_W_SMESHDS_Mesh::AddSubMesh(SMESHDS_SubMesh* theSubMesh, int theID)
00097 {
00098   mySubMeshes[theID] = theSubMesh;
00099 }
00100 
00101 void DriverMED_W_SMESHDS_Mesh::AddGroupOfNodes()
00102 {
00103   myDoGroupOfNodes = true;
00104 }
00105 
00106 void DriverMED_W_SMESHDS_Mesh::AddGroupOfEdges()
00107 {
00108   myDoGroupOfEdges = true;
00109 }
00110 
00111 void DriverMED_W_SMESHDS_Mesh::AddGroupOfFaces()
00112 {
00113   myDoGroupOfFaces = true;
00114 }
00115 
00116 void DriverMED_W_SMESHDS_Mesh::AddGroupOfVolumes()
00117 {
00118   myDoGroupOfVolumes = true;
00119 }
00120 
00121 namespace{
00122   typedef double (SMDS_MeshNode::* TGetCoord)() const;
00123   typedef const char* TName;
00124   typedef const char* TUnit;
00125 
00126   // name length in a mesh must be equal to 16 :
00127   //         1234567890123456
00128   TName M = "m               ";
00129   TName X = "x               ";
00130   TName Y = "y               ";
00131   TName Z = "z               ";
00132 
00133   TUnit aUnit[3] = {M,M,M};
00134 
00135   // 3 dim
00136   TGetCoord aXYZGetCoord[3] = {
00137     &SMDS_MeshNode::X, 
00138     &SMDS_MeshNode::Y, 
00139     &SMDS_MeshNode::Z
00140   };
00141   TName aXYZName[3] = {X,Y,Z};
00142   
00143   // 2 dim
00144   TGetCoord aXYGetCoord[2] = {
00145     &SMDS_MeshNode::X, 
00146     &SMDS_MeshNode::Y
00147   };
00148   TName aXYName[2] = {X,Y};
00149 
00150   TGetCoord aYZGetCoord[2] = {
00151     &SMDS_MeshNode::Y, 
00152     &SMDS_MeshNode::Z
00153   };
00154   TName aYZName[2] = {Y,Z};
00155 
00156   TGetCoord aXZGetCoord[2] = {
00157     &SMDS_MeshNode::X, 
00158     &SMDS_MeshNode::Z
00159   };
00160   TName aXZName[2] = {X,Z};
00161 
00162   // 1 dim
00163   TGetCoord aXGetCoord[1] = {
00164     &SMDS_MeshNode::X
00165   };
00166   TName aXName[1] = {X};
00167 
00168   TGetCoord aYGetCoord[1] = {
00169     &SMDS_MeshNode::Y
00170   };
00171   TName aYName[1] = {Y};
00172 
00173   TGetCoord aZGetCoord[1] = {
00174     &SMDS_MeshNode::Z
00175   };
00176   TName aZName[1] = {Z};
00177 
00178 
00179   class TCoordHelper{
00180     SMDS_NodeIteratorPtr myNodeIter;
00181     const SMDS_MeshNode* myCurrentNode;
00182     TGetCoord* myGetCoord;
00183     TName* myName;
00184     TUnit* myUnit;
00185   public:
00186     TCoordHelper(const SMDS_NodeIteratorPtr& theNodeIter,
00187                  TGetCoord* theGetCoord,
00188                  TName* theName,
00189                  TUnit* theUnit = aUnit):
00190       myNodeIter(theNodeIter),
00191       myGetCoord(theGetCoord),
00192       myName(theName),
00193       myUnit(theUnit)
00194     {}
00195     virtual ~TCoordHelper(){}
00196     bool Next(){ 
00197       return myNodeIter->more() && 
00198         (myCurrentNode = myNodeIter->next());
00199     }
00200     const SMDS_MeshNode* GetNode(){
00201       return myCurrentNode;
00202     }
00203     MED::TIntVector::value_type GetID(){
00204       return myCurrentNode->GetID();
00205     }
00206     MED::TFloatVector::value_type GetCoord(TInt theCoodId){
00207       return (myCurrentNode->*myGetCoord[theCoodId])();
00208     }
00209     MED::TStringVector::value_type GetName(TInt theDimId){
00210       return myName[theDimId];
00211     }
00212     MED::TStringVector::value_type GetUnit(TInt theDimId){
00213       return myUnit[theDimId];
00214     }
00215   };
00216   typedef boost::shared_ptr<TCoordHelper> TCoordHelperPtr;
00217 
00218   //-------------------------------------------------------
00222   //-------------------------------------------------------
00223   struct TElemTypeData
00224   {
00225     EEntiteMaillage     _entity;
00226     EGeometrieElement   _geomType;
00227     TInt                _nbElems;
00228     SMDSAbs_ElementType _smdsType;
00229 
00230     TElemTypeData (EEntiteMaillage entity, EGeometrieElement geom, TInt nb, SMDSAbs_ElementType type)
00231       : _entity(entity), _geomType(geom), _nbElems( nb ), _smdsType( type ) {}
00232   };
00233 
00234 
00235   typedef NCollection_DataMap< Standard_Address, int > TElemFamilyMap;
00236 
00237   //================================================================================
00242   //================================================================================
00243 
00244   void fillElemFamilyMap( TElemFamilyMap &            anElemFamMap,
00245                           list<DriverMED_FamilyPtr> & aFamilies,
00246                           const SMDSAbs_ElementType   anElemType)
00247   {
00248     anElemFamMap.Clear();
00249     //anElemFamMap.clear();
00250     list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
00251     while ( aFamsIter != aFamilies.end() )
00252     {
00253       if ((*aFamsIter)->GetType() != anElemType) {
00254         aFamsIter++;
00255       }
00256       else {
00257         int aFamId = (*aFamsIter)->GetId();
00258         const set<const SMDS_MeshElement *>& anElems = (*aFamsIter)->GetElements();
00259         set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElems.begin();
00260         for (; anElemsIter != anElems.end(); anElemsIter++)
00261         {
00262           anElemFamMap.Bind( (Standard_Address)*anElemsIter, aFamId );
00263           //anElemFamMap[*anElemsIter] = aFamId;
00264         }
00265         // remove a family from the list
00266         aFamilies.erase( aFamsIter++ );
00267       }
00268     }
00269   }
00270 
00271   //================================================================================
00275   //================================================================================
00276 
00277   int getFamilyId( const TElemFamilyMap &  anElemFamMap,
00278                    const SMDS_MeshElement* anElement,
00279                    const int               aDefaultFamilyId)
00280   {
00281     if ( anElemFamMap.IsBound( (Standard_Address) anElement ))
00282       return anElemFamMap( (Standard_Address) anElement );
00283 //     TElemFamilyMap::iterator elem_famNum = anElemFamMap.find( anElement );
00284 //     if ( elem_famNum != anElemFamMap.end() )
00285 //       return elem_famNum->second;
00286     return aDefaultFamilyId;
00287   }
00288 }
00289 
00290 Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
00291 {
00292   Status aResult = DRS_OK;
00293   if (myMesh->hasConstructionEdges() || myMesh->hasConstructionFaces()) {
00294     INFOS("SMDS_MESH with hasConstructionEdges() or hasConstructionFaces() do not supports!!!");
00295     return DRS_FAIL;
00296   }
00297   try {
00298     MESSAGE("Perform - myFile : "<<myFile);
00299 
00300     // Creating the MED mesh for corresponding SMDS structure
00301     //-------------------------------------------------------
00302     string aMeshName;
00303     if (myMeshId != -1) {
00304       ostringstream aMeshNameStr;
00305       aMeshNameStr<<myMeshId;
00306       aMeshName = aMeshNameStr.str();
00307     } else {
00308       aMeshName = myMeshName;
00309     }
00310 
00311     // Mesh dimension definition
00312     TInt aSpaceDimension;
00313     TCoordHelperPtr aCoordHelperPtr;
00314     {  
00315       bool anIsXDimension = false;
00316       bool anIsYDimension = false;
00317       bool anIsZDimension = false;
00318       {
00319         SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
00320         double aBounds[6];
00321         if(aNodesIter->more()){
00322           const SMDS_MeshNode* aNode = aNodesIter->next();
00323           aBounds[0] = aBounds[1] = aNode->X();
00324           aBounds[2] = aBounds[3] = aNode->Y();
00325           aBounds[4] = aBounds[5] = aNode->Z();
00326         }
00327         while(aNodesIter->more()){
00328           const SMDS_MeshNode* aNode = aNodesIter->next();
00329           aBounds[0] = min(aBounds[0],aNode->X());
00330           aBounds[1] = max(aBounds[1],aNode->X());
00331           
00332           aBounds[2] = min(aBounds[2],aNode->Y());
00333           aBounds[3] = max(aBounds[3],aNode->Y());
00334           
00335           aBounds[4] = min(aBounds[4],aNode->Z());
00336           aBounds[5] = max(aBounds[5],aNode->Z());
00337         }
00338 
00339         double EPS = 1.0E-7;
00340         anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
00341         anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
00342         anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
00343         aSpaceDimension = anIsXDimension + anIsYDimension + anIsZDimension;
00344         if(!aSpaceDimension)
00345           aSpaceDimension = 3;
00346         // PAL16857(SMESH not conform to the MED convention):
00347         if ( aSpaceDimension == 2 && anIsZDimension ) // 2D only if mesh is in XOY plane
00348           aSpaceDimension = 3;
00349         // PAL18941(a saved study with a mesh belong Z is opened and the mesh is belong X)
00350         if ( aSpaceDimension == 1 && !anIsXDimension ) {// 1D only if mesh is along OX
00351           if ( anIsYDimension ) {
00352             aSpaceDimension = 2;
00353             anIsXDimension = true;
00354           } else {
00355             aSpaceDimension = 3;
00356           }
00357         }
00358       }
00359 
00360       SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator(/*idInceasingOrder=*/true);
00361       switch(aSpaceDimension){
00362       case 3:
00363         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName));
00364         break;
00365       case 2:
00366         if(anIsXDimension && anIsYDimension)
00367           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName));
00368         if(anIsYDimension && anIsZDimension)
00369           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName));
00370         if(anIsXDimension && anIsZDimension)
00371           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName));
00372         break;
00373       case 1:
00374         if(anIsXDimension)
00375           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName));
00376         if(anIsYDimension)
00377           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName));
00378         if(anIsZDimension)
00379           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName));
00380         break;
00381       }
00382     }
00383     TInt aMeshDimension = 0;
00384     if ( myMesh->NbEdges() > 0 )
00385       aMeshDimension = 1;
00386     if ( myMesh->NbFaces() > 0 )
00387       aMeshDimension = 2;
00388     if ( myMesh->NbVolumes() > 0 )
00389       aMeshDimension = 3;
00390     
00391     PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aSpaceDimension,aMeshName);
00392     MESSAGE("Add - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
00393     myMed->SetMeshInfo(aMeshInfo);
00394 
00395     // Storing SMDS groups and sub-meshes as med families
00396     //----------------------------------------------------
00397     int myNodesDefaultFamilyId   = 0;
00398     int my0DElementsDefaultFamilyId = 0;
00399     int myEdgesDefaultFamilyId   = 0;
00400     int myFacesDefaultFamilyId   = 0;
00401     int myVolumesDefaultFamilyId = 0;
00402     int nbNodes   = myMesh->NbNodes();
00403     //int nb0DElements = myMesh->Nb0DElements();
00404     int nbEdges   = myMesh->NbEdges();
00405     int nbFaces   = myMesh->NbFaces();
00406     int nbVolumes = myMesh->NbVolumes();
00407     if (myDoGroupOfNodes && nbNodes)
00408       myNodesDefaultFamilyId = REST_NODES_FAMILY;
00409     if (myDoGroupOfEdges && nbEdges)
00410       myEdgesDefaultFamilyId = REST_EDGES_FAMILY;
00411     if (myDoGroupOfFaces && nbFaces)
00412       myFacesDefaultFamilyId = REST_FACES_FAMILY;
00413     if (myDoGroupOfVolumes && nbVolumes)
00414       myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY;
00415 
00416     MESSAGE("Perform - aFamilyInfo");
00417     //cout << " DriverMED_Family::MakeFamilies() " << endl;
00418     list<DriverMED_FamilyPtr> aFamilies;
00419     if (myAllSubMeshes) {
00420       aFamilies = DriverMED_Family::MakeFamilies
00421         (myMesh->SubMeshes(), myGroups,
00422          myDoGroupOfNodes   && nbNodes,
00423          myDoGroupOfEdges   && nbEdges,
00424          myDoGroupOfFaces   && nbFaces,
00425          myDoGroupOfVolumes && nbVolumes);
00426     } else {
00427       aFamilies = DriverMED_Family::MakeFamilies
00428         (mySubMeshes, myGroups,
00429          myDoGroupOfNodes   && nbNodes,
00430          myDoGroupOfEdges   && nbEdges,
00431          myDoGroupOfFaces   && nbFaces,
00432          myDoGroupOfVolumes && nbVolumes);
00433     }
00434     //cout << " myMed->SetFamilyInfo() " << endl;
00435     list<DriverMED_FamilyPtr>::iterator aFamsIter;
00436     for (aFamsIter = aFamilies.begin(); aFamsIter != aFamilies.end(); aFamsIter++)
00437     {
00438       PFamilyInfo aFamilyInfo = (*aFamsIter)->GetFamilyInfo(myMed,aMeshInfo);
00439       myMed->SetFamilyInfo(aFamilyInfo);
00440     }
00441 
00442     // Storing SMDS nodes to the MED file for the MED mesh
00443     //----------------------------------------------------
00444 #ifdef _EDF_NODE_IDS_
00445     typedef map<TInt,TInt> TNodeIdMap;
00446     TNodeIdMap aNodeIdMap;
00447 #endif
00448     const EModeSwitch   theMode        = eFULL_INTERLACE;
00449     const ERepere       theSystem      = eCART;
00450     const EBooleen      theIsElemNum   = eVRAI;
00451     const EBooleen      theIsElemNames = eFAUX;
00452     const EConnectivite theConnMode    = eNOD;
00453 
00454     TInt aNbNodes = myMesh->NbNodes();
00455     //cout << " myMed->CrNodeInfo() aNbNodes = " << aNbNodes << endl;
00456     PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo, aNbNodes,
00457                                             theMode, theSystem, theIsElemNum, theIsElemNames);
00458 
00459     //cout << " fillElemFamilyMap( SMDSAbs_Node )" << endl;
00460     // find family numbers for nodes
00461     TElemFamilyMap anElemFamMap;
00462     fillElemFamilyMap( anElemFamMap, aFamilies, SMDSAbs_Node );
00463 
00464     for (TInt iNode = 0; aCoordHelperPtr->Next(); iNode++)
00465     {
00466       // coordinates
00467       TCoordSlice aTCoordSlice = aNodeInfo->GetCoordSlice( iNode );
00468       for(TInt iCoord = 0; iCoord < aSpaceDimension; iCoord++){
00469         aTCoordSlice[iCoord] = aCoordHelperPtr->GetCoord(iCoord);
00470       }
00471       // node number
00472       int aNodeID = aCoordHelperPtr->GetID();
00473       aNodeInfo->SetElemNum( iNode, aNodeID );
00474 #ifdef _EDF_NODE_IDS_
00475       aNodeIdMap[aNodeID] = iNode+1;
00476 #endif
00477       // family number
00478       const SMDS_MeshNode* aNode = aCoordHelperPtr->GetNode();
00479       int famNum = getFamilyId( anElemFamMap, aNode, myNodesDefaultFamilyId );
00480       aNodeInfo->SetFamNum( iNode, famNum );
00481     }
00482     anElemFamMap.Clear();
00483 
00484     // coordinate names and units
00485     for (TInt iCoord = 0; iCoord < aSpaceDimension; iCoord++) {
00486       aNodeInfo->SetCoordName( iCoord, aCoordHelperPtr->GetName(iCoord));
00487       aNodeInfo->SetCoordUnit( iCoord, aCoordHelperPtr->GetUnit(iCoord));
00488     }
00489 
00490     //cout << " SetNodeInfo(aNodeInfo)" << endl;
00491     MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbNodes);
00492     myMed->SetNodeInfo(aNodeInfo);
00493     aNodeInfo.reset(); // free memory used for arrays
00494 
00495 
00496     // Storing SMDS elements to the MED file for the MED mesh
00497     //-------------------------------------------------------
00498     // Write one element type at once in order to minimize memory usage (PAL19276)
00499 
00500     const SMDS_MeshInfo& nbElemInfo = myMesh->GetMeshInfo();
00501 
00502     // poly elements are not supported by med-2.1
00503     bool polyTypesSupported = myMed->CrPolygoneInfo(aMeshInfo,eMAILLE,ePOLYGONE,0,0);
00504     TInt nbPolygonNodes = 0, nbPolyhedronNodes = 0, nbPolyhedronFaces = 0;
00505 
00506     // collect info on all geom types
00507 
00508     list< TElemTypeData > aTElemTypeDatas;
00509 
00510     EEntiteMaillage anEntity = eMAILLE;
00511 #ifdef _ELEMENTS_BY_DIM_
00512     anEntity = eNOEUD_ELEMENT;
00513 #endif
00514     aTElemTypeDatas.push_back(TElemTypeData(anEntity,
00515                                             ePOINT1,
00516                                             nbElemInfo.Nb0DElements(),
00517                                             SMDSAbs_0DElement));
00518 #ifdef _ELEMENTS_BY_DIM_
00519     anEntity = eARETE;
00520 #endif
00521     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00522                                             eSEG2,
00523                                             nbElemInfo.NbEdges( ORDER_LINEAR ),
00524                                             SMDSAbs_Edge));
00525     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00526                                             eSEG3,
00527                                             nbElemInfo.NbEdges( ORDER_QUADRATIC ),
00528                                             SMDSAbs_Edge));
00529 #ifdef _ELEMENTS_BY_DIM_
00530     anEntity = eFACE;
00531 #endif
00532     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00533                                             eTRIA3,
00534                                             nbElemInfo.NbTriangles( ORDER_LINEAR ),
00535                                             SMDSAbs_Face));
00536     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00537                                             eTRIA6,
00538                                             nbElemInfo.NbTriangles( ORDER_QUADRATIC ),
00539                                             SMDSAbs_Face));
00540     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00541                                             eQUAD4,
00542                                             nbElemInfo.NbQuadrangles( ORDER_LINEAR ),
00543                                             SMDSAbs_Face));
00544     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00545                                              eQUAD8,
00546                                              nbElemInfo.NbQuadrangles( ORDER_QUADRATIC ) -
00547                                              nbElemInfo.NbBiQuadQuadrangles(),
00548                                              SMDSAbs_Face));
00549     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00550                                              eQUAD9,
00551                                              nbElemInfo.NbBiQuadQuadrangles(),
00552                                              SMDSAbs_Face));
00553     if ( polyTypesSupported ) {
00554       aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00555                                                ePOLYGONE,
00556                                                nbElemInfo.NbPolygons(),
00557                                                SMDSAbs_Face));
00558       // we need one more loop on poly elements to count nb of their nodes
00559       aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00560                                                ePOLYGONE,
00561                                                nbElemInfo.NbPolygons(),
00562                                                SMDSAbs_Face));
00563     }
00564 #ifdef _ELEMENTS_BY_DIM_
00565     anEntity = eMAILLE;
00566 #endif
00567     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00568                                             eTETRA4,
00569                                             nbElemInfo.NbTetras( ORDER_LINEAR ),
00570                                             SMDSAbs_Volume));
00571     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00572                                             eTETRA10,
00573                                             nbElemInfo.NbTetras( ORDER_QUADRATIC ),
00574                                             SMDSAbs_Volume));
00575     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00576                                             ePYRA5,
00577                                             nbElemInfo.NbPyramids( ORDER_LINEAR ),
00578                                             SMDSAbs_Volume));
00579     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00580                                             ePYRA13,
00581                                             nbElemInfo.NbPyramids( ORDER_QUADRATIC ),
00582                                             SMDSAbs_Volume));
00583     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00584                                             ePENTA6,
00585                                             nbElemInfo.NbPrisms( ORDER_LINEAR ),
00586                                             SMDSAbs_Volume));
00587     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00588                                              ePENTA15,
00589                                              nbElemInfo.NbPrisms( ORDER_QUADRATIC ),
00590                                              SMDSAbs_Volume));
00591     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00592                                              eHEXA8,
00593                                              nbElemInfo.NbHexas( ORDER_LINEAR ),
00594                                              SMDSAbs_Volume));
00595     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00596                                              eHEXA20,
00597                                              nbElemInfo.NbHexas( ORDER_QUADRATIC )-
00598                                              nbElemInfo.NbTriQuadHexas(),
00599                                              SMDSAbs_Volume));
00600     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00601                                              eHEXA27,
00602                                              nbElemInfo.NbTriQuadHexas(),
00603                                              SMDSAbs_Volume));
00604     aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00605                                              eOCTA12,
00606                                              nbElemInfo.NbHexPrisms(),
00607                                              SMDSAbs_Volume));
00608     if ( polyTypesSupported ) {
00609       aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00610                                                ePOLYEDRE,
00611                                                nbElemInfo.NbPolyhedrons(),
00612                                                SMDSAbs_Volume));
00613       // we need one more loop on poly elements to count nb of their nodes
00614       aTElemTypeDatas.push_back( TElemTypeData(anEntity,
00615                                                ePOLYEDRE,
00616                                                nbElemInfo.NbPolyhedrons(),
00617                                                SMDSAbs_Volume));
00618     }
00619 
00620     vector< bool > isElemFamMapBuilt( SMDSAbs_NbElementTypes, false );
00621 
00622     // loop on all geom types of elements
00623 
00624     list< TElemTypeData >::iterator aElemTypeData = aTElemTypeDatas.begin();
00625     for ( ; aElemTypeData != aTElemTypeDatas.end(); ++aElemTypeData )
00626     {
00627       if ( aElemTypeData->_nbElems == 0 )
00628         continue;
00629 
00630       int defaultFamilyId = 0;
00631       switch ( aElemTypeData->_smdsType ) {
00632       case SMDSAbs_0DElement:
00633         defaultFamilyId = my0DElementsDefaultFamilyId;
00634         break;
00635       case SMDSAbs_Edge:
00636         defaultFamilyId = myEdgesDefaultFamilyId;
00637         break;
00638       case SMDSAbs_Face:
00639         defaultFamilyId = myFacesDefaultFamilyId;
00640         break;
00641       case SMDSAbs_Volume:
00642         defaultFamilyId = myVolumesDefaultFamilyId;
00643         break;
00644       default:
00645         continue;
00646       }
00647 
00648       // iterator on elements of a current type
00649       SMDS_ElemIteratorPtr elemIterator = myMesh->elementsIterator( aElemTypeData->_smdsType );
00650       if ( !elemIterator->more()) continue;
00651       int iElem = 0;
00652 
00653       // Treat POLYGONs
00654       // ---------------
00655       if ( aElemTypeData->_geomType == ePOLYGONE )
00656       {
00657         if ( nbPolygonNodes == 0 ) {
00658           // Count nb of nodes
00659           while ( const SMDS_MeshElement* anElem = elemIterator->next() ) {
00660             if ( anElem->IsPoly() ) {
00661               nbPolygonNodes += anElem->NbNodes();
00662               if ( ++iElem == aElemTypeData->_nbElems )
00663                 break;
00664             }
00665           }
00666         }
00667         else {
00668           // Store in med file
00669           PPolygoneInfo aPolygoneInfo = myMed->CrPolygoneInfo(aMeshInfo,
00670                                                               aElemTypeData->_entity,
00671                                                               aElemTypeData->_geomType,
00672                                                               aElemTypeData->_nbElems,
00673                                                               nbPolygonNodes,
00674                                                               theConnMode, theIsElemNum,
00675                                                               theIsElemNames);
00676           TElemNum & index = *(aPolygoneInfo->myIndex.get());
00677           index[0] = 1;
00678 
00679           while ( const SMDS_MeshElement* anElem = elemIterator->next() )
00680           {
00681             if ( !anElem->IsPoly() )
00682               continue;
00683 
00684             // index
00685             TInt aNbNodes = anElem->NbNodes();
00686             index[ iElem+1 ] = index[ iElem ] + aNbNodes;
00687 
00688             // connectivity
00689             TConnSlice aTConnSlice = aPolygoneInfo->GetConnSlice( iElem );
00690             for(TInt iNode = 0; iNode < aNbNodes; iNode++) {
00691               const SMDS_MeshElement* aNode = anElem->GetNode( iNode );
00692 #ifdef _EDF_NODE_IDS_
00693               aTConnSlice[ iNode ] = aNodeIdMap[aNode->GetID()];
00694 #else
00695               aTConnSlice[ iNode ] = aNode->GetID();
00696 #endif
00697             }
00698             // element number
00699             aPolygoneInfo->SetElemNum( iElem, anElem->GetID() );
00700 
00701             // family number
00702             int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId );
00703             aPolygoneInfo->SetFamNum( iElem, famNum );
00704 
00705             if ( ++iElem == aPolygoneInfo->GetNbElem() )
00706               break;
00707           }
00708           myMed->SetPolygoneInfo(aPolygoneInfo);
00709         }
00710 
00711       } 
00712 
00713       // Treat POLYEDREs
00714       // ----------------
00715       else if (aElemTypeData->_geomType == ePOLYEDRE )
00716       {
00717         if ( nbPolyhedronNodes == 0 ) {
00718           // Count nb of nodes
00719           while ( const SMDS_MeshElement* anElem = elemIterator->next() ) {
00720               const SMDS_VtkVolume *aPolyedre = dynamic_cast<const SMDS_VtkVolume*>(anElem);
00721               if ( aPolyedre && aPolyedre->IsPoly()) {
00722               nbPolyhedronNodes += aPolyedre->NbNodes();
00723               nbPolyhedronFaces += aPolyedre->NbFaces();
00724               if ( ++iElem == aElemTypeData->_nbElems )
00725                 break;
00726             }
00727           }
00728         }
00729         else {
00730           // Store in med file
00731           PPolyedreInfo aPolyhInfo = myMed->CrPolyedreInfo(aMeshInfo,
00732                                                            aElemTypeData->_entity,
00733                                                            aElemTypeData->_geomType,
00734                                                            aElemTypeData->_nbElems,
00735                                                            nbPolyhedronFaces+1,
00736                                                            nbPolyhedronNodes,
00737                                                            theConnMode,
00738                                                            theIsElemNum,
00739                                                            theIsElemNames);
00740           TElemNum & index = *(aPolyhInfo->myIndex.get());
00741           TElemNum & faces = *(aPolyhInfo->myFaces.get());
00742           TElemNum & conn  = *(aPolyhInfo->myConn.get());
00743           index[0] = 1;
00744           faces[0] = 1;
00745 
00746           TInt iFace = 0, iNode = 0;
00747           while ( const SMDS_MeshElement* anElem = elemIterator->next() )
00748           {
00749             const SMDS_VtkVolume *aPolyedre = dynamic_cast<const SMDS_VtkVolume*>(anElem);
00750             if ( !aPolyedre )
00751               continue;
00752             if ( !aPolyedre->IsPoly() )
00753               continue;
00754             // index
00755             TInt aNbFaces = aPolyedre->NbFaces();
00756             index[ iElem+1 ] = index[ iElem ] + aNbFaces;
00757 
00758             // face index
00759             for (TInt f = 1; f <= aNbFaces; ++f, ++iFace ) {
00760               int aNbFaceNodes = aPolyedre->NbFaceNodes( f );
00761               faces[ iFace+1 ] = faces[ iFace ] + aNbFaceNodes;
00762             }
00763             // connectivity
00764             SMDS_ElemIteratorPtr nodeIt = anElem->nodesIterator();
00765             while ( nodeIt->more() ) {
00766               const SMDS_MeshElement* aNode = nodeIt->next();
00767 #ifdef _EDF_NODE_IDS_
00768               conn[ iNode ] = aNodeIdMap[aNode->GetID()];
00769 #else
00770               conn[ iNode ] = aNode->GetID();
00771 #endif
00772               ++iNode;
00773             }
00774             // element number
00775             aPolyhInfo->SetElemNum( iElem, anElem->GetID() );
00776 
00777             // family number
00778             int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId );
00779             aPolyhInfo->SetFamNum( iElem, famNum );
00780 
00781             if ( ++iElem == aPolyhInfo->GetNbElem() )
00782               break;
00783           }
00784           myMed->SetPolyedreInfo(aPolyhInfo);
00785         }
00786       } // if (aElemTypeData->_geomType == ePOLYEDRE )
00787 
00788       else
00789       {
00790         // Treat standard types
00791         // ---------------------
00792 
00793         // allocate data arrays
00794         PCellInfo aCellInfo = myMed->CrCellInfo( aMeshInfo,
00795                                                  aElemTypeData->_entity,
00796                                                  aElemTypeData->_geomType,
00797                                                  aElemTypeData->_nbElems,
00798                                                  theConnMode,
00799                                                  theIsElemNum,
00800                                                  theIsElemNames);
00801         // build map of family numbers for this type
00802         if ( !isElemFamMapBuilt[ aElemTypeData->_smdsType ])
00803         {
00804           //cout << " fillElemFamilyMap()" << endl;
00805           fillElemFamilyMap( anElemFamMap, aFamilies, aElemTypeData->_smdsType );
00806           isElemFamMapBuilt[ aElemTypeData->_smdsType ] = true;
00807         }
00808 
00809         TInt aNbNodes = MED::GetNbNodes(aElemTypeData->_geomType);
00810         while ( const SMDS_MeshElement* anElem = elemIterator->next() )
00811         {
00812           if ( anElem->NbNodes() != aNbNodes || anElem->IsPoly() )
00813             continue; // other geometry
00814 
00815           // connectivity
00816           TConnSlice aTConnSlice = aCellInfo->GetConnSlice( iElem );
00817           for (TInt iNode = 0; iNode < aNbNodes; iNode++) {
00818             const SMDS_MeshElement* aNode = anElem->GetNode( iNode );
00819 #ifdef _EDF_NODE_IDS_
00820             aTConnSlice[ iNode ] = aNodeIdMap[aNode->GetID()];
00821 #else
00822             aTConnSlice[ iNode ] = aNode->GetID();
00823 #endif
00824           }
00825           // element number
00826           aCellInfo->SetElemNum( iElem, anElem->GetID() );
00827 
00828           // family number
00829           int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId );
00830           aCellInfo->SetFamNum( iElem, famNum );
00831 
00832           if ( ++iElem == aCellInfo->GetNbElem() )
00833             break;
00834         }
00835         // store data in a file
00836         myMed->SetCellInfo(aCellInfo);
00837       }
00838 
00839     } // loop on geom types
00840 
00841 
00842   }
00843   catch(const std::exception& exc) {
00844     INFOS("The following exception was caught:\n\t"<<exc.what());
00845     throw;
00846   }
00847   catch(...) {
00848     INFOS("Unknown exception was caught !!!");
00849     throw;
00850   }
00851 
00852   myMeshId = -1;
00853   myGroups.clear();
00854   mySubMeshes.clear();
00855   return aResult;
00856 }