Salome HOME
Merge from V5_1_3_BR branch (07/12/09)
[modules/smesh.git] / src / DriverMED / DriverMED_R_SMESHDS_Mesh.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH DriverMED : driver to read and write 'med' files
23 //  File   : DriverMED_R_SMESHDS_Mesh.cxx
24 //  Module : SMESH
25 //
26 #include "DriverMED_R_SMESHDS_Mesh.h"
27 #include "DriverMED_R_SMDS_Mesh.h"
28 #include "SMESHDS_Mesh.hxx"
29 #include "utilities.h"
30
31 #include "DriverMED_Family.h"
32
33 #include "SMESHDS_Group.hxx"
34
35 #include "MED_Factory.hxx"
36 #include "MED_CoordUtils.hxx"
37 #include "MED_Utilities.hxx"
38
39 #include <stdlib.h>
40
41 #ifdef _DEBUG_
42 static int MYDEBUG = 0;
43 //#define _DEXCEPT_
44 #else
45 static int MYDEBUG = 0;
46 #endif
47
48 #define _EDF_NODE_IDS_
49
50 using namespace MED;
51 using namespace std;
52
53 void
54 DriverMED_R_SMESHDS_Mesh
55 ::SetMeshName(string theMeshName)
56 {
57   myMeshName = theMeshName;
58 }
59
60 static const SMDS_MeshNode* 
61 FindNode(const SMDS_Mesh* theMesh, TInt theId){
62   const SMDS_MeshNode* aNode = theMesh->FindNode(theId);
63   if(aNode) return aNode;
64   EXCEPTION(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
65 }
66
67
68 Driver_Mesh::Status 
69 DriverMED_R_SMESHDS_Mesh
70 ::Perform()
71 {
72   Status aResult = DRS_FAIL;
73 #ifndef _DEXCEPT_
74   try{
75 #endif
76     myFamilies.clear();
77     if(MYDEBUG) MESSAGE("Perform - myFile : "<<myFile);
78     PWrapper aMed = CrWrapper(myFile,true);
79
80     aResult = DRS_EMPTY;
81     if(TInt aNbMeshes = aMed->GetNbMeshes()){
82       for(int iMesh = 0; iMesh < aNbMeshes; iMesh++){
83         // Reading the MED mesh
84         //---------------------
85         PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
86
87         string aMeshName;
88         if (myMeshId != -1) {
89           ostringstream aMeshNameStr;
90           aMeshNameStr<<myMeshId;
91           aMeshName = aMeshNameStr.str();
92         } else {
93           aMeshName = myMeshName;
94         }
95         if(MYDEBUG) MESSAGE("Perform - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
96         if(aMeshName != aMeshInfo->GetName()) continue;
97         aResult = DRS_OK;
98
99         //TInt aMeshDim = aMeshInfo->GetDim();
100         
101         // Reading MED families to the temporary structure
102         //------------------------------------------------
103         TErr anErr;
104         TInt aNbFams = aMed->GetNbFamilies(aMeshInfo);
105         if(MYDEBUG) MESSAGE("Read " << aNbFams << " families");
106         for (TInt iFam = 0; iFam < aNbFams; iFam++) {
107           PFamilyInfo aFamilyInfo = aMed->GetPFamilyInfo(aMeshInfo,iFam+1,&anErr);
108           if(anErr >= 0){
109             TInt aFamId = aFamilyInfo->GetId();
110             if(MYDEBUG) MESSAGE("Family " << aFamId << " :");
111             
112             DriverMED_FamilyPtr aFamily (new DriverMED_Family);
113             
114             TInt aNbGrp = aFamilyInfo->GetNbGroup();
115             if(MYDEBUG) MESSAGE("belong to " << aNbGrp << " groups");
116             bool isAttrOk = false;
117             if(aFamilyInfo->GetNbAttr() == aNbGrp)
118               isAttrOk = true;
119             for (TInt iGr = 0; iGr < aNbGrp; iGr++) {
120               string aGroupName = aFamilyInfo->GetGroupName(iGr);
121               if(isAttrOk){
122                 TInt anAttrVal = aFamilyInfo->GetAttrVal(iGr);
123                 aFamily->SetGroupAttributVal(anAttrVal);
124               }
125               
126               if(MYDEBUG) MESSAGE(aGroupName);
127               aFamily->AddGroupName(aGroupName);
128               
129             }
130             aFamily->SetId( aFamId );
131             myFamilies[aFamId] = aFamily;
132           }
133         }
134
135         if (aMeshInfo->GetType() == MED::eSTRUCTURE){
136           /*bool aRes = */buildMeshGrille(aMed,aMeshInfo);
137           continue;
138         }
139
140         // Reading MED nodes to the corresponding SMDS structure
141         //------------------------------------------------------
142         PNodeInfo aNodeInfo = aMed->GetPNodeInfo(aMeshInfo);
143         if (!aNodeInfo) {
144           aResult = DRS_FAIL;
145           continue;
146         }
147
148         PCoordHelper aCoordHelper = GetCoordHelper(aNodeInfo);
149
150         EBooleen anIsNodeNum = aNodeInfo->IsElemNum();
151         TInt aNbElems = aNodeInfo->GetNbElem();
152         if(MYDEBUG) MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems<<"; anIsNodeNum = "<<anIsNodeNum);
153         DriverMED_FamilyPtr aFamily;
154         for(TInt iElem = 0; iElem < aNbElems; iElem++){
155           TCCoordSlice aCoordSlice = aNodeInfo->GetCoordSlice(iElem);
156           double aCoords[3] = {0.0, 0.0, 0.0};
157           for(TInt iDim = 0; iDim < 3; iDim++)
158             aCoords[iDim] = aCoordHelper->GetCoord(aCoordSlice,iDim);
159           const SMDS_MeshNode* aNode;
160           if(anIsNodeNum) {
161             aNode = myMesh->AddNodeWithID
162               (aCoords[0],aCoords[1],aCoords[2],aNodeInfo->GetElemNum(iElem));
163           } else {
164             aNode = myMesh->AddNode
165               (aCoords[0],aCoords[1],aCoords[2]);
166           }
167           //cout<<aNode->GetID()<<": "<<aNode->X()<<", "<<aNode->Y()<<", "<<aNode->Z()<<endl;
168
169           // Save reference to this node from its family
170           TInt aFamNum = aNodeInfo->GetFamNum(iElem);
171           if ( checkFamilyID ( aFamily, aFamNum ))
172           {
173             aFamily->AddElement(aNode);
174             aFamily->SetType(SMDSAbs_Node);
175           }
176         }
177
178         // Reading pre information about all MED cells
179         //--------------------------------------------
180         typedef MED::TVector<int> TNodeIds;
181         bool takeNumbers = true;  // initially we trust the numbers from file
182         MED::TEntityInfo aEntityInfo = aMed->GetEntityInfo(aMeshInfo);
183         MED::TEntityInfo::iterator anEntityIter = aEntityInfo.begin();
184         for(; anEntityIter != aEntityInfo.end(); anEntityIter++){
185           const EEntiteMaillage& anEntity = anEntityIter->first;
186           if(anEntity == eNOEUD) continue;
187           // Reading MED cells to the corresponding SMDS structure
188           //------------------------------------------------------
189           const MED::TGeom2Size& aGeom2Size = anEntityIter->second;
190           MED::TGeom2Size::const_iterator aGeom2SizeIter = aGeom2Size.begin();
191           for(; aGeom2SizeIter != aGeom2Size.end(); aGeom2SizeIter++){
192             const EGeometrieElement& aGeom = aGeom2SizeIter->first;
193
194             switch(aGeom) {
195 //          case ePOINT1: ## PAL16410
196 //            break;
197             case ePOLYGONE: {
198               PPolygoneInfo aPolygoneInfo = aMed->GetPPolygoneInfo(aMeshInfo,anEntity,aGeom);
199               EBooleen anIsElemNum = takeNumbers ? aPolygoneInfo->IsElemNum() : eFAUX;
200               
201               TInt aNbElem = aPolygoneInfo->GetNbElem();
202               for(TInt iElem = 0; iElem < aNbElem; iElem++){
203                 MED::TCConnSlice aConnSlice = aPolygoneInfo->GetConnSlice(iElem);
204                 TInt aNbConn = aPolygoneInfo->GetNbConn(iElem);
205                 TNodeIds aNodeIds(aNbConn);
206 #ifdef _EDF_NODE_IDS_
207                 if(anIsNodeNum)
208                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
209                     aNodeIds[iConn] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
210                 else
211                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
212                     aNodeIds[iConn] = aConnSlice[iConn];
213 #else
214                 for(TInt iConn = 0; iConn < aNbConn; iConn++)
215                   aNodeIds[iConn] = aConnSlice[iConn];
216 #endif
217                 bool isRenum = false;
218                 SMDS_MeshElement* anElement = NULL;
219                 TInt aFamNum = aPolygoneInfo->GetFamNum(iElem);
220
221 #ifndef _DEXCEPT_
222                 try{
223 #endif
224                   if(anIsElemNum){
225                     TInt anElemId = aPolygoneInfo->GetElemNum(iElem);
226                     anElement = myMesh->AddPolygonalFaceWithID(aNodeIds,anElemId);
227                   }
228                   if(!anElement){
229                     vector<const SMDS_MeshNode*> aNodes(aNbConn);
230                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
231                       aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
232                     anElement = myMesh->AddPolygonalFace(aNodes);
233                     isRenum = anIsElemNum;
234                   }
235 #ifndef _DEXCEPT_
236                 }catch(const std::exception& exc){
237                   aResult = DRS_FAIL;
238                 }catch (...){
239                   aResult = DRS_FAIL;
240                 }
241 #endif
242                 if(!anElement){
243                   aResult = DRS_WARN_SKIP_ELEM;
244                 }else{
245                   if(isRenum){
246                     anIsElemNum = eFAUX;
247                     takeNumbers = false;
248                     if(aResult < DRS_WARN_RENUMBER)
249                       aResult = DRS_WARN_RENUMBER;
250                   }
251                   if ( checkFamilyID ( aFamily, aFamNum ))
252                   {
253                     // Save reference to this element from its family
254                     aFamily->AddElement(anElement);
255                     aFamily->SetType(anElement->GetType());
256                   }
257                 }
258               }
259               break;
260             }
261             case ePOLYEDRE: {
262               PPolyedreInfo aPolyedreInfo = aMed->GetPPolyedreInfo(aMeshInfo,anEntity,aGeom);
263               EBooleen anIsElemNum = takeNumbers ? aPolyedreInfo->IsElemNum() : eFAUX;
264
265               TInt aNbElem = aPolyedreInfo->GetNbElem();
266               for(TInt iElem = 0; iElem < aNbElem; iElem++){
267                 MED::TCConnSliceArr aConnSliceArr = aPolyedreInfo->GetConnSliceArr(iElem);
268                 TInt aNbFaces = aConnSliceArr.size();
269                 typedef MED::TVector<int> TQuantities;
270                 TQuantities aQuantities(aNbFaces);
271                 TInt aNbNodes = aPolyedreInfo->GetNbNodes(iElem);
272                 TNodeIds aNodeIds(aNbNodes);
273                 for(TInt iFace = 0, iNode = 0; iFace < aNbFaces; iFace++){
274                   MED::TCConnSlice aConnSlice = aConnSliceArr[iFace];
275                   TInt aNbConn = aConnSlice.size();
276                   aQuantities[iFace] = aNbConn;
277 #ifdef _EDF_NODE_IDS_
278                   if(anIsNodeNum)
279                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
280                       aNodeIds[iNode++] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
281                   else
282                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
283                       aNodeIds[iNode++] = aConnSlice[iConn];
284 #else
285                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
286                     aNodeIds[iNode++] = aConnSlice[iConn];
287 #endif          
288                 }
289
290                 bool isRenum = false;
291                 SMDS_MeshElement* anElement = NULL;
292                 TInt aFamNum = aPolyedreInfo->GetFamNum(iElem);
293                 
294 #ifndef _DEXCEPT_
295                 try{
296 #endif
297                   if(anIsElemNum){
298                     TInt anElemId = aPolyedreInfo->GetElemNum(iElem);
299                     anElement = myMesh->AddPolyhedralVolumeWithID(aNodeIds,aQuantities,anElemId);
300                   }
301                   if(!anElement){
302                     vector<const SMDS_MeshNode*> aNodes(aNbNodes);
303                     for(TInt iConn = 0; iConn < aNbNodes; iConn++)
304                       aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
305                     anElement = myMesh->AddPolyhedralVolume(aNodes,aQuantities);
306                     isRenum = anIsElemNum;
307                   }
308 #ifndef _DEXCEPT_
309                 }catch(const std::exception& exc){
310                   aResult = DRS_FAIL;
311                 }catch(...){
312                   aResult = DRS_FAIL;
313                 }
314 #endif          
315                 if(!anElement){
316                   aResult = DRS_WARN_SKIP_ELEM;
317                 }else{
318                   if(isRenum){
319                     anIsElemNum = eFAUX;
320                     takeNumbers = false;
321                     if (aResult < DRS_WARN_RENUMBER)
322                       aResult = DRS_WARN_RENUMBER;
323                   }
324                   if ( checkFamilyID ( aFamily, aFamNum )) {
325                     // Save reference to this element from its family
326                     aFamily->AddElement(anElement);
327                     aFamily->SetType(anElement->GetType());
328                   }
329                 }
330               }
331               break;
332             }
333             default: {
334               PCellInfo aCellInfo = aMed->GetPCellInfo(aMeshInfo,anEntity,aGeom);
335               EBooleen anIsElemNum = takeNumbers ? aCellInfo->IsElemNum() : eFAUX;
336               TInt aNbElems = aCellInfo->GetNbElem();
337               if(MYDEBUG) MESSAGE("Perform - anEntity = "<<anEntity<<"; anIsElemNum = "<<anIsElemNum);
338               if(MYDEBUG) MESSAGE("Perform - aGeom = "<<aGeom<<"; aNbElems = "<<aNbElems);
339
340               TInt aNbNodes = -1;
341               switch(aGeom){
342               case eSEG2:    aNbNodes = 2;  break;
343               case eSEG3:    aNbNodes = 3;  break;
344               case eTRIA3:   aNbNodes = 3;  break;
345               case eTRIA6:   aNbNodes = 6;  break;
346               case eQUAD4:   aNbNodes = 4;  break;
347               case eQUAD8:   aNbNodes = 8;  break;
348               case eTETRA4:  aNbNodes = 4;  break;
349               case eTETRA10: aNbNodes = 10; break;
350               case ePYRA5:   aNbNodes = 5;  break;
351               case ePYRA13:  aNbNodes = 13; break;
352               case ePENTA6:  aNbNodes = 6;  break;
353               case ePENTA15: aNbNodes = 15; break;
354               case eHEXA8:   aNbNodes = 8;  break;
355               case eHEXA20:  aNbNodes = 20; break;
356               case ePOINT1:  aNbNodes = 1;  break;
357               default:;
358               }
359               vector<TInt> aNodeIds(aNbNodes);
360               for(int iElem = 0; iElem < aNbElems; iElem++){
361                 bool anIsValidConnect = false;
362                 TCConnSlice aConnSlice = aCellInfo->GetConnSlice(iElem);
363 #ifndef _DEXCEPT_
364                 try{
365 #endif
366 #ifdef _EDF_NODE_IDS_
367                   if(anIsNodeNum)
368                     for(int iNode = 0; iNode < aNbNodes; iNode++)
369                       aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iNode] - 1);
370                   else
371                     for(int iNode = 0; iNode < aNbNodes; iNode++)
372                       aNodeIds[iNode] = aConnSlice[iNode];
373 #else
374                   for(int iNode = 0; iNode < aNbNodes; iNode++)
375                     aNodeIds[iNode] = aConnSlice[iNode];
376 #endif
377                   anIsValidConnect = true;
378 #ifndef _DEXCEPT_
379                 }catch(const std::exception& exc){
380                   //INFOS("Follow exception was cought:\n\t"<<exc.what());
381                   aResult = DRS_FAIL;
382                 }catch(...){
383                   //INFOS("Unknown exception was cought !!!");
384                   aResult = DRS_FAIL;
385                 }
386 #endif          
387                 if(!anIsValidConnect)
388                   continue;
389
390                 bool isRenum = false;
391                 const SMDS_MeshElement* anElement = NULL;
392                 TInt aFamNum = aCellInfo->GetFamNum(iElem);
393 #ifndef _DEXCEPT_
394                 try{
395 #endif
396                   //MESSAGE("Try to create element # " << iElem << " with id = "
397                   //        << aCellInfo->GetElemNum(iElem));
398                   switch(aGeom) {
399                   case ePOINT1:
400                     //anElement = FindNode(myMesh,aNodeIds[0]);
401                     if(anIsElemNum)
402                       anElement = myMesh->Add0DElementWithID
403                         (aNodeIds[0], aCellInfo->GetElemNum(iElem));
404                     if (!anElement) {
405                       anElement = myMesh->Add0DElement(FindNode(myMesh,aNodeIds[0]));
406                       isRenum = anIsElemNum;
407                     }
408                     break;
409                   case eSEG2:
410                     if(anIsElemNum)
411                       anElement = myMesh->AddEdgeWithID(aNodeIds[0],
412                                                         aNodeIds[1],
413                                                         aCellInfo->GetElemNum(iElem));
414                     if (!anElement) {
415                       anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
416                                                   FindNode(myMesh,aNodeIds[1]));
417                       isRenum = anIsElemNum;
418                     }
419                     break;
420                   case eSEG3:
421                     if(anIsElemNum)
422                       anElement = myMesh->AddEdgeWithID(aNodeIds[0],
423                                                         aNodeIds[1],
424                                                         aNodeIds[2],
425                                                         aCellInfo->GetElemNum(iElem));
426                     if (!anElement) {
427                       anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
428                                                   FindNode(myMesh,aNodeIds[1]),
429                                                   FindNode(myMesh,aNodeIds[2]));
430                       isRenum = anIsElemNum;
431                     }
432                     break;
433                   case eTRIA3:
434                     aNbNodes = 3;
435                     if(anIsElemNum)
436                       anElement = myMesh->AddFaceWithID(aNodeIds[0],
437                                                         aNodeIds[1],
438                                                         aNodeIds[2],
439                                                         aCellInfo->GetElemNum(iElem));
440                     if (!anElement) {
441                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
442                                                   FindNode(myMesh,aNodeIds[1]),
443                                                   FindNode(myMesh,aNodeIds[2]));
444                       isRenum = anIsElemNum;
445                     }
446                     break;
447                   case eTRIA6:
448                     aNbNodes = 6;
449                     if(anIsElemNum)
450                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
451                                                         aNodeIds[2], aNodeIds[3],
452                                                         aNodeIds[4], aNodeIds[5],
453                                                         aCellInfo->GetElemNum(iElem));
454                     if (!anElement) {
455                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
456                                                   FindNode(myMesh,aNodeIds[1]),
457                                                   FindNode(myMesh,aNodeIds[2]),
458                                                   FindNode(myMesh,aNodeIds[3]),
459                                                   FindNode(myMesh,aNodeIds[4]),
460                                                   FindNode(myMesh,aNodeIds[5]));
461                       isRenum = anIsElemNum;
462                     }
463                     break;
464                   case eQUAD4:
465                     aNbNodes = 4;
466                     if(anIsElemNum)
467                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
468                                                         aNodeIds[2], aNodeIds[3],
469                                                         aCellInfo->GetElemNum(iElem));
470                     if (!anElement) {
471                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
472                                                   FindNode(myMesh,aNodeIds[1]),
473                                                   FindNode(myMesh,aNodeIds[2]),
474                                                   FindNode(myMesh,aNodeIds[3]));
475                       isRenum = anIsElemNum;
476                     }
477                     break;
478                   case eQUAD8:
479                     aNbNodes = 8;
480                     if(anIsElemNum)
481                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
482                                                         aNodeIds[2], aNodeIds[3],
483                                                         aNodeIds[4], aNodeIds[5],
484                                                         aNodeIds[6], aNodeIds[7],
485                                                         aCellInfo->GetElemNum(iElem));
486                     if (!anElement) {
487                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
488                                                   FindNode(myMesh,aNodeIds[1]),
489                                                   FindNode(myMesh,aNodeIds[2]),
490                                                   FindNode(myMesh,aNodeIds[3]),
491                                                   FindNode(myMesh,aNodeIds[4]),
492                                                   FindNode(myMesh,aNodeIds[5]),
493                                                   FindNode(myMesh,aNodeIds[6]),
494                                                   FindNode(myMesh,aNodeIds[7]));
495                       isRenum = anIsElemNum;
496                     }
497                     break;
498                   case eTETRA4:
499                     aNbNodes = 4;
500                     if(anIsElemNum)
501                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
502                                                           aNodeIds[2], aNodeIds[3],
503                                                           aCellInfo->GetElemNum(iElem));
504                     if (!anElement) {
505                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
506                                                     FindNode(myMesh,aNodeIds[1]),
507                                                     FindNode(myMesh,aNodeIds[2]),
508                                                     FindNode(myMesh,aNodeIds[3]));
509                       isRenum = anIsElemNum;
510                     }
511                     break;
512                   case eTETRA10:
513                     aNbNodes = 10;
514                     if(anIsElemNum)
515                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
516                                                           aNodeIds[2], aNodeIds[3],
517                                                           aNodeIds[4], aNodeIds[5],
518                                                           aNodeIds[6], aNodeIds[7],
519                                                           aNodeIds[8], aNodeIds[9],
520                                                           aCellInfo->GetElemNum(iElem));
521                     if (!anElement) {
522                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
523                                                     FindNode(myMesh,aNodeIds[1]),
524                                                     FindNode(myMesh,aNodeIds[2]),
525                                                     FindNode(myMesh,aNodeIds[3]),
526                                                     FindNode(myMesh,aNodeIds[4]),
527                                                     FindNode(myMesh,aNodeIds[5]),
528                                                     FindNode(myMesh,aNodeIds[6]),
529                                                     FindNode(myMesh,aNodeIds[7]),
530                                                     FindNode(myMesh,aNodeIds[8]),
531                                                     FindNode(myMesh,aNodeIds[9]));
532                       isRenum = anIsElemNum;
533                     }
534                     break;
535                   case ePYRA5:
536                     aNbNodes = 5;
537                     // There is some differnce between SMDS and MED
538                     if(anIsElemNum)
539                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
540                                                           aNodeIds[2], aNodeIds[3],
541                                                           aNodeIds[4],
542                                                           aCellInfo->GetElemNum(iElem));
543                     if (!anElement) {
544                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
545                                                     FindNode(myMesh,aNodeIds[1]),
546                                                     FindNode(myMesh,aNodeIds[2]),
547                                                     FindNode(myMesh,aNodeIds[3]),
548                                                     FindNode(myMesh,aNodeIds[4]));
549                       isRenum = anIsElemNum;
550                     }
551                     break;
552                   case ePYRA13:
553                     aNbNodes = 13;
554                     // There is some differnce between SMDS and MED
555                     if(anIsElemNum)
556                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
557                                                           aNodeIds[2], aNodeIds[3],
558                                                           aNodeIds[4], aNodeIds[5],
559                                                           aNodeIds[6], aNodeIds[7],
560                                                           aNodeIds[8], aNodeIds[9],
561                                                           aNodeIds[10], aNodeIds[11],
562                                                           aNodeIds[12],
563                                                           aCellInfo->GetElemNum(iElem));
564                     if (!anElement) {
565                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
566                                                     FindNode(myMesh,aNodeIds[1]),
567                                                     FindNode(myMesh,aNodeIds[2]),
568                                                     FindNode(myMesh,aNodeIds[3]),
569                                                     FindNode(myMesh,aNodeIds[4]),
570                                                     FindNode(myMesh,aNodeIds[5]),
571                                                     FindNode(myMesh,aNodeIds[6]),
572                                                     FindNode(myMesh,aNodeIds[7]),
573                                                     FindNode(myMesh,aNodeIds[8]),
574                                                     FindNode(myMesh,aNodeIds[9]),
575                                                     FindNode(myMesh,aNodeIds[10]),
576                                                     FindNode(myMesh,aNodeIds[11]),
577                                                     FindNode(myMesh,aNodeIds[12]));
578                       isRenum = anIsElemNum;
579                     }
580                     break;
581                   case ePENTA6:
582                     aNbNodes = 6;
583                     if(anIsElemNum)
584                       anElement = myMesh->AddVolumeWithID(aNodeIds[0],
585                                                           aNodeIds[1],
586                                                           aNodeIds[2],
587                                                           aNodeIds[3],
588                                                           aNodeIds[4],
589                                                           aNodeIds[5],
590                                                           aCellInfo->GetElemNum(iElem));
591                     if (!anElement) {
592                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
593                                                     FindNode(myMesh,aNodeIds[1]),
594                                                     FindNode(myMesh,aNodeIds[2]),
595                                                     FindNode(myMesh,aNodeIds[3]),
596                                                     FindNode(myMesh,aNodeIds[4]),
597                                                     FindNode(myMesh,aNodeIds[5]));
598                       isRenum = anIsElemNum;
599                     }
600                     break;
601                   case ePENTA15:
602                     aNbNodes = 15;
603                     if(anIsElemNum)
604                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
605                                                           aNodeIds[2], aNodeIds[3],
606                                                           aNodeIds[4], aNodeIds[5],
607                                                           aNodeIds[6], aNodeIds[7],
608                                                           aNodeIds[8], aNodeIds[9],
609                                                           aNodeIds[10], aNodeIds[11],
610                                                           aNodeIds[12], aNodeIds[13],
611                                                           aNodeIds[14],
612                                                           aCellInfo->GetElemNum(iElem));
613                     if (!anElement) {
614                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
615                                                     FindNode(myMesh,aNodeIds[1]),
616                                                     FindNode(myMesh,aNodeIds[2]),
617                                                     FindNode(myMesh,aNodeIds[3]),
618                                                   FindNode(myMesh,aNodeIds[4]),
619                                                     FindNode(myMesh,aNodeIds[5]),
620                                                     FindNode(myMesh,aNodeIds[6]),
621                                                     FindNode(myMesh,aNodeIds[7]),
622                                                     FindNode(myMesh,aNodeIds[8]),
623                                                     FindNode(myMesh,aNodeIds[9]),
624                                                     FindNode(myMesh,aNodeIds[10]),
625                                                     FindNode(myMesh,aNodeIds[11]),
626                                                     FindNode(myMesh,aNodeIds[12]),
627                                                     FindNode(myMesh,aNodeIds[13]),
628                                                     FindNode(myMesh,aNodeIds[14]));
629                       isRenum = anIsElemNum;
630                     }
631                     break;
632                   case eHEXA8:
633                     aNbNodes = 8;
634                     if(anIsElemNum)
635                       anElement = myMesh->AddVolumeWithID(aNodeIds[0],
636                                                           aNodeIds[1],
637                                                           aNodeIds[2],
638                                                           aNodeIds[3],
639                                                           aNodeIds[4],
640                                                           aNodeIds[5],
641                                                           aNodeIds[6],
642                                                           aNodeIds[7],
643                                                           aCellInfo->GetElemNum(iElem));
644                     if (!anElement) {
645                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
646                                                     FindNode(myMesh,aNodeIds[1]),
647                                                     FindNode(myMesh,aNodeIds[2]),
648                                                     FindNode(myMesh,aNodeIds[3]),
649                                                     FindNode(myMesh,aNodeIds[4]),
650                                                     FindNode(myMesh,aNodeIds[5]),
651                                                     FindNode(myMesh,aNodeIds[6]),
652                                                     FindNode(myMesh,aNodeIds[7]));
653                       isRenum = anIsElemNum;
654                     }
655                     break;
656                   case eHEXA20:
657                     aNbNodes = 20;
658                     if(anIsElemNum)
659                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
660                                                           aNodeIds[2], aNodeIds[3],
661                                                           aNodeIds[4], aNodeIds[5],
662                                                           aNodeIds[6], aNodeIds[7],
663                                                           aNodeIds[8], aNodeIds[9],
664                                                           aNodeIds[10], aNodeIds[11],
665                                                           aNodeIds[12], aNodeIds[13],
666                                                           aNodeIds[14], aNodeIds[15],
667                                                           aNodeIds[16], aNodeIds[17],
668                                                           aNodeIds[18], aNodeIds[19],
669                                                           aCellInfo->GetElemNum(iElem));
670                     if (!anElement) {
671                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
672                                                     FindNode(myMesh,aNodeIds[1]),
673                                                     FindNode(myMesh,aNodeIds[2]),
674                                                     FindNode(myMesh,aNodeIds[3]),
675                                                     FindNode(myMesh,aNodeIds[4]),
676                                                     FindNode(myMesh,aNodeIds[5]),
677                                                     FindNode(myMesh,aNodeIds[6]),
678                                                     FindNode(myMesh,aNodeIds[7]),
679                                                     FindNode(myMesh,aNodeIds[8]),
680                                                     FindNode(myMesh,aNodeIds[9]),
681                                                     FindNode(myMesh,aNodeIds[10]),
682                                                     FindNode(myMesh,aNodeIds[11]),
683                                                     FindNode(myMesh,aNodeIds[12]),
684                                                     FindNode(myMesh,aNodeIds[13]),
685                                                     FindNode(myMesh,aNodeIds[14]),
686                                                     FindNode(myMesh,aNodeIds[15]),
687                                                     FindNode(myMesh,aNodeIds[16]),
688                                                     FindNode(myMesh,aNodeIds[17]),
689                                                     FindNode(myMesh,aNodeIds[18]),
690                                                     FindNode(myMesh,aNodeIds[19]));
691                       isRenum = anIsElemNum;
692                     }
693                     break;
694                   }
695
696 #ifndef _DEXCEPT_
697                 }catch(const std::exception& exc){
698                   //INFOS("Follow exception was cought:\n\t"<<exc.what());
699                   aResult = DRS_FAIL;
700                 }catch(...){
701                   //INFOS("Unknown exception was cought !!!");
702                   aResult = DRS_FAIL;
703                 }
704 #endif          
705                 if (!anElement) {
706                   aResult = DRS_WARN_SKIP_ELEM;
707                 }
708                 else {
709                   if (isRenum) {
710                     anIsElemNum = eFAUX;
711                     takeNumbers = false;
712                     if (aResult < DRS_WARN_RENUMBER)
713                       aResult = DRS_WARN_RENUMBER;
714                   }
715                   if ( checkFamilyID ( aFamily, aFamNum )) {
716                     // Save reference to this element from its family
717                     myFamilies[aFamNum]->AddElement(anElement);
718                     myFamilies[aFamNum]->SetType(anElement->GetType());
719                   }
720                 }
721               }
722             }}
723           }
724         }
725       }
726     }
727 #ifndef _DEXCEPT_
728   }catch(const std::exception& exc){
729     INFOS("Follow exception was cought:\n\t"<<exc.what());
730     aResult = DRS_FAIL;
731   }catch(...){
732     INFOS("Unknown exception was cought !!!");
733     aResult = DRS_FAIL;
734   }
735 #endif
736   if(MYDEBUG) MESSAGE("Perform - aResult status = "<<aResult);
737   return aResult;
738 }
739
740 list<string> DriverMED_R_SMESHDS_Mesh::GetMeshNames(Status& theStatus)
741 {
742   list<string> aMeshNames;
743
744   try {
745     if(MYDEBUG) MESSAGE("GetMeshNames - myFile : " << myFile);
746     theStatus = DRS_OK;
747     PWrapper aMed = CrWrapper(myFile);
748
749     if (TInt aNbMeshes = aMed->GetNbMeshes()) {
750       for (int iMesh = 0; iMesh < aNbMeshes; iMesh++) {
751         // Reading the MED mesh
752         //---------------------
753         PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
754         aMeshNames.push_back(aMeshInfo->GetName());
755       }
756     }
757   }catch(const std::exception& exc){
758     INFOS("Follow exception was cought:\n\t"<<exc.what());
759     theStatus = DRS_FAIL;
760   }catch(...){
761     INFOS("Unknown exception was cought !!!");
762     theStatus = DRS_FAIL;
763   }
764
765   return aMeshNames;
766 }
767
768 list<TNameAndType> DriverMED_R_SMESHDS_Mesh::GetGroupNamesAndTypes()
769 {
770   list<TNameAndType> aResult;
771   set<TNameAndType> aResGroupNames;
772
773   map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
774   for (; aFamsIter != myFamilies.end(); aFamsIter++)
775   {
776     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
777     const MED::TStringSet& aGroupNames = aFamily->GetGroupNames();
778     set<string>::const_iterator aGrNamesIter = aGroupNames.begin();
779     for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
780     {
781       const set< SMDSAbs_ElementType >& types = aFamily->GetTypes();
782       set< SMDSAbs_ElementType >::const_iterator type = types.begin();
783       for ( ; type != types.end(); ++type )
784       {
785         TNameAndType aNameAndType = make_pair( *aGrNamesIter, *type );
786         if ( aResGroupNames.insert( aNameAndType ).second ) {
787           aResult.push_back( aNameAndType );
788         }
789       }
790     }
791   }
792
793   return aResult;
794 }
795
796 void DriverMED_R_SMESHDS_Mesh::GetGroup(SMESHDS_Group* theGroup)
797 {
798   string aGroupName (theGroup->GetStoreName());
799   if(MYDEBUG) MESSAGE("Get Group " << aGroupName);
800
801   map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
802   for (; aFamsIter != myFamilies.end(); aFamsIter++)
803   {
804     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
805     if (aFamily->GetTypes().count( theGroup->GetType() ) && aFamily->MemberOf(aGroupName))
806     {
807       const set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
808       set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElements.begin();
809       for (; anElemsIter != anElements.end(); anElemsIter++)
810       {
811         const SMDS_MeshElement * element = *anElemsIter;
812         if ( element->GetType() == theGroup->GetType() ) // Issue 0020576
813           theGroup->SMDSGroup().Add(element);
814       }
815       int aGroupAttrVal = aFamily->GetGroupAttributVal();
816       if( aGroupAttrVal != 0)
817         theGroup->SetColorGroup(aGroupAttrVal);
818 //       if ( element ) -- Issue 0020576
819 //         theGroup->SetType( theGroup->SMDSGroup().GetType() );
820     }
821   }
822 }
823
824 void DriverMED_R_SMESHDS_Mesh::GetSubMesh (SMESHDS_SubMesh* theSubMesh,
825                                            const int theId)
826 {
827   char submeshGrpName[ 30 ];
828   sprintf( submeshGrpName, "SubMesh %d", theId );
829   string aName (submeshGrpName);
830   map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
831   for (; aFamsIter != myFamilies.end(); aFamsIter++)
832   {
833     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
834     if (aFamily->MemberOf(aName))
835     {
836       const set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
837       set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElements.begin();
838       if (aFamily->GetType() == SMDSAbs_Node)
839       {
840         for (; anElemsIter != anElements.end(); anElemsIter++)
841         {
842           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>(*anElemsIter);
843           theSubMesh->AddNode(node);
844         }
845       }
846       else
847       {
848         for (; anElemsIter != anElements.end(); anElemsIter++)
849         {
850           theSubMesh->AddElement(*anElemsIter);
851         }
852       }
853     }
854   }
855 }
856
857 void DriverMED_R_SMESHDS_Mesh::CreateAllSubMeshes ()
858 {
859   map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
860   for (; aFamsIter != myFamilies.end(); aFamsIter++)
861   {
862     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
863     MED::TStringSet aGroupNames = aFamily->GetGroupNames();
864     set<string>::iterator aGrNamesIter = aGroupNames.begin();
865     for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
866     {
867       string aName = *aGrNamesIter;
868       // Check, if this is a Group or SubMesh name
869       if (aName.substr(0, 7) == string("SubMesh"))
870       {
871         int Id = atoi(string(aName).substr(7).c_str());
872         set<const SMDS_MeshElement *> anElements = aFamily->GetElements();
873         set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
874         if (aFamily->GetType() == SMDSAbs_Node)
875         {
876           for (; anElemsIter != anElements.end(); anElemsIter++)
877           {
878             SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>
879               ( static_cast<const SMDS_MeshNode*>( *anElemsIter ));
880             // find out a shape type
881             TopoDS_Shape aShape = myMesh->IndexToShape( Id );
882             int aShapeType = ( aShape.IsNull() ? -1 : aShape.ShapeType() );
883             switch ( aShapeType ) {
884             case TopAbs_FACE:
885               myMesh->SetNodeOnFace(node, Id); break;
886             case TopAbs_EDGE:
887               myMesh->SetNodeOnEdge(node, Id); break;
888             case TopAbs_VERTEX:
889               myMesh->SetNodeOnVertex(node, Id); break;
890             default:
891               myMesh->SetNodeInVolume(node, Id);
892             }
893           }
894         }
895         else
896         {
897           for (; anElemsIter != anElements.end(); anElemsIter++)
898           {
899             myMesh->SetMeshElementOnShape(*anElemsIter, Id);
900           }
901         }
902       }
903     }
904   }
905 }
906 /*!
907  * \brief Ensure aFamily to have required ID
908  * \param aFamily - a family to check and update
909  * \param anID - an ID aFamily should have
910  * \retval bool  - true if successful
911  */
912 bool DriverMED_R_SMESHDS_Mesh::checkFamilyID(DriverMED_FamilyPtr & aFamily, int anID) const
913 {
914   if ( !aFamily || aFamily->GetId() != anID ) {
915     map<int, DriverMED_FamilyPtr>::const_iterator i_fam = myFamilies.find(anID);
916     if ( i_fam == myFamilies.end() )
917       return false;
918     aFamily = i_fam->second;
919   }
920   return ( aFamily->GetId() == anID );
921 }
922
923
924 /*! \brief Reading the structured mesh and convert to non structured (by filling of smesh structure for non structured mesh)
925  * \param theWrapper  - PWrapper const pointer
926  * \param theMeshInfo - PMeshInfo const pointer
927  * \return TRUE, if successfully. Else FALSE
928  */
929 bool DriverMED_R_SMESHDS_Mesh::buildMeshGrille(const MED::PWrapper& theWrapper,
930                                                const MED::PMeshInfo& theMeshInfo)
931 {
932   bool res = true;
933
934   MED::PGrilleInfo aGrilleInfo = theWrapper->GetPGrilleInfo(theMeshInfo);
935   MED::TInt aNbNodes = aGrilleInfo->GetNbNodes();
936   MED::TInt aNbCells = aGrilleInfo->GetNbCells();
937   MED::TInt aMeshDim = theMeshInfo->GetDim();
938   DriverMED_FamilyPtr aFamily;
939   for(MED::TInt iNode=0;iNode < aNbNodes; iNode++){
940     double aCoords[3] = {0.0, 0.0, 0.0};
941     const SMDS_MeshNode* aNode;
942     MED::TNodeCoord aMEDNodeCoord = aGrilleInfo->GetCoord(iNode);
943     for(MED::TInt iDim=0;iDim<aMeshDim;iDim++)
944       aCoords[(int)iDim] = aMEDNodeCoord[(int)iDim];
945     aNode = myMesh->AddNodeWithID(aCoords[0],aCoords[1],aCoords[2],(int)iNode);
946
947     if((aGrilleInfo->myFamNumNode).size() > 0){
948       TInt aFamNum = aGrilleInfo->GetFamNumNode(iNode);
949       if ( checkFamilyID ( aFamily, aFamNum ))
950         {
951           aFamily->AddElement(aNode);
952           aFamily->SetType(SMDSAbs_Node);
953         }
954     }
955     
956   }
957
958   SMDS_MeshElement* anElement = NULL;
959   MED::TIntVector aNodeIds;
960   for(MED::TInt iCell=0;iCell < aNbCells; iCell++){
961     aNodeIds = aGrilleInfo->GetConn(iCell);
962     switch(aGrilleInfo->GetGeom()){
963     case MED::eSEG2:
964       if(aNodeIds.size() != 2){
965         res = false;
966         EXCEPTION(runtime_error,"buildMeshGrille Error. Incorrect size of ids 2!="<<aNodeIds.size());
967       }
968       anElement = myMesh->AddEdgeWithID(aNodeIds[0],
969                                         aNodeIds[1],
970                                         iCell);
971       break;
972     case MED::eQUAD4:
973       if(aNodeIds.size() != 4){
974         res = false;
975         EXCEPTION(runtime_error,"buildMeshGrille Error. Incorrect size of ids 4!="<<aNodeIds.size());
976       }
977       anElement = myMesh->AddFaceWithID(aNodeIds[0],
978                                         aNodeIds[2],
979                                         aNodeIds[3],
980                                         aNodeIds[1],
981                                         iCell);
982       break;
983     case MED::eHEXA8:
984       if(aNodeIds.size() != 8){
985         res = false;
986         EXCEPTION(runtime_error,"buildMeshGrille Error. Incorrect size of ids 8!="<<aNodeIds.size());
987       }
988       anElement = myMesh->AddVolumeWithID(aNodeIds[0],
989                                           aNodeIds[2],
990                                           aNodeIds[3],
991                                           aNodeIds[1],
992                                           aNodeIds[4],
993                                           aNodeIds[6],
994                                           aNodeIds[7],
995                                           aNodeIds[5],
996                                           iCell);
997       break;
998     default:
999       break;
1000     }
1001     
1002     if((aGrilleInfo->myFamNum).size() > 0){
1003       TInt aFamNum = aGrilleInfo->GetFamNum(iCell);
1004       if ( checkFamilyID ( aFamily, aFamNum )){
1005         aFamily->AddElement(anElement);
1006         aFamily->SetType(anElement->GetType());
1007       }
1008     }
1009   }
1010
1011   return res;
1012 }