Salome HOME
99b82120962319a16e724e1fe88b576abf3c8648
[modules/smesh.git] / src / DriverGMF / DriverGMF_Read.cxx
1 // Copyright (C) 2007-2012  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, Read 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 // File      : DriverGMF_Read.cxx
23 // Created   : Mon Sep 17 17:03:02 2012
24 // Author    : Edward AGAPOV (eap)
25
26 #include "DriverGMF_Read.hxx"
27 #include "DriverGMF.hxx"
28
29 #include "SMESHDS_Group.hxx"
30 #include "SMESHDS_Mesh.hxx"
31 #include "SMESH_Comment.hxx"
32
33 #include <Basics_Utils.hxx>
34
35 extern "C"
36 {
37 #include "libmesh5.h"
38 }
39
40 #include <stdarg.h>
41
42 // --------------------------------------------------------------------------------
43 DriverGMF_Read::DriverGMF_Read():
44   Driver_SMESHDS_Mesh(),
45   _makeRequiredGroups( true )
46 {
47 }
48 // --------------------------------------------------------------------------------
49 DriverGMF_Read::~DriverGMF_Read()
50 {
51 }
52
53 //================================================================================
54 /*!
55  * \brief Read a GMF file
56  */
57 //================================================================================
58
59 Driver_Mesh::Status DriverGMF_Read::Perform()
60 {
61   Kernel_Utils::Localizer loc;
62
63   Status status = DRS_OK;
64
65   int dim, version;
66
67   // open the file
68   int meshID = GmfOpenMesh( myFile.c_str(), GmfRead, &version, &dim );
69   if ( !meshID )
70   {
71     if ( DriverGMF::isExtensionCorrect( myFile ))
72       return addMessage( SMESH_Comment("Can't open for reading ") << myFile, /*fatal=*/true );
73     else
74       return addMessage( SMESH_Comment("Not '.mesh' or '.meshb' extension of file ") << myFile, /*fatal=*/true );
75   }
76   DriverGMF::MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction
77
78   // Read nodes
79
80   int nbNodes = GmfStatKwd(meshID, GmfVertices);
81   if ( nbNodes < 1 )
82     return addMessage( "No nodes in the mesh", /*fatal=*/true );
83
84   GmfGotoKwd(meshID, GmfVertices);
85
86   int ref;
87
88   const int nodeIDShift = myMesh->GetMeshInfo().NbNodes();
89   if ( version != GmfFloat )
90   {
91     double x, y, z;
92     for ( int i = 1; i <= nbNodes; ++i )
93     {
94       GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref);
95       myMesh->AddNodeWithID( x,y,z, nodeIDShift + i);
96     }
97   }
98   else
99   {
100     float x, y, z;
101     for ( int i = 1; i <= nbNodes; ++i )
102     {
103       GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref);
104       myMesh->AddNodeWithID( x,y,z, nodeIDShift + i);
105     }
106   }
107
108   // Read elements
109
110   int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
111
112   /* Read extra vertices for quadratic edges */
113   std::vector<int> quadNodesAtEdges;
114   int nbQuadEdges = 0;
115   if ( (nbQuadEdges = GmfStatKwd(meshID, GmfExtraVerticesAtEdges)) )
116   {
117     quadNodesAtEdges.reserve( nbQuadEdges );
118     GmfGotoKwd(meshID, GmfExtraVerticesAtEdges);
119     for ( int i = 1; i <= nbQuadEdges; ++i )
120     {
121       GmfGetLin(meshID, GmfExtraVerticesAtEdges, &iN[0], &iN[1], &iN[2]);
122       quadNodesAtEdges.push_back(iN[2]);
123     }
124   }
125
126   /* Read edges */
127   const int edgeIDShift = myMesh->GetMeshInfo().NbElements();
128   if ( int nbEdges = GmfStatKwd(meshID, GmfEdges))
129   {
130     const bool readQuadNodes = ( nbQuadEdges == nbEdges );
131     GmfGotoKwd(meshID, GmfEdges);
132     for ( int i = 1; i <= nbEdges; ++i )
133     {
134       GmfGetLin(meshID, GmfEdges, &iN[0], &iN[1], &ref);
135       if ( readQuadNodes )
136       {
137         const int midN = quadNodesAtEdges[i-1];
138         if ( !myMesh->AddEdgeWithID( iN[0], iN[1], midN, edgeIDShift + i ))
139           status = storeBadNodeIds( "GmfEdges + GmfExtraVerticesAtEdges",i, 3, iN[0],iN[1],midN);
140       }
141       else
142       {
143         if ( !myMesh->AddEdgeWithID( iN[0], iN[1], edgeIDShift + i ))
144           status = storeBadNodeIds( "GmfEdges",i, 2, iN[0], iN[1] );
145       }
146     }
147   }
148
149   /* Read extra vertices for quadratic triangles */
150   std::vector< std::vector<int> > quadNodes;
151   int nbQuadTria = 0;
152   if ( (nbQuadTria = GmfStatKwd(meshID, GmfExtraVerticesAtTriangles)) )
153   {
154     GmfGotoKwd(meshID, GmfExtraVerticesAtTriangles);
155     quadNodes.reserve( nbQuadTria );
156     std::vector<int> nodes(4);
157     for ( int i = 1; i <= nbQuadTria; ++i )
158     {
159       GmfGetLin(meshID, GmfExtraVerticesAtTriangles,
160                 &iN[0], &iN[1], &iN[2], &iN[3], &iN[4],
161                 &iN[5]); // iN[5] - preview TRIA7
162       nodes.clear();
163       nodes.push_back(iN[2]);
164       nodes.push_back(iN[3]);
165       nodes.push_back(iN[4]);
166       nodes.push_back(iN[5]);
167       nodes.resize( iN[1] );
168
169       quadNodes.push_back(nodes);
170     }
171   }
172
173   /* Read triangles */
174   const int triaIDShift = myMesh->GetMeshInfo().NbElements();
175   if ( int nbTria = GmfStatKwd(meshID, GmfTriangles))
176   {
177     const bool readQuadNodes = (nbQuadTria == nbTria);
178     GmfGotoKwd(meshID, GmfTriangles);
179     for ( int i = 1; i <= nbTria; ++i )
180     {
181       GmfGetLin(meshID, GmfTriangles, &iN[0], &iN[1], &iN[2], &ref);
182       if ( readQuadNodes )
183       {
184         const std::vector<int>& midN = quadNodes[ i-1 ];
185         if ( !myMesh->AddFaceWithID( iN[0],iN[1],iN[2], midN[0],midN[1],midN[2],  triaIDShift + i ))
186           status = storeBadNodeIds( "GmfTriangles + GmfExtraVerticesAtTriangles",i, 6, 
187                                     iN[0],iN[1],iN[2], midN[0],midN[1],midN[2] );
188       }
189       else
190       {
191         if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], triaIDShift + i ))
192           status = storeBadNodeIds( "GmfTriangles",i, 3, iN[0], iN[1], iN[2] );
193       }
194     }
195   }
196
197   /* Read extra vertices for quadratic quadrangles */
198   std::vector< std::vector<int> > quadNodesAtQuadrilaterals;
199   int nbQuadQuad = 0;
200   if ( (nbQuadQuad = GmfStatKwd(meshID, GmfExtraVerticesAtQuadrilaterals)) )
201   {
202     GmfGotoKwd(meshID, GmfExtraVerticesAtQuadrilaterals);
203     quadNodesAtQuadrilaterals.reserve( nbQuadQuad );
204     std::vector<int> nodes( 5 );
205     for ( int i = 1; i <= nbQuadQuad; ++i )
206     {
207       GmfGetLin(meshID, GmfExtraVerticesAtQuadrilaterals,
208                 &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6]);
209       nodes.clear();
210       nodes.push_back(iN[2]);
211       nodes.push_back(iN[3]);
212       nodes.push_back(iN[4]);
213       nodes.push_back(iN[5]);
214       nodes.push_back(iN[6]);
215       nodes.resize( iN[1] );
216
217       quadNodesAtQuadrilaterals.push_back(nodes);
218     }
219   }
220
221  /* Read quadrangles */
222   const int quadIDShift = myMesh->GetMeshInfo().NbElements();
223   if ( int nbQuad = GmfStatKwd(meshID, GmfQuadrilaterals))
224   {
225     const bool readQuadNodes = (nbQuadQuad == nbQuad);
226     GmfGotoKwd(meshID, GmfQuadrilaterals);
227     for ( int i = 1; i <= nbQuad; ++i )
228     {
229       GmfGetLin(meshID, GmfQuadrilaterals, &iN[0], &iN[1], &iN[2], &iN[3], &ref);
230       if ( readQuadNodes )
231       {
232         const std::vector<int>& midN = quadNodesAtQuadrilaterals[ i-1 ];
233         if ( midN.size() == 4 )
234         {
235           if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3],
236                                        midN[0], midN[1], midN[2], midN[3],
237                                        quadIDShift + i ))
238             status = storeBadNodeIds( "GmfQuadrilaterals + GmfExtraVerticesAtQuadrilaterals",i, 8,
239                                       iN[0], iN[1],iN[2], iN[3],
240                                       midN[0], midN[1], midN[2], midN[3]);
241         }
242         else
243         {
244           if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3],
245                                        midN[0], midN[1], midN[2], midN[3], midN[4],
246                                        quadIDShift + i ))
247             status = storeBadNodeIds( "GmfQuadrilaterals + GmfExtraVerticesAtQuadrilaterals",i, 9,
248                                       iN[0], iN[1],iN[2], iN[3],
249                                       midN[0], midN[1], midN[2], midN[3], midN[4]);
250         }
251       }
252       else
253       {
254         if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3], quadIDShift + i ))
255           status = storeBadNodeIds( "GmfQuadrilaterals",i, 4, iN[0], iN[1],iN[2], iN[3] );
256       }
257     }
258   }
259  
260   /* Read terahedra */
261   const int tetIDShift = myMesh->GetMeshInfo().NbElements();
262   if ( int nbTet = GmfStatKwd(meshID, GmfTetrahedra))
263   {
264     GmfGotoKwd(meshID, GmfTetrahedra);
265     for ( int i = 1; i <= nbTet; ++i )
266     {
267       GmfGetLin(meshID, GmfTetrahedra, &iN[0], &iN[1], &iN[2], &iN[3], &ref);
268       if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], tetIDShift + i ))
269         status = storeBadNodeIds( "GmfTetrahedra",i, 4, iN[0], iN[1],iN[2], iN[3] );
270     }
271   }
272   /* Read quadratic terahedra */
273   const int tet2IDShift = myMesh->GetMeshInfo().NbElements();
274   if ( int nbTet = GmfStatKwd(meshID, GmfTetrahedraP2))
275   {
276     GmfGotoKwd(meshID, GmfTetrahedraP2);
277     for ( int i = 1; i <= nbTet; ++i )
278     {
279       GmfGetLin(meshID, GmfTetrahedraP2, &iN[0], &iN[1], &iN[2],
280                 &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &iN[8], &iN[9], &ref);
281       if ( !myMesh->AddVolumeWithID( iN[0],iN[2],iN[1],iN[3],
282                                      iN[6],iN[5],iN[4],
283                                      iN[7],iN[9],iN[8], tet2IDShift + i ))
284         status = storeBadNodeIds( "GmfTetrahedraP2",i, 10, iN[0],iN[1],iN[2],iN[3],
285                                   iN[4],iN[5],iN[6],iN[7],iN[8],iN[9] );
286     }
287   }
288   /* Read pyramids */
289   const int pyrIDShift = myMesh->GetMeshInfo().NbElements();
290   if ( int nbPyr = GmfStatKwd(meshID, GmfPyramids))
291   {
292     GmfGotoKwd(meshID, GmfPyramids);
293     for ( int i = 1; i <= nbPyr; ++i )
294     {
295       GmfGetLin(meshID, GmfPyramids, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &ref);
296       if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[4], pyrIDShift + i ))
297         status = storeBadNodeIds( "GmfPyramids",i, 5, iN[0], iN[1],iN[2], iN[3], iN[4] );
298     }
299   }
300   /* Read hexahedra */
301   const int hexIDShift = myMesh->GetMeshInfo().NbElements();
302   if ( int nbHex = GmfStatKwd(meshID, GmfHexahedra))
303   {
304     GmfGotoKwd(meshID, GmfHexahedra);
305     for ( int i = 1; i <= nbHex; ++i )
306     {
307       GmfGetLin(meshID, GmfHexahedra,
308                 &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7], &ref);
309       if ( !myMesh->AddVolumeWithID( iN[0], iN[3], iN[2], iN[1], iN[4], iN[7], iN[6], iN[5],
310                                      hexIDShift + i))
311         status = storeBadNodeIds( "GmfHexahedra",i,
312                                   8, iN[0], iN[1],iN[2], iN[3], iN[4], iN[7], iN[6], iN[5] );
313     }
314   }
315   /* Read tri-quadratic hexahedra */
316   const int hex2IDShift = myMesh->GetMeshInfo().NbElements();
317   if ( int nbHex = GmfStatKwd(meshID, GmfHexahedraQ2))
318   {
319     GmfGotoKwd(meshID, GmfHexahedraQ2);
320     for ( int i = 1; i <= nbHex; ++i )
321     {
322       GmfGetLin(meshID, GmfHexahedraQ2, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5],
323                 &iN[6], &iN[7], &iN[8],&iN[9],&iN[10],&iN[11],&iN[12],&iN[13],&iN[14],
324                 &iN[15],&iN[16],&iN[17],&iN[18],&iN[19],&iN[20],&iN[21],&iN[22],&iN[23],
325                 &iN[24],&iN[25],&iN[26], &ref);
326       if ( !myMesh->AddVolumeWithID( iN[0],iN[3],iN[2],iN[1],iN[4],iN[7],iN[6],iN[5],iN[11],iN[10],
327                                      iN[9],iN[8],iN[12],iN[15],iN[14], iN[13],iN[19],iN[18],iN[17],
328                                      iN[16],iN[20],iN[24],iN[23],iN[22],iN[21], iN[25],iN[26],
329                                      hex2IDShift + i ))
330         status = storeBadNodeIds( "GmfHexahedraQ2",i, 27,
331                                   iN[0],iN[3],iN[2],iN[1],iN[4], iN[7],iN[6],iN[5],iN[11],iN[10],
332                                   iN[9],iN[8],iN[12],iN[15],iN[14], iN[13],iN[19],iN[18],iN[17],
333                                   iN[16],iN[20],iN[24],iN[23],iN[22],iN[21], iN[25],iN[26]);
334     }
335   }
336   /* Read prism */
337   const int prismIDShift = myMesh->GetMeshInfo().NbElements();
338   if ( int nbPrism = GmfStatKwd(meshID, GmfPrisms))
339   {
340     GmfGotoKwd(meshID, GmfPrisms);
341     for ( int i = 1; i <= nbPrism; ++i )
342     {
343       GmfGetLin(meshID, GmfPrisms,
344                 &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref);
345       if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[5], iN[4], prismIDShift + i))
346         status = storeBadNodeIds( "GmfPrisms",i,
347                                   6, iN[0], iN[1],iN[2], iN[3], iN[4], iN[5] );
348     }
349   }
350
351   // Read required entities into groups
352
353   if ( _makeRequiredGroups )
354   {
355     // get ids of existing groups
356     std::set< int > groupIDs;
357     const std::set<SMESHDS_GroupBase*>& groups = myMesh->GetGroups();
358     std::set<SMESHDS_GroupBase*>::const_iterator grIter = groups.begin();
359     for ( ; grIter != groups.end(); ++grIter )
360       groupIDs.insert( (*grIter)->GetID() );
361     if ( groupIDs.empty() ) groupIDs.insert( 0 );
362
363     const int kes[4][3] = { { GmfRequiredVertices,      SMDSAbs_Node, nodeIDShift },
364                             { GmfRequiredEdges,         SMDSAbs_Edge, edgeIDShift },
365                             { GmfRequiredTriangles,     SMDSAbs_Face, triaIDShift },
366                             { GmfRequiredQuadrilaterals,SMDSAbs_Face, quadIDShift }};
367     const char* names[4] = { "_required_Vertices"      ,
368                              "_required_Edges"         ,
369                              "_required_Triangles"     ,
370                              "_required_Quadrilaterals" };
371     for ( int i = 0; i < 4; ++i )
372     {
373       int                 gmfKwd = kes[i][0];
374       SMDSAbs_ElementType entity = (SMDSAbs_ElementType) kes[i][1];
375       int                 shift  = kes[i][2];
376       if ( int nb = GmfStatKwd(meshID, gmfKwd))
377       {
378         const int newID = *groupIDs.rbegin() + 1;
379         groupIDs.insert( newID );
380         SMESHDS_Group* group = new SMESHDS_Group( newID, myMesh, entity );
381         group->SetStoreName( names[i] );
382         myMesh->AddGroup( group );
383
384         GmfGotoKwd(meshID, gmfKwd);
385         for ( int i = 0; i < nb; ++i )
386         {
387           GmfGetLin(meshID, gmfKwd, &iN[0] );
388           group->Add( shift + iN[0] );
389         }
390       }
391     }
392   }
393
394   return status;
395 }
396
397 //================================================================================
398 /*!
399  * \brief Store a message about invalid IDs of nodes
400  */
401 //================================================================================
402
403 Driver_Mesh::Status DriverGMF_Read::storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...)
404 {
405   if ( myStatus != DRS_OK )
406     return myStatus;
407
408   SMESH_Comment msg;
409
410   va_list VarArg;
411   va_start(VarArg, nb);
412
413   for ( int i = 0; i < nb; ++i )
414   {
415     int id = va_arg(VarArg, int );
416     if ( !myMesh->FindNode( id ))
417       msg << " " << id;
418   }
419   va_end(VarArg);
420
421   if ( !msg.empty() )
422   {
423     std::string nbStr;
424     const char* nbNames[] = { "1-st ", "2-nd ", "3-d " };
425     if ( elemNb < 3 ) nbStr = nbNames[ elemNb-1 ];
426     else              nbStr = SMESH_Comment(elemNb) << "-th ";
427
428     return addMessage
429       ( SMESH_Comment("Wrong node IDs of ")<< nbStr << gmfKwd << ":" << msg,
430         /*fatal=*/false );
431   }
432   return DRS_OK;
433 }