1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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, or (at your option) any later version.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File : DriverGMF_Read.cxx
23 // Created : Mon Sep 17 17:03:02 2012
24 // Author : Edward AGAPOV (eap)
26 #include "DriverGMF_Read.hxx"
27 #include "DriverGMF.hxx"
29 #include "SMESHDS_Group.hxx"
30 #include "SMESHDS_Mesh.hxx"
31 #include "SMESH_Comment.hxx"
32 #include "SMESH_TypeDefs.hxx"
34 #include <Basics_Utils.hxx>
43 // --------------------------------------------------------------------------------
44 DriverGMF_Read::DriverGMF_Read():
45 Driver_SMESHDS_Mesh(),
46 _makeRequiredGroups( true )
49 // --------------------------------------------------------------------------------
50 DriverGMF_Read::~DriverGMF_Read()
54 //================================================================================
56 * \brief Read a GMF file
58 //================================================================================
60 Driver_Mesh::Status DriverGMF_Read::Perform()
62 Kernel_Utils::Localizer loc;
64 Status status = DRS_OK;
69 int meshID = GmfOpenMesh( myFile.c_str(), GmfRead, &version, &dim );
72 if ( DriverGMF::isExtensionCorrect( myFile ))
73 return addMessage( SMESH_Comment("Can't open for reading ") << myFile,
76 return addMessage( SMESH_Comment("Not '.mesh' or '.meshb' extension of file ") << myFile,
79 DriverGMF::MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction
83 int nbNodes = GmfStatKwd(meshID, GmfVertices);
85 return addMessage( "No nodes in the mesh", /*fatal=*/true );
87 GmfGotoKwd(meshID, GmfVertices);
91 const int nodeIDShift = myMesh->GetMeshInfo().NbNodes();
92 if ( version != GmfFloat )
95 for ( int i = 1; i <= nbNodes; ++i )
97 GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref);
98 myMesh->AddNodeWithID( x,y,z, nodeIDShift + i);
104 for ( int i = 1; i <= nbNodes; ++i )
106 GmfGetLin(meshID, GmfVertices, &x, &y, &z, &ref);
107 myMesh->AddNodeWithID( x,y,z, nodeIDShift + i);
113 int iN[28]; // 28 - nb nodes in HEX27 (+ 1 for safety :)
116 const int edgeIDShift = myMesh->GetMeshInfo().NbElements();
117 if ( int nbEdges = GmfStatKwd(meshID, GmfEdges))
119 // read extra vertices for quadratic edges
120 std::vector<int> quadNodesAtEdges( nbEdges + 1, -1 );
121 if ( int nbQuadEdges = GmfStatKwd(meshID, GmfExtraVerticesAtEdges))
123 GmfGotoKwd(meshID, GmfExtraVerticesAtEdges);
124 for ( int i = 1; i <= nbQuadEdges; ++i )
126 GmfGetLin(meshID, GmfExtraVerticesAtEdges, &iN[0], &iN[1], &iN[2]);
128 quadNodesAtEdges[ iN[0] ] = iN[2];
132 GmfGotoKwd(meshID, GmfEdges);
133 for ( int i = 1; i <= nbEdges; ++i )
135 GmfGetLin(meshID, GmfEdges, &iN[0], &iN[1], &ref);
136 const int midN = quadNodesAtEdges[ i ];
139 if ( !myMesh->AddEdgeWithID( iN[0], iN[1], midN, edgeIDShift + i ))
140 status = storeBadNodeIds( "GmfEdges + GmfExtraVerticesAtEdges",i,
141 3, iN[0], iN[1], midN);
145 if ( !myMesh->AddEdgeWithID( iN[0], iN[1], edgeIDShift + i ))
146 status = storeBadNodeIds( "GmfEdges",i, 2, iN[0], iN[1] );
152 const int triaIDShift = myMesh->GetMeshInfo().NbElements();
153 if ( int nbTria = GmfStatKwd(meshID, GmfTriangles))
155 // read extra vertices for quadratic triangles
156 std::vector< std::vector<int> > quadNodesAtTriangles( nbTria + 1 );
157 if ( int nbQuadTria = GmfStatKwd(meshID, GmfExtraVerticesAtTriangles ))
159 GmfGotoKwd( meshID, GmfExtraVerticesAtTriangles );
160 for ( int i = 1; i <= nbQuadTria; ++i )
162 GmfGetLin(meshID, GmfExtraVerticesAtTriangles,
163 &iN[0], &iN[1], &iN[2], &iN[3], &iN[4],
164 &iN[5]); // iN[5] - preview TRIA7
165 if ( iN[0] <= nbTria )
167 std::vector<int>& nodes = quadNodesAtTriangles[ iN[0] ];
168 nodes.insert( nodes.end(), & iN[2], & iN[5+1] );
169 nodes.resize( iN[1] );
174 GmfGotoKwd(meshID, GmfTriangles);
175 for ( int i = 1; i <= nbTria; ++i )
177 GmfGetLin(meshID, GmfTriangles, &iN[0], &iN[1], &iN[2], &ref);
178 std::vector<int>& midN = quadNodesAtTriangles[ i ];
179 if ( midN.size() >= 3 )
181 if ( !myMesh->AddFaceWithID( iN[0],iN[1],iN[2], midN[0],midN[1],midN[2],
183 status = storeBadNodeIds( "GmfTriangles + GmfExtraVerticesAtTriangles",i, 6,
184 iN[0],iN[1],iN[2], midN[0],midN[1],midN[2] );
188 if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], triaIDShift + i ))
189 status = storeBadNodeIds( "GmfTriangles",i, 3, iN[0], iN[1], iN[2] );
191 if ( !midN.empty() ) SMESHUtils::FreeVector( midN );
195 /* Read quadrangles */
196 const int quadIDShift = myMesh->GetMeshInfo().NbElements();
197 if ( int nbQuad = GmfStatKwd(meshID, GmfQuadrilaterals))
199 // read extra vertices for quadratic quadrangles
200 std::vector< std::vector<int> > quadNodesAtQuadrilaterals( nbQuad + 1 );
201 if ( int nbQuadQuad = GmfStatKwd( meshID, GmfExtraVerticesAtQuadrilaterals ))
203 GmfGotoKwd(meshID, GmfExtraVerticesAtQuadrilaterals);
204 for ( int i = 1; i <= nbQuadQuad; ++i )
206 GmfGetLin(meshID, GmfExtraVerticesAtQuadrilaterals,
207 &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6]);
208 if ( iN[0] <= nbQuad )
210 std::vector<int>& nodes = quadNodesAtQuadrilaterals[ iN[0] ];
211 nodes.insert( nodes.end(), & iN[2], & iN[6+1] );
212 nodes.resize( iN[1] );
216 // create quadrangles
217 GmfGotoKwd(meshID, GmfQuadrilaterals);
218 for ( int i = 1; i <= nbQuad; ++i )
220 GmfGetLin(meshID, GmfQuadrilaterals, &iN[0], &iN[1], &iN[2], &iN[3], &ref);
221 std::vector<int>& midN = quadNodesAtQuadrilaterals[ i ];
222 if ( midN.size() == 8-4 ) // QUAD8
224 if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3],
225 midN[0], midN[1], midN[2], midN[3],
227 status = storeBadNodeIds( "GmfQuadrilaterals + GmfExtraVerticesAtQuadrilaterals",i, 8,
228 iN[0], iN[1],iN[2], iN[3],
229 midN[0], midN[1], midN[2], midN[3]);
231 else if ( midN.size() > 8-4 ) // QUAD9
233 if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3],
234 midN[0], midN[1], midN[2], midN[3], midN[4],
236 status = storeBadNodeIds( "GmfQuadrilaterals + GmfExtraVerticesAtQuadrilaterals",i, 9,
237 iN[0], iN[1],iN[2], iN[3],
238 midN[0], midN[1], midN[2], midN[3], midN[4]);
242 if ( !myMesh->AddFaceWithID( iN[0], iN[1], iN[2], iN[3], quadIDShift + i ))
243 status = storeBadNodeIds( "GmfQuadrilaterals",i, 4, iN[0], iN[1],iN[2], iN[3] );
245 if ( !midN.empty() ) SMESHUtils::FreeVector( midN );
250 const int tetIDShift = myMesh->GetMeshInfo().NbElements();
251 if ( int nbTet = GmfStatKwd( meshID, GmfTetrahedra ))
253 // read extra vertices for quadratic tetrahedra
254 std::vector< std::vector<int> > quadNodesAtTetrahedra( nbTet + 1 );
255 if ( int nbQuadTetra = GmfStatKwd( meshID, GmfExtraVerticesAtTetrahedra ))
257 GmfGotoKwd(meshID, GmfExtraVerticesAtTetrahedra);
258 for ( int i = 1; i <= nbQuadTetra; ++i )
260 GmfGetLin(meshID, GmfExtraVerticesAtTetrahedra,
261 &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &iN[6], &iN[7]);
262 if ( iN[0] <= nbTet )
264 std::vector<int>& nodes = quadNodesAtTetrahedra[ iN[0] ];
265 nodes.insert( nodes.end(), & iN[2], & iN[7+1] );
266 nodes.resize( iN[1] );
271 GmfGotoKwd(meshID, GmfTetrahedra);
272 for ( int i = 1; i <= nbTet; ++i )
274 GmfGetLin(meshID, GmfTetrahedra, &iN[0], &iN[1], &iN[2], &iN[3], &ref);
275 std::vector<int>& midN = quadNodesAtTetrahedra[ i ];
276 if ( midN.size() >= 10-4 ) // TETRA10
278 if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3],
279 midN[2], midN[1], midN[0], midN[3], midN[5], midN[4],
281 status = storeBadNodeIds( "GmfTetrahedra + GmfExtraVerticesAtTetrahedra",i, 10,
282 iN[0], iN[2], iN[1], iN[3],
283 midN[2], midN[1], midN[0], midN[3], midN[5], midN[4] );
287 if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], tetIDShift + i ))
288 status = storeBadNodeIds( "GmfTetrahedra" ,i, 4, iN[0], iN[2], iN[1], iN[3] );
290 if ( !midN.empty() ) SMESHUtils::FreeVector( midN );
295 const int pyrIDShift = myMesh->GetMeshInfo().NbElements();
296 if ( int nbPyr = GmfStatKwd(meshID, GmfPyramids))
298 GmfGotoKwd(meshID, GmfPyramids);
299 for ( int i = 1; i <= nbPyr; ++i )
301 GmfGetLin(meshID, GmfPyramids, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &ref);
302 if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[4], pyrIDShift + i ))
303 status = storeBadNodeIds( "GmfPyramids",i, 5, iN[0], iN[1],iN[2], iN[3], iN[4] );
308 const int hexIDShift = myMesh->GetMeshInfo().NbElements();
309 if ( int nbHex = GmfStatKwd(meshID, GmfHexahedra))
311 // read extra vertices for quadratic hexahedra
312 std::vector< std::vector<int> > quadNodesAtHexahedra( nbHex + 1 );
313 if ( int nbQuadHexa = GmfStatKwd( meshID, GmfExtraVerticesAtHexahedra ))
315 GmfGotoKwd(meshID, GmfExtraVerticesAtHexahedra);
316 for ( int i = 1; i <= nbQuadHexa; ++i )
318 GmfGetLin(meshID, GmfExtraVerticesAtHexahedra, &iN[0], &iN[1], // Hexa Id, Nb extra vertices
319 &iN[2], &iN[3], &iN[4], &iN[5],
320 &iN[6], &iN[7], &iN[8], &iN[9],
321 &iN[10], &iN[11], &iN[12], &iN[13], // HEXA20
323 &iN[15], &iN[16], &iN[17], &iN[18],
326 if ( iN[0] <= nbHex )
328 std::vector<int>& nodes = quadNodesAtHexahedra[ iN[0] ];
329 nodes.insert( nodes.end(), & iN[2], & iN[20+1] );
330 nodes.resize( iN[1] );
335 GmfGotoKwd(meshID, GmfHexahedra);
336 for ( int i = 1; i <= nbHex; ++i )
338 GmfGetLin(meshID, GmfHexahedra, &iN[0], &iN[1], &iN[2], &iN[3],
339 &iN[4], &iN[5], &iN[6], &iN[7], &ref);
340 std::vector<int>& midN = quadNodesAtHexahedra[ i ];
341 if ( midN.size() == 20-8 ) // HEXA20
343 if ( !myMesh->AddVolumeWithID( iN[0], iN[3], iN[2], iN[1],
344 iN[4], iN[7], iN[6], iN[5],
345 midN[3], midN[2], midN[1], midN[0],
346 midN[7], midN[6], midN[5], midN[4],
347 midN[8], midN[11], midN[10], midN[9],
349 status = storeBadNodeIds( "GmfHexahedra + GmfExtraVerticesAtHexahedra",i, 20,
350 iN[0], iN[3], iN[2], iN[1],
351 iN[4], iN[7], iN[6], iN[5],
352 midN[3], midN[2], midN[1], midN[0],
353 midN[7], midN[6], midN[5], midN[4],
354 midN[8], midN[11], midN[10], midN[9]);
356 else if ( midN.size() >= 27-8 ) // HEXA27
358 if ( !myMesh->AddVolumeWithID( iN[0], iN[3], iN[2], iN[1],
359 iN[4], iN[7], iN[6], iN[5],
360 midN[3], midN[2], midN[1], midN[0],
361 midN[7], midN[6], midN[5], midN[4],
362 midN[8], midN[11], midN[10], midN[9],
364 midN[16], midN[15], midN[14], midN[13],
368 status = storeBadNodeIds( "GmfHexahedra + GmfExtraVerticesAtHexahedra",i, 27,
369 iN[0], iN[3], iN[2], iN[1],
370 iN[4], iN[7], iN[6], iN[5],
371 midN[3], midN[2], midN[1], midN[0],
372 midN[7], midN[6], midN[5], midN[4],
373 midN[8], midN[11], midN[10], midN[9],
375 midN[16], midN[15], midN[14], midN[13],
381 if ( !myMesh->AddVolumeWithID( iN[0], iN[3], iN[2], iN[1],
382 iN[4], iN[7], iN[6], iN[5], hexIDShift + i ) )
383 status = storeBadNodeIds( "GmfHexahedra" ,i, 8, iN[0], iN[3], iN[2], iN[1],
384 iN[4], iN[7], iN[6], iN[5] );
386 if ( !midN.empty() ) SMESHUtils::FreeVector( midN );
391 const int prismIDShift = myMesh->GetMeshInfo().NbElements();
392 if ( int nbPrism = GmfStatKwd(meshID, GmfPrisms))
394 GmfGotoKwd(meshID, GmfPrisms);
395 for ( int i = 1; i <= nbPrism; ++i )
397 GmfGetLin(meshID, GmfPrisms, &iN[0], &iN[1], &iN[2], &iN[3], &iN[4], &iN[5], &ref);
398 if ( !myMesh->AddVolumeWithID( iN[0], iN[2], iN[1], iN[3], iN[5], iN[4], prismIDShift + i))
399 status = storeBadNodeIds( "GmfPrisms",i,
400 6, iN[0], iN[1],iN[2], iN[3], iN[4], iN[5] );
404 // Read required entities into groups
406 if ( _makeRequiredGroups )
408 // get ids of existing groups
409 std::set< int > groupIDs;
410 const std::set<SMESHDS_GroupBase*>& groups = myMesh->GetGroups();
411 std::set<SMESHDS_GroupBase*>::const_iterator grIter = groups.begin();
412 for ( ; grIter != groups.end(); ++grIter )
413 groupIDs.insert( (*grIter)->GetID() );
414 if ( groupIDs.empty() ) groupIDs.insert( 0 );
416 const int kes[4][3] = { { GmfRequiredVertices, SMDSAbs_Node, nodeIDShift },
417 { GmfRequiredEdges, SMDSAbs_Edge, edgeIDShift },
418 { GmfRequiredTriangles, SMDSAbs_Face, triaIDShift },
419 { GmfRequiredQuadrilaterals,SMDSAbs_Face, quadIDShift }};
420 const char* names[4] = { "_required_Vertices" ,
422 "_required_Triangles" ,
423 "_required_Quadrilaterals" };
424 for ( int i = 0; i < 4; ++i )
426 int gmfKwd = kes[i][0];
427 SMDSAbs_ElementType entity = (SMDSAbs_ElementType) kes[i][1];
428 int shift = kes[i][2];
429 if ( int nb = GmfStatKwd(meshID, gmfKwd))
431 const int newID = *groupIDs.rbegin() + 1;
432 groupIDs.insert( newID );
433 SMESHDS_Group* group = new SMESHDS_Group( newID, myMesh, entity );
434 group->SetStoreName( names[i] );
435 myMesh->AddGroup( group );
437 GmfGotoKwd(meshID, gmfKwd);
438 for ( int i = 0; i < nb; ++i )
440 GmfGetLin(meshID, gmfKwd, &iN[0] );
441 group->Add( shift + iN[0] );
450 //================================================================================
452 * \brief Store a message about invalid IDs of nodes
454 //================================================================================
456 Driver_Mesh::Status DriverGMF_Read::storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...)
458 if ( myStatus != DRS_OK )
464 va_start(VarArg, nb);
466 for ( int i = 0; i < nb; ++i )
468 int id = va_arg(VarArg, int );
469 if ( !myMesh->FindNode( id ))
477 const char* nbNames[] = { "1-st ", "2-nd ", "3-d " };
478 if ( elemNb < 3 ) nbStr = nbNames[ elemNb-1 ];
479 else nbStr = SMESH_Comment(elemNb) << "-th ";
482 ( SMESH_Comment("Wrong node IDs of ")<< nbStr << gmfKwd << ":" << msg,