Salome HOME
Fix for the bug "21427: EDF 2024 SMESH: numbering does not take into account clipping".
[modules/smesh.git] / src / DriverMED / DriverMED_R_SMESHDS_Mesh.cxx
1 // Copyright (C) 2007-2011  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
23 //  SMESH DriverMED : driver to read and write 'med' files
24 //  File   : DriverMED_R_SMESHDS_Mesh.cxx
25 //  Module : SMESH
26 //
27 #include "DriverMED_R_SMESHDS_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 = 1;
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         aMeshInfo->myDim=aMeshInfo->mySpaceDim;//Bug correction to ignore meshdim in MEDFile because can be false.
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             //MESSAGE("AddNodeWithID " << aNodeInfo->GetElemNum(iElem));
164           } else {
165             aNode = myMesh->AddNodeWithID
166               (aCoords[0],aCoords[1],aCoords[2], iElem+1);
167             //MESSAGE("AddNode " << aNode->GetID());
168           }
169           //cout<<aNode->GetID()<<": "<<aNode->X()<<", "<<aNode->Y()<<", "<<aNode->Z()<<endl;
170
171           // Save reference to this node from its family
172           TInt aFamNum = aNodeInfo->GetFamNum(iElem);
173           if ( checkFamilyID ( aFamily, aFamNum ))
174           {
175             aFamily->AddElement(aNode);
176             aFamily->SetType(SMDSAbs_Node);
177           }
178         }
179
180         // Reading pre information about all MED cells
181         //--------------------------------------------
182         typedef MED::TVector<int> TNodeIds;
183         bool takeNumbers = true;  // initially we trust the numbers from file
184         MED::TEntityInfo aEntityInfo = aMed->GetEntityInfo(aMeshInfo);
185         MED::TEntityInfo::iterator anEntityIter = aEntityInfo.begin();
186         for(; anEntityIter != aEntityInfo.end(); anEntityIter++){
187           const EEntiteMaillage& anEntity = anEntityIter->first;
188           if(anEntity == eNOEUD) continue;
189           // Reading MED cells to the corresponding SMDS structure
190           //------------------------------------------------------
191           const MED::TGeom2Size& aGeom2Size = anEntityIter->second;
192           MED::TGeom2Size::const_iterator aGeom2SizeIter = aGeom2Size.begin();
193           for(; aGeom2SizeIter != aGeom2Size.end(); aGeom2SizeIter++){
194             const EGeometrieElement& aGeom = aGeom2SizeIter->first;
195
196             switch(aGeom) {
197 //          case ePOINT1: ## PAL16410
198 //            break;
199             case ePOLYGONE: {
200               PPolygoneInfo aPolygoneInfo = aMed->GetPPolygoneInfo(aMeshInfo,anEntity,aGeom);
201               EBooleen anIsElemNum = takeNumbers ? aPolygoneInfo->IsElemNum() : eFAUX;
202               
203               TInt aNbElem = aPolygoneInfo->GetNbElem();
204               for(TInt iElem = 0; iElem < aNbElem; iElem++){
205                 MED::TCConnSlice aConnSlice = aPolygoneInfo->GetConnSlice(iElem);
206                 TInt aNbConn = aPolygoneInfo->GetNbConn(iElem);
207                 TNodeIds aNodeIds(aNbConn);
208 #ifdef _EDF_NODE_IDS_
209                 if(anIsNodeNum)
210                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
211                     aNodeIds[iConn] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
212                 else
213                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
214                     aNodeIds[iConn] = aConnSlice[iConn];
215 #else
216                 for(TInt iConn = 0; iConn < aNbConn; iConn++)
217                   aNodeIds[iConn] = aConnSlice[iConn];
218 #endif
219                 bool isRenum = false;
220                 SMDS_MeshElement* anElement = NULL;
221                 TInt aFamNum = aPolygoneInfo->GetFamNum(iElem);
222
223 #ifndef _DEXCEPT_
224                 try{
225 #endif
226                   if(anIsElemNum){
227                     TInt anElemId = aPolygoneInfo->GetElemNum(iElem);
228                     anElement = myMesh->AddPolygonalFaceWithID(aNodeIds,anElemId);
229                     //MESSAGE("AddPolygonalFaceWithID " << anElemId);
230                   }
231                   if(!anElement){
232                     vector<const SMDS_MeshNode*> aNodes(aNbConn);
233                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
234                       aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
235                     anElement = myMesh->AddPolygonalFace(aNodes);
236                     //MESSAGE("AddPolygonalFace " << anElement->GetID());
237                     isRenum = anIsElemNum;
238                   }
239 #ifndef _DEXCEPT_
240                 }catch(const std::exception& exc){
241                   aResult = DRS_FAIL;
242                 }catch (...){
243                   aResult = DRS_FAIL;
244                 }
245 #endif
246                 if(!anElement){
247                   aResult = DRS_WARN_SKIP_ELEM;
248                 }else{
249                   if(isRenum){
250                     anIsElemNum = eFAUX;
251                     takeNumbers = false;
252                     if(aResult < DRS_WARN_RENUMBER)
253                       aResult = DRS_WARN_RENUMBER;
254                   }
255                   if ( checkFamilyID ( aFamily, aFamNum ))
256                   {
257                     // Save reference to this element from its family
258                     aFamily->AddElement(anElement);
259                     aFamily->SetType(anElement->GetType());
260                   }
261                 }
262               }
263               break;
264             }
265             case ePOLYEDRE: {
266               PPolyedreInfo aPolyedreInfo = aMed->GetPPolyedreInfo(aMeshInfo,anEntity,aGeom);
267               EBooleen anIsElemNum = takeNumbers ? aPolyedreInfo->IsElemNum() : eFAUX;
268
269               TInt aNbElem = aPolyedreInfo->GetNbElem();
270               for(TInt iElem = 0; iElem < aNbElem; iElem++){
271                 MED::TCConnSliceArr aConnSliceArr = aPolyedreInfo->GetConnSliceArr(iElem);
272                 TInt aNbFaces = aConnSliceArr.size();
273                 typedef MED::TVector<int> TQuantities;
274                 TQuantities aQuantities(aNbFaces);
275                 TInt aNbNodes = aPolyedreInfo->GetNbNodes(iElem);
276                 //MESSAGE("--- aNbNodes " << aNbNodes);
277                 TNodeIds aNodeIds(aNbNodes);
278                 for(TInt iFace = 0, iNode = 0; iFace < aNbFaces; iFace++){
279                   //MESSAGE("--- iface " << aNbFaces << " " << iFace);
280                   MED::TCConnSlice aConnSlice = aConnSliceArr[iFace];
281                   TInt aNbConn = aConnSlice.size();
282                   aQuantities[iFace] = aNbConn;
283 #ifdef _EDF_NODE_IDS_
284                   //MESSAGE(anIsNodeNum);
285                   if(anIsNodeNum)
286                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
287                       {
288                       //MESSAGE("iConn " << iConn << " aConnSlice[iConn] " << aConnSlice[iConn]);
289                       aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
290                       //MESSAGE("aNodeIds[" << iNode << "]=" << aNodeIds[iNode]);
291                       iNode++;
292                       }
293                   else
294                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
295                       {
296                       //MESSAGE("iConn " << iConn);
297                       aNodeIds[iNode++] = aConnSlice[iConn];
298                       }
299 #else
300                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
301                     {
302                     //MESSAGE("iConn " << iConn);
303                     aNodeIds[iNode++] = aConnSlice[iConn];
304                     }
305 #endif          
306                 }
307
308                 bool isRenum = false;
309                 SMDS_MeshElement* anElement = NULL;
310                 TInt aFamNum = aPolyedreInfo->GetFamNum(iElem);
311                 
312 #ifndef _DEXCEPT_
313                 try{
314 #endif
315                   if(anIsElemNum){
316                     TInt anElemId = aPolyedreInfo->GetElemNum(iElem);
317                     anElement = myMesh->AddPolyhedralVolumeWithID(aNodeIds,aQuantities,anElemId);
318                     //MESSAGE("AddPolyhedralVolumeWithID " << anElemId);
319                   }
320                   if(!anElement){
321                     vector<const SMDS_MeshNode*> aNodes(aNbNodes);
322                     for(TInt iConn = 0; iConn < aNbNodes; iConn++)
323                       aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
324                     anElement = myMesh->AddPolyhedralVolume(aNodes,aQuantities);
325                     //MESSAGE("AddPolyhedralVolume " << anElement->GetID());
326                     isRenum = anIsElemNum;
327                   }
328 #ifndef _DEXCEPT_
329                 }catch(const std::exception& exc){
330                   aResult = DRS_FAIL;
331                 }catch(...){
332                   aResult = DRS_FAIL;
333                 }
334 #endif          
335                 if(!anElement){
336                   aResult = DRS_WARN_SKIP_ELEM;
337                 }else{
338                   if(isRenum){
339                     anIsElemNum = eFAUX;
340                     takeNumbers = false;
341                     if (aResult < DRS_WARN_RENUMBER)
342                       aResult = DRS_WARN_RENUMBER;
343                   }
344                   if ( checkFamilyID ( aFamily, aFamNum )) {
345                     // Save reference to this element from its family
346                     aFamily->AddElement(anElement);
347                     aFamily->SetType(anElement->GetType());
348                   }
349                 }
350               }
351               break;
352             }
353             default: {
354               PCellInfo aCellInfo = aMed->GetPCellInfo(aMeshInfo,anEntity,aGeom);
355               EBooleen anIsElemNum = takeNumbers ? aCellInfo->IsElemNum() : eFAUX;
356               TInt aNbElems = aCellInfo->GetNbElem();
357               if(MYDEBUG) MESSAGE("Perform - anEntity = "<<anEntity<<"; anIsElemNum = "<<anIsElemNum);
358               if(MYDEBUG) MESSAGE("Perform - aGeom = "<<aGeom<<"; aNbElems = "<<aNbElems);
359
360               TInt aNbNodes = -1;
361               switch(aGeom){
362               case eSEG2:    aNbNodes = 2;  break;
363               case eSEG3:    aNbNodes = 3;  break;
364               case eTRIA3:   aNbNodes = 3;  break;
365               case eTRIA6:   aNbNodes = 6;  break;
366               case eQUAD4:   aNbNodes = 4;  break;
367               case eQUAD8:   aNbNodes = 8;  break;
368               case eTETRA4:  aNbNodes = 4;  break;
369               case eTETRA10: aNbNodes = 10; break;
370               case ePYRA5:   aNbNodes = 5;  break;
371               case ePYRA13:  aNbNodes = 13; break;
372               case ePENTA6:  aNbNodes = 6;  break;
373               case ePENTA15: aNbNodes = 15; break;
374               case eHEXA8:   aNbNodes = 8;  break;
375               case eHEXA20:  aNbNodes = 20; break;
376               case ePOINT1:  aNbNodes = 1;  break;
377               default:;
378               }
379               vector<TInt> aNodeIds(aNbNodes);
380               for(int iElem = 0; iElem < aNbElems; iElem++){
381                 bool anIsValidConnect = false;
382                 TCConnSlice aConnSlice = aCellInfo->GetConnSlice(iElem);
383 #ifndef _DEXCEPT_
384                 try{
385 #endif
386 #ifdef _EDF_NODE_IDS_
387                   if(anIsNodeNum)
388                     for(int iNode = 0; iNode < aNbNodes; iNode++)
389                       aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iNode] - 1);
390                   else
391                     for(int iNode = 0; iNode < aNbNodes; iNode++)
392                       aNodeIds[iNode] = aConnSlice[iNode];
393 #else
394                   for(int iNode = 0; iNode < aNbNodes; iNode++)
395                     aNodeIds[iNode] = aConnSlice[iNode];
396 #endif
397                   anIsValidConnect = true;
398 #ifndef _DEXCEPT_
399                 }catch(const std::exception& exc){
400                   INFOS("Following exception was caught:\n\t"<<exc.what());
401                   aResult = DRS_FAIL;
402                 }catch(...){
403                   INFOS("Unknown exception was cought !!!");
404                   aResult = DRS_FAIL;
405                 }
406 #endif          
407                 if(!anIsValidConnect)
408                   continue;
409
410                 bool isRenum = false;
411                 const SMDS_MeshElement* anElement = NULL;
412                 TInt aFamNum = aCellInfo->GetFamNum(iElem);
413 #ifndef _DEXCEPT_
414                 try{
415 #endif
416                   //MESSAGE("Try to create element # " << iElem << " with id = "
417                   //        << aCellInfo->GetElemNum(iElem));
418                   switch(aGeom) {
419                   case ePOINT1:
420                     //anElement = FindNode(myMesh,aNodeIds[0]);
421                     if(anIsElemNum)
422                       anElement = myMesh->Add0DElementWithID
423                         (aNodeIds[0], aCellInfo->GetElemNum(iElem));
424                     if (!anElement) {
425                       anElement = myMesh->Add0DElement(FindNode(myMesh,aNodeIds[0]));
426                       isRenum = anIsElemNum;
427                     }
428                     break;
429                   case eSEG2:
430                     if(anIsElemNum)
431                       anElement = myMesh->AddEdgeWithID(aNodeIds[0],
432                                                         aNodeIds[1],
433                                                         aCellInfo->GetElemNum(iElem));
434                     if (!anElement) {
435                       anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
436                                                   FindNode(myMesh,aNodeIds[1]));
437                       isRenum = anIsElemNum;
438                     }
439                     break;
440                   case eSEG3:
441                     if(anIsElemNum)
442                       anElement = myMesh->AddEdgeWithID(aNodeIds[0],
443                                                         aNodeIds[1],
444                                                         aNodeIds[2],
445                                                         aCellInfo->GetElemNum(iElem));
446                     if (!anElement) {
447                       anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
448                                                   FindNode(myMesh,aNodeIds[1]),
449                                                   FindNode(myMesh,aNodeIds[2]));
450                       isRenum = anIsElemNum;
451                     }
452                     break;
453                   case eTRIA3:
454                     aNbNodes = 3;
455                     if(anIsElemNum)
456                       anElement = myMesh->AddFaceWithID(aNodeIds[0],
457                                                         aNodeIds[1],
458                                                         aNodeIds[2],
459                                                         aCellInfo->GetElemNum(iElem));
460                     if (!anElement) {
461                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
462                                                   FindNode(myMesh,aNodeIds[1]),
463                                                   FindNode(myMesh,aNodeIds[2]));
464                       isRenum = anIsElemNum;
465                     }
466                     break;
467                   case eTRIA6:
468                     aNbNodes = 6;
469                     if(anIsElemNum)
470                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
471                                                         aNodeIds[2], aNodeIds[3],
472                                                         aNodeIds[4], aNodeIds[5],
473                                                         aCellInfo->GetElemNum(iElem));
474                     if (!anElement) {
475                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
476                                                   FindNode(myMesh,aNodeIds[1]),
477                                                   FindNode(myMesh,aNodeIds[2]),
478                                                   FindNode(myMesh,aNodeIds[3]),
479                                                   FindNode(myMesh,aNodeIds[4]),
480                                                   FindNode(myMesh,aNodeIds[5]));
481                       isRenum = anIsElemNum;
482                     }
483                     break;
484                   case eQUAD4:
485                     aNbNodes = 4;
486                     if(anIsElemNum)
487                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
488                                                         aNodeIds[2], aNodeIds[3],
489                                                         aCellInfo->GetElemNum(iElem));
490                     if (!anElement) {
491                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
492                                                   FindNode(myMesh,aNodeIds[1]),
493                                                   FindNode(myMesh,aNodeIds[2]),
494                                                   FindNode(myMesh,aNodeIds[3]));
495                       isRenum = anIsElemNum;
496                     }
497                     break;
498                   case eQUAD8:
499                     aNbNodes = 8;
500                     if(anIsElemNum)
501                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
502                                                         aNodeIds[2], aNodeIds[3],
503                                                         aNodeIds[4], aNodeIds[5],
504                                                         aNodeIds[6], aNodeIds[7],
505                                                         aCellInfo->GetElemNum(iElem));
506                     if (!anElement) {
507                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
508                                                   FindNode(myMesh,aNodeIds[1]),
509                                                   FindNode(myMesh,aNodeIds[2]),
510                                                   FindNode(myMesh,aNodeIds[3]),
511                                                   FindNode(myMesh,aNodeIds[4]),
512                                                   FindNode(myMesh,aNodeIds[5]),
513                                                   FindNode(myMesh,aNodeIds[6]),
514                                                   FindNode(myMesh,aNodeIds[7]));
515                       isRenum = anIsElemNum;
516                     }
517                     break;
518                   case eTETRA4:
519                     aNbNodes = 4;
520                     if(anIsElemNum)
521                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
522                                                           aNodeIds[2], aNodeIds[3],
523                                                           aCellInfo->GetElemNum(iElem));
524                     if (!anElement) {
525                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
526                                                     FindNode(myMesh,aNodeIds[1]),
527                                                     FindNode(myMesh,aNodeIds[2]),
528                                                     FindNode(myMesh,aNodeIds[3]));
529                       isRenum = anIsElemNum;
530                     }
531                     break;
532                   case eTETRA10:
533                     aNbNodes = 10;
534                     if(anIsElemNum)
535                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
536                                                           aNodeIds[2], aNodeIds[3],
537                                                           aNodeIds[4], aNodeIds[5],
538                                                           aNodeIds[6], aNodeIds[7],
539                                                           aNodeIds[8], aNodeIds[9],
540                                                           aCellInfo->GetElemNum(iElem));
541                     if (!anElement) {
542                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
543                                                     FindNode(myMesh,aNodeIds[1]),
544                                                     FindNode(myMesh,aNodeIds[2]),
545                                                     FindNode(myMesh,aNodeIds[3]),
546                                                     FindNode(myMesh,aNodeIds[4]),
547                                                     FindNode(myMesh,aNodeIds[5]),
548                                                     FindNode(myMesh,aNodeIds[6]),
549                                                     FindNode(myMesh,aNodeIds[7]),
550                                                     FindNode(myMesh,aNodeIds[8]),
551                                                     FindNode(myMesh,aNodeIds[9]));
552                       isRenum = anIsElemNum;
553                     }
554                     break;
555                   case ePYRA5:
556                     aNbNodes = 5;
557                     // There is some differnce between SMDS and MED
558                     if(anIsElemNum)
559                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
560                                                           aNodeIds[2], aNodeIds[3],
561                                                           aNodeIds[4],
562                                                           aCellInfo->GetElemNum(iElem));
563                     if (!anElement) {
564                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
565                                                     FindNode(myMesh,aNodeIds[1]),
566                                                     FindNode(myMesh,aNodeIds[2]),
567                                                     FindNode(myMesh,aNodeIds[3]),
568                                                     FindNode(myMesh,aNodeIds[4]));
569                       isRenum = anIsElemNum;
570                     }
571                     break;
572                   case ePYRA13:
573                     aNbNodes = 13;
574                     // There is some difference between SMDS and MED
575                     if(anIsElemNum)
576                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
577                                                           aNodeIds[2], aNodeIds[3],
578                                                           aNodeIds[4], aNodeIds[5],
579                                                           aNodeIds[6], aNodeIds[7],
580                                                           aNodeIds[8], aNodeIds[9],
581                                                           aNodeIds[10], aNodeIds[11],
582                                                           aNodeIds[12],
583                                                           aCellInfo->GetElemNum(iElem));
584                     if (!anElement) {
585                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
586                                                     FindNode(myMesh,aNodeIds[1]),
587                                                     FindNode(myMesh,aNodeIds[2]),
588                                                     FindNode(myMesh,aNodeIds[3]),
589                                                     FindNode(myMesh,aNodeIds[4]),
590                                                     FindNode(myMesh,aNodeIds[5]),
591                                                     FindNode(myMesh,aNodeIds[6]),
592                                                     FindNode(myMesh,aNodeIds[7]),
593                                                     FindNode(myMesh,aNodeIds[8]),
594                                                     FindNode(myMesh,aNodeIds[9]),
595                                                     FindNode(myMesh,aNodeIds[10]),
596                                                     FindNode(myMesh,aNodeIds[11]),
597                                                     FindNode(myMesh,aNodeIds[12]));
598                       isRenum = anIsElemNum;
599                     }
600                     break;
601                   case ePENTA6:
602                     aNbNodes = 6;
603                     if(anIsElemNum)
604                       anElement = myMesh->AddVolumeWithID(aNodeIds[0],
605                                                           aNodeIds[1],
606                                                           aNodeIds[2],
607                                                           aNodeIds[3],
608                                                           aNodeIds[4],
609                                                           aNodeIds[5],
610                                                           aCellInfo->GetElemNum(iElem));
611                     if (!anElement) {
612                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
613                                                     FindNode(myMesh,aNodeIds[1]),
614                                                     FindNode(myMesh,aNodeIds[2]),
615                                                     FindNode(myMesh,aNodeIds[3]),
616                                                     FindNode(myMesh,aNodeIds[4]),
617                                                     FindNode(myMesh,aNodeIds[5]));
618                       isRenum = anIsElemNum;
619                     }
620                     break;
621                   case ePENTA15:
622                     aNbNodes = 15;
623                     if(anIsElemNum)
624                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
625                                                           aNodeIds[2], aNodeIds[3],
626                                                           aNodeIds[4], aNodeIds[5],
627                                                           aNodeIds[6], aNodeIds[7],
628                                                           aNodeIds[8], aNodeIds[9],
629                                                           aNodeIds[10], aNodeIds[11],
630                                                           aNodeIds[12], aNodeIds[13],
631                                                           aNodeIds[14],
632                                                           aCellInfo->GetElemNum(iElem));
633                     if (!anElement) {
634                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
635                                                     FindNode(myMesh,aNodeIds[1]),
636                                                     FindNode(myMesh,aNodeIds[2]),
637                                                     FindNode(myMesh,aNodeIds[3]),
638                                                   FindNode(myMesh,aNodeIds[4]),
639                                                     FindNode(myMesh,aNodeIds[5]),
640                                                     FindNode(myMesh,aNodeIds[6]),
641                                                     FindNode(myMesh,aNodeIds[7]),
642                                                     FindNode(myMesh,aNodeIds[8]),
643                                                     FindNode(myMesh,aNodeIds[9]),
644                                                     FindNode(myMesh,aNodeIds[10]),
645                                                     FindNode(myMesh,aNodeIds[11]),
646                                                     FindNode(myMesh,aNodeIds[12]),
647                                                     FindNode(myMesh,aNodeIds[13]),
648                                                     FindNode(myMesh,aNodeIds[14]));
649                       isRenum = anIsElemNum;
650                     }
651                     break;
652                   case eHEXA8:
653                     aNbNodes = 8;
654                     if(anIsElemNum)
655                       anElement = myMesh->AddVolumeWithID(aNodeIds[0],
656                                                           aNodeIds[1],
657                                                           aNodeIds[2],
658                                                           aNodeIds[3],
659                                                           aNodeIds[4],
660                                                           aNodeIds[5],
661                                                           aNodeIds[6],
662                                                           aNodeIds[7],
663                                                           aCellInfo->GetElemNum(iElem));
664                     if (!anElement) {
665                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
666                                                     FindNode(myMesh,aNodeIds[1]),
667                                                     FindNode(myMesh,aNodeIds[2]),
668                                                     FindNode(myMesh,aNodeIds[3]),
669                                                     FindNode(myMesh,aNodeIds[4]),
670                                                     FindNode(myMesh,aNodeIds[5]),
671                                                     FindNode(myMesh,aNodeIds[6]),
672                                                     FindNode(myMesh,aNodeIds[7]));
673                       isRenum = anIsElemNum;
674                     }
675                     break;
676                   case eHEXA20:
677                     aNbNodes = 20;
678                     if(anIsElemNum)
679                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
680                                                           aNodeIds[2], aNodeIds[3],
681                                                           aNodeIds[4], aNodeIds[5],
682                                                           aNodeIds[6], aNodeIds[7],
683                                                           aNodeIds[8], aNodeIds[9],
684                                                           aNodeIds[10], aNodeIds[11],
685                                                           aNodeIds[12], aNodeIds[13],
686                                                           aNodeIds[14], aNodeIds[15],
687                                                           aNodeIds[16], aNodeIds[17],
688                                                           aNodeIds[18], aNodeIds[19],
689                                                           aCellInfo->GetElemNum(iElem));
690                     if (!anElement) {
691                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
692                                                     FindNode(myMesh,aNodeIds[1]),
693                                                     FindNode(myMesh,aNodeIds[2]),
694                                                     FindNode(myMesh,aNodeIds[3]),
695                                                     FindNode(myMesh,aNodeIds[4]),
696                                                     FindNode(myMesh,aNodeIds[5]),
697                                                     FindNode(myMesh,aNodeIds[6]),
698                                                     FindNode(myMesh,aNodeIds[7]),
699                                                     FindNode(myMesh,aNodeIds[8]),
700                                                     FindNode(myMesh,aNodeIds[9]),
701                                                     FindNode(myMesh,aNodeIds[10]),
702                                                     FindNode(myMesh,aNodeIds[11]),
703                                                     FindNode(myMesh,aNodeIds[12]),
704                                                     FindNode(myMesh,aNodeIds[13]),
705                                                     FindNode(myMesh,aNodeIds[14]),
706                                                     FindNode(myMesh,aNodeIds[15]),
707                                                     FindNode(myMesh,aNodeIds[16]),
708                                                     FindNode(myMesh,aNodeIds[17]),
709                                                     FindNode(myMesh,aNodeIds[18]),
710                                                     FindNode(myMesh,aNodeIds[19]));
711                       isRenum = anIsElemNum;
712                     }
713                     break;
714                   }
715 //                  if (anIsElemNum) {
716 //                    MESSAGE("add element with id " << aCellInfo->GetElemNum(iElem));
717 //                  }
718 //                  else {
719 //                    MESSAGE("add element "<< anElement->GetID());
720 //                  }
721 #ifndef _DEXCEPT_
722                 }catch(const std::exception& exc){
723                   INFOS("The following exception was caught:\n\t"<<exc.what());
724                   aResult = DRS_FAIL;
725                 }catch(...){
726                   INFOS("Unknown exception was caught !!!");
727                   aResult = DRS_FAIL;
728                 }
729 #endif          
730                 if (!anElement) {
731                   aResult = DRS_WARN_SKIP_ELEM;
732                 }
733                 else {
734                   if (isRenum) {
735                     anIsElemNum = eFAUX;
736                     takeNumbers = false;
737                     if (aResult < DRS_WARN_RENUMBER)
738                       aResult = DRS_WARN_RENUMBER;
739                   }
740                   if ( checkFamilyID ( aFamily, aFamNum )) {
741                     // Save reference to this element from its family
742                     myFamilies[aFamNum]->AddElement(anElement);
743                     myFamilies[aFamNum]->SetType(anElement->GetType());
744                   }
745                 }
746               }
747             }}
748           }
749         }
750       }
751     }
752 #ifndef _DEXCEPT_
753   }catch(const std::exception& exc){
754     INFOS("The following exception was caught:\n\t"<<exc.what());
755     aResult = DRS_FAIL;
756   }catch(...){
757     INFOS("Unknown exception was caught !!!");
758     aResult = DRS_FAIL;
759   }
760 #endif
761   if (myMesh)
762     myMesh->compactMesh();
763   if(MYDEBUG) MESSAGE("Perform - aResult status = "<<aResult);
764   return aResult;
765 }
766
767 list<string> DriverMED_R_SMESHDS_Mesh::GetMeshNames(Status& theStatus)
768 {
769   list<string> aMeshNames;
770
771   try {
772     if(MYDEBUG) MESSAGE("GetMeshNames - myFile : " << myFile);
773     theStatus = DRS_OK;
774     PWrapper aMed = CrWrapper(myFile);
775
776     if (TInt aNbMeshes = aMed->GetNbMeshes()) {
777       for (int iMesh = 0; iMesh < aNbMeshes; iMesh++) {
778         // Reading the MED mesh
779         //---------------------
780         PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
781         aMeshNames.push_back(aMeshInfo->GetName());
782       }
783     }
784   }catch(const std::exception& exc){
785     INFOS("Following exception was caught:\n\t"<<exc.what());
786     theStatus = DRS_FAIL;
787   }catch(...){
788     INFOS("Unknown exception was caught !!!");
789     theStatus = DRS_FAIL;
790   }
791
792   return aMeshNames;
793 }
794
795 list<TNameAndType> DriverMED_R_SMESHDS_Mesh::GetGroupNamesAndTypes()
796 {
797   list<TNameAndType> aResult;
798   set<TNameAndType> aResGroupNames;
799
800   map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
801   for (; aFamsIter != myFamilies.end(); aFamsIter++)
802   {
803     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
804     const MED::TStringSet& aGroupNames = aFamily->GetGroupNames();
805     set<string>::const_iterator aGrNamesIter = aGroupNames.begin();
806     for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
807     {
808       const set< SMDSAbs_ElementType >& types = aFamily->GetTypes();
809       set< SMDSAbs_ElementType >::const_iterator type = types.begin();
810       for ( ; type != types.end(); ++type )
811       {
812         TNameAndType aNameAndType = make_pair( *aGrNamesIter, *type );
813         if ( aResGroupNames.insert( aNameAndType ).second ) {
814           aResult.push_back( aNameAndType );
815         }
816       }
817     }
818   }
819
820   return aResult;
821 }
822
823 void DriverMED_R_SMESHDS_Mesh::GetGroup(SMESHDS_Group* theGroup)
824 {
825   string aGroupName (theGroup->GetStoreName());
826   if(MYDEBUG) MESSAGE("Get Group " << aGroupName);
827
828   map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
829   for (; aFamsIter != myFamilies.end(); aFamsIter++)
830   {
831     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
832     if (aFamily->GetTypes().count( theGroup->GetType() ) && aFamily->MemberOf(aGroupName))
833     {
834       const set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
835       set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElements.begin();
836       for (; anElemsIter != anElements.end(); anElemsIter++)
837       {
838         const SMDS_MeshElement * element = *anElemsIter;
839         if ( element->GetType() == theGroup->GetType() ) // Issue 0020576
840           theGroup->SMDSGroup().Add(element);
841       }
842       int aGroupAttrVal = aFamily->GetGroupAttributVal();
843       if( aGroupAttrVal != 0)
844         theGroup->SetColorGroup(aGroupAttrVal);
845 //       if ( element ) -- Issue 0020576
846 //         theGroup->SetType( theGroup->SMDSGroup().GetType() );
847     }
848   }
849 }
850
851 void DriverMED_R_SMESHDS_Mesh::GetSubMesh (SMESHDS_SubMesh* theSubMesh,
852                                            const int theId)
853 {
854   char submeshGrpName[ 30 ];
855   sprintf( submeshGrpName, "SubMesh %d", theId );
856   string aName (submeshGrpName);
857   map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
858   for (; aFamsIter != myFamilies.end(); aFamsIter++)
859   {
860     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
861     if (aFamily->MemberOf(aName))
862     {
863       const set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
864       set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElements.begin();
865       if (aFamily->GetType() == SMDSAbs_Node)
866       {
867         for (; anElemsIter != anElements.end(); anElemsIter++)
868         {
869           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>(*anElemsIter);
870           theSubMesh->AddNode(node);
871         }
872       }
873       else
874       {
875         for (; anElemsIter != anElements.end(); anElemsIter++)
876         {
877           theSubMesh->AddElement(*anElemsIter);
878         }
879       }
880     }
881   }
882 }
883
884 void DriverMED_R_SMESHDS_Mesh::CreateAllSubMeshes ()
885 {
886   map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
887   for (; aFamsIter != myFamilies.end(); aFamsIter++)
888   {
889     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
890     MED::TStringSet aGroupNames = aFamily->GetGroupNames();
891     set<string>::iterator aGrNamesIter = aGroupNames.begin();
892     for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
893     {
894       string aName = *aGrNamesIter;
895       // Check, if this is a Group or SubMesh name
896       if (aName.substr(0, 7) == string("SubMesh"))
897       {
898         int Id = atoi(string(aName).substr(7).c_str());
899         set<const SMDS_MeshElement *> anElements = aFamily->GetElements();
900         set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
901         if (aFamily->GetType() == SMDSAbs_Node)
902         {
903           for (; anElemsIter != anElements.end(); anElemsIter++)
904           {
905             SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>
906               ( static_cast<const SMDS_MeshNode*>( *anElemsIter ));
907             // find out a shape type
908             TopoDS_Shape aShape = myMesh->IndexToShape( Id );
909             int aShapeType = ( aShape.IsNull() ? -1 : aShape.ShapeType() );
910             switch ( aShapeType ) {
911             case TopAbs_FACE:
912               myMesh->SetNodeOnFace(node, Id); break;
913             case TopAbs_EDGE:
914               myMesh->SetNodeOnEdge(node, Id); break;
915             case TopAbs_VERTEX:
916               myMesh->SetNodeOnVertex(node, Id); break;
917             default:
918               myMesh->SetNodeInVolume(node, Id);
919             }
920           }
921         }
922         else
923         {
924           for (; anElemsIter != anElements.end(); anElemsIter++)
925           {
926             myMesh->SetMeshElementOnShape(*anElemsIter, Id);
927           }
928         }
929       }
930     }
931   }
932 }
933 /*!
934  * \brief Ensure aFamily to have required ID
935  * \param aFamily - a family to check and update
936  * \param anID - an ID aFamily should have
937  * \retval bool  - true if successful
938  */
939 bool DriverMED_R_SMESHDS_Mesh::checkFamilyID(DriverMED_FamilyPtr & aFamily, int anID) const
940 {
941   if ( !aFamily || aFamily->GetId() != anID ) {
942     map<int, DriverMED_FamilyPtr>::const_iterator i_fam = myFamilies.find(anID);
943     if ( i_fam == myFamilies.end() )
944       return false;
945     aFamily = i_fam->second;
946   }
947   return ( aFamily->GetId() == anID );
948 }
949
950
951 /*! \brief Reading the structured mesh and convert to non structured (by filling of smesh structure for non structured mesh)
952  * \param theWrapper  - PWrapper const pointer
953  * \param theMeshInfo - PMeshInfo const pointer
954  * \return TRUE, if successfully. Else FALSE
955  */
956 bool DriverMED_R_SMESHDS_Mesh::buildMeshGrille(const MED::PWrapper& theWrapper,
957                                                const MED::PMeshInfo& theMeshInfo)
958 {
959   bool res = true;
960
961   MED::PGrilleInfo aGrilleInfo = theWrapper->GetPGrilleInfo(theMeshInfo);
962   MED::TInt aNbNodes = aGrilleInfo->GetNbNodes();
963   MED::TInt aNbCells = aGrilleInfo->GetNbCells();
964   MED::TInt aMeshDim = theMeshInfo->GetDim();
965   DriverMED_FamilyPtr aFamily;
966   for(MED::TInt iNode=0;iNode < aNbNodes; iNode++){
967     double aCoords[3] = {0.0, 0.0, 0.0};
968     const SMDS_MeshNode* aNode;
969     MED::TNodeCoord aMEDNodeCoord = aGrilleInfo->GetCoord(iNode);
970     for(MED::TInt iDim=0;iDim<aMeshDim;iDim++)
971       aCoords[(int)iDim] = aMEDNodeCoord[(int)iDim];
972     aNode = myMesh->AddNodeWithID(aCoords[0],aCoords[1],aCoords[2],iNode+1);
973     if (!aNode) {
974       EXCEPTION(runtime_error,"buildMeshGrille Error. Node not created! "<<(int)iNode);
975     }
976
977     if((aGrilleInfo->myFamNumNode).size() > 0){
978       TInt aFamNum = aGrilleInfo->GetFamNumNode(iNode);
979       if ( checkFamilyID ( aFamily, aFamNum ))
980         {
981           aFamily->AddElement(aNode);
982           aFamily->SetType(SMDSAbs_Node);
983         }
984     }
985     
986   }
987
988   SMDS_MeshElement* anElement = NULL;
989   MED::TIntVector aNodeIds;
990   for(MED::TInt iCell=0;iCell < aNbCells; iCell++){
991     aNodeIds = aGrilleInfo->GetConn(iCell);
992     switch(aGrilleInfo->GetGeom()){
993     case MED::eSEG2:
994       if(aNodeIds.size() != 2){
995         res = false;
996         EXCEPTION(runtime_error,"buildMeshGrille Error. Incorrect size of ids 2!="<<aNodeIds.size());
997       }
998       anElement = myMesh->AddEdgeWithID(aNodeIds[0]+1,
999                                         aNodeIds[1]+1,
1000                                         iCell+1);
1001       break;
1002     case MED::eQUAD4:
1003       if(aNodeIds.size() != 4){
1004         res = false;
1005         EXCEPTION(runtime_error,"buildMeshGrille Error. Incorrect size of ids 4!="<<aNodeIds.size());
1006       }
1007       anElement = myMesh->AddFaceWithID(aNodeIds[0]+1,
1008                                         aNodeIds[2]+1,
1009                                         aNodeIds[3]+1,
1010                                         aNodeIds[1]+1,
1011                                         iCell+1);
1012       break;
1013     case MED::eHEXA8:
1014       if(aNodeIds.size() != 8){
1015         res = false;
1016         EXCEPTION(runtime_error,"buildMeshGrille Error. Incorrect size of ids 8!="<<aNodeIds.size());
1017       }
1018       anElement = myMesh->AddVolumeWithID(aNodeIds[0]+1,
1019                                           aNodeIds[2]+1,
1020                                           aNodeIds[3]+1,
1021                                           aNodeIds[1]+1,
1022                                           aNodeIds[4]+1,
1023                                           aNodeIds[6]+1,
1024                                           aNodeIds[7]+1,
1025                                           aNodeIds[5]+1,
1026                                           iCell+1);
1027       break;
1028     default:
1029       break;
1030     }
1031     if (!anElement) {
1032       EXCEPTION(runtime_error,"buildMeshGrille Error. Element not created! "<<iCell);
1033     }
1034     if((aGrilleInfo->myFamNum).size() > 0){
1035       TInt aFamNum = aGrilleInfo->GetFamNum(iCell);
1036       if ( checkFamilyID ( aFamily, aFamNum )){
1037         aFamily->AddElement(anElement);
1038         aFamily->SetType(anElement->GetType());
1039       }
1040     }
1041   }
1042
1043   return res;
1044 }