1 // Copyright (C) 2007-2024 CEA, EDF, 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_Write.cxx
23 // Created : Mon Sep 17 17:03:02 2012
24 // Author : Edward AGAPOV (eap)
26 #include "DriverGMF_Write.hxx"
27 #include "DriverGMF.hxx"
29 #include "SMESHDS_GroupBase.hxx"
30 #include "SMESHDS_Mesh.hxx"
31 #include "SMESH_Comment.hxx"
33 #include <Basics_Utils.hxx>
35 #include "utilities.h"
37 using SMESHUtils::ControlPnt;
46 #define BEGIN_ELEM_WRITE( SMDSEntity, GmfKwd, elem ) \
47 elemIt = elementIterator( SMDSEntity ); \
48 if ( elemIt->more() ) \
50 GmfSetKwd(meshID, GmfKwd, myMesh->GetMeshInfo().NbElements( SMDSEntity )); \
51 for ( int gmfID = 1; elemIt->more(); ++gmfID ) \
53 const SMDS_MeshElement* elem = elemIt->next(); \
54 GmfSetLin(meshID, GmfKwd,
56 #define BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom, LinType, GmfKwd, elem ) \
57 elemIt = elementIterator( SMDSGeom ); \
58 if ( elemIt->more() ) \
60 smIdType totalNbElems = myMesh->GetMeshInfo().NbElements( SMDSGeom );\
61 smIdType nbLinearElems = myMesh->GetMeshInfo().NbElements( LinType ); \
62 if ( totalNbElems - nbLinearElems > 0 ) \
64 GmfSetKwd(meshID, GmfKwd, totalNbElems - nbLinearElems); \
65 for ( int gmfID = 1; elemIt->more(); ++gmfID ) \
67 const SMDS_MeshElement* elem = elemIt->next(); \
68 if ( elem->IsQuadratic() ) { \
69 GmfSetLin(meshID, GmfKwd, gmfID, elem->NbNodes() - elem->NbCornerNodes(),
71 #define END_ELEM_WRITE( elem ) \
72 elem->getshapeId() ); \
75 #define END_ELEM_WRITE_ADD_TO_MAP( elem, e2id ) \
76 elem->getshapeId() ); \
77 e2id.insert( e2id.end(), std::make_pair( elem, gmfID )); \
80 #define END_EXTRA_VERTICES_WRITE() \
85 DriverGMF_Write::DriverGMF_Write():
86 Driver_SMESHDS_Mesh(), _exportRequiredGroups( true )
89 DriverGMF_Write::~DriverGMF_Write()
93 //================================================================================
95 * \brief Reads a GMF file
97 //================================================================================
99 Driver_Mesh::Status DriverGMF_Write::Perform()
101 Kernel_Utils::Localizer loc;
103 if ( Driver_Mesh::IsMeshTooLarge< int >( myMesh, /*checkIDs =*/ false))
104 return DRS_TOO_LARGE_MESH;
106 const int dim = 3, version = sizeof(double) < 8 ? 1 : 2;
108 int meshID = GmfOpenMesh( myFile.c_str(), GmfWrite, version, dim );
111 if ( DriverGMF::isExtensionCorrect( myFile ))
112 return addMessage( SMESH_Comment("Can't open for writing ") << myFile, /*fatal=*/true );
114 return addMessage( SMESH_Comment("Not '.mesh' or '.meshb' extension of file ") << myFile, /*fatal=*/true );
117 DriverGMF::MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction
120 std::map< const SMDS_MeshNode* , int > node2IdMap;
121 smIdType iN = 0, nbNodes = myMesh->NbNodes();
122 GmfSetKwd( meshID, GmfVertices, nbNodes );
124 SMDS_NodeIteratorPtr nodeIt = myMesh->nodesIterator();
125 while ( nodeIt->more() )
127 const SMDS_MeshNode* n = nodeIt->next();
129 GmfSetLin( meshID, GmfVertices, xyz[0], xyz[1], xyz[2], n->getshapeId() );
130 node2IdMap.insert( node2IdMap.end(), std::make_pair( n, ++iN ));
133 return addMessage("Wrong nb of nodes returned by nodesIterator", /*fatal=*/true);
136 SMDS_ElemIteratorPtr elemIt;
137 typedef std::map< const SMDS_MeshElement*, size_t, TIDCompare > TElem2IDMap;
140 TElem2IDMap edge2IDMap;
141 BEGIN_ELEM_WRITE( SMDSGeom_EDGE, GmfEdges, edge )
142 node2IdMap[ edge->GetNode( 0 )],
143 node2IdMap[ edge->GetNode( 1 )],
144 END_ELEM_WRITE_ADD_TO_MAP( edge, edge2IDMap );
146 // nodes of quadratic edges
147 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_EDGE, SMDSEntity_Edge,
148 GmfExtraVerticesAtEdges, edge )
149 node2IdMap[ edge->GetNode( 2 )]
150 END_EXTRA_VERTICES_WRITE();
153 TElem2IDMap tria2IDMap;
154 BEGIN_ELEM_WRITE( SMDSGeom_TRIANGLE, GmfTriangles, tria )
155 node2IdMap[ tria->GetNode( 0 )],
156 node2IdMap[ tria->GetNode( 1 )],
157 node2IdMap[ tria->GetNode( 2 )],
158 END_ELEM_WRITE_ADD_TO_MAP( tria, tria2IDMap );
160 // nodes of quadratic triangles
161 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_TRIANGLE, SMDSEntity_Triangle,
162 GmfExtraVerticesAtTriangles, tria )
163 node2IdMap[ tria->GetNode( 3 )],
164 node2IdMap[ tria->GetNode( 4 )],
165 node2IdMap[ tria->GetNode( 5 )],
166 node2IdMap[ tria->GetNodeWrap( 6 )] // for TRIA7
167 END_EXTRA_VERTICES_WRITE();
170 TElem2IDMap quad2IDMap;
171 BEGIN_ELEM_WRITE( SMDSGeom_QUADRANGLE, GmfQuadrilaterals, quad )
172 node2IdMap[ quad->GetNode( 0 )],
173 node2IdMap[ quad->GetNode( 1 )],
174 node2IdMap[ quad->GetNode( 2 )],
175 node2IdMap[ quad->GetNode( 3 )],
176 END_ELEM_WRITE_ADD_TO_MAP( quad, quad2IDMap );
178 // nodes of quadratic quadrangles
179 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_QUADRANGLE, SMDSEntity_Quadrangle,
180 GmfExtraVerticesAtQuadrilaterals, quad )
181 node2IdMap[ quad->GetNode( 4 )],
182 node2IdMap[ quad->GetNode( 5 )],
183 node2IdMap[ quad->GetNode( 6 )],
184 node2IdMap[ quad->GetNode( 7 )],
185 node2IdMap[ quad->GetNodeWrap( 8 )] // for QUAD9
186 END_EXTRA_VERTICES_WRITE();
189 BEGIN_ELEM_WRITE( SMDSGeom_TETRA, GmfTetrahedra, tetra )
190 node2IdMap[ tetra->GetNode( 0 )],
191 node2IdMap[ tetra->GetNode( 2 )],
192 node2IdMap[ tetra->GetNode( 1 )],
193 node2IdMap[ tetra->GetNode( 3 )],
194 END_ELEM_WRITE( tetra );
196 // nodes of quadratic terahedra
197 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_TETRA, SMDSEntity_Tetra,
198 GmfExtraVerticesAtTetrahedra, tetra )
199 node2IdMap[ tetra->GetNode( 6 )],
200 node2IdMap[ tetra->GetNode( 5 )],
201 node2IdMap[ tetra->GetNode( 4 )],
202 node2IdMap[ tetra->GetNode( 7 )],
203 node2IdMap[ tetra->GetNode( 9 )],
204 node2IdMap[ tetra->GetNode( 8 )]
205 //node2IdMap[ tetra->GetNodeWrap( 10 )], // for TETRA11
206 END_EXTRA_VERTICES_WRITE();
209 BEGIN_ELEM_WRITE( SMDSEntity_Pyramid, GmfPyramids, pyra )
210 node2IdMap[ pyra->GetNode( 3 )],
211 node2IdMap[ pyra->GetNode( 2 )],
212 node2IdMap[ pyra->GetNode( 1 )],
213 node2IdMap[ pyra->GetNode( 0 )],
214 node2IdMap[ pyra->GetNode( 4 )],
215 END_ELEM_WRITE( pyra );
218 BEGIN_ELEM_WRITE( SMDSGeom_HEXA, GmfHexahedra, hexa )
219 node2IdMap[ hexa->GetNode( 0 )],
220 node2IdMap[ hexa->GetNode( 3 )],
221 node2IdMap[ hexa->GetNode( 2 )],
222 node2IdMap[ hexa->GetNode( 1 )],
223 node2IdMap[ hexa->GetNode( 4 )],
224 node2IdMap[ hexa->GetNode( 7 )],
225 node2IdMap[ hexa->GetNode( 6 )],
226 node2IdMap[ hexa->GetNode( 5 )],
227 END_ELEM_WRITE( hexa );
229 // nodes of quadratic hexahedra
230 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_HEXA, SMDSEntity_Hexa,
231 GmfExtraVerticesAtHexahedra, hexa )
232 node2IdMap[ hexa->GetNode( 11 )], // HEXA20
233 node2IdMap[ hexa->GetNode( 10 )],
234 node2IdMap[ hexa->GetNode( 9 )],
235 node2IdMap[ hexa->GetNode( 8 )],
236 node2IdMap[ hexa->GetNode( 15 )],
237 node2IdMap[ hexa->GetNode( 14 )],
238 node2IdMap[ hexa->GetNode( 13 )],
239 node2IdMap[ hexa->GetNode( 12 )],
240 node2IdMap[ hexa->GetNode( 16 )],
241 node2IdMap[ hexa->GetNode( 19 )],
242 node2IdMap[ hexa->GetNodeWrap( 18 )], // + HEXA27
243 node2IdMap[ hexa->GetNodeWrap( 17 )],
244 node2IdMap[ hexa->GetNodeWrap( 20 )],
245 node2IdMap[ hexa->GetNodeWrap( 24 )],
246 node2IdMap[ hexa->GetNodeWrap( 23 )],
247 node2IdMap[ hexa->GetNodeWrap( 22 )],
248 node2IdMap[ hexa->GetNodeWrap( 21 )],
249 node2IdMap[ hexa->GetNodeWrap( 25 )],
250 node2IdMap[ hexa->GetNodeWrap( 26 )]
251 END_EXTRA_VERTICES_WRITE();
254 BEGIN_ELEM_WRITE( SMDSEntity_Penta, GmfPrisms, prism )
255 node2IdMap[ prism->GetNode( 0 )],
256 node2IdMap[ prism->GetNode( 2 )],
257 node2IdMap[ prism->GetNode( 1 )],
258 node2IdMap[ prism->GetNode( 3 )],
259 node2IdMap[ prism->GetNode( 5 )],
260 node2IdMap[ prism->GetNode( 4 )],
261 END_ELEM_WRITE( prism );
264 if ( _exportRequiredGroups )
267 SMESH_Comment badGroups;
268 const std::set<SMESHDS_GroupBase*>& groupSet = myMesh->GetGroups();
269 std::set<SMESHDS_GroupBase*>::const_iterator grIt = groupSet.begin();
270 for ( ; grIt != groupSet.end(); ++grIt )
272 const SMESHDS_GroupBase* group = *grIt;
273 std::string groupName = group->GetStoreName();
274 std::string::size_type pos = groupName.find( "_required_" );
275 if ( pos == std::string::npos ) continue;
278 SMDSAbs_EntityType smdsEntity;
279 std::string entity = groupName.substr( pos + strlen("_required_"));
280 if ( entity == "Vertices" ) {
281 gmfKwd = GmfRequiredVertices;
282 smdsEntity = SMDSEntity_Node;
284 else if ( entity == "Edges" ) {
285 gmfKwd = GmfRequiredEdges;
286 smdsEntity = SMDSEntity_Edge;
288 else if ( entity == "Triangles" ) {
289 gmfKwd = GmfRequiredTriangles;
290 smdsEntity = SMDSEntity_Triangle;
292 else if ( entity == "Quadrilaterals" ) {
293 gmfKwd = GmfRequiredQuadrilaterals;
294 smdsEntity = SMDSEntity_Quadrangle;
297 addMessage( SMESH_Comment("Invalig gmf entity name: ") << entity, /*fatal=*/false );
301 // check elem type in the group
303 SMDS_ElemIteratorPtr elemIt = group->GetElements();
304 while ( elemIt->more() )
305 nbOkElems += ( elemIt->next()->GetEntityType() == smdsEntity );
307 if ( nbOkElems != group->Extent() && nbOkElems == 0 )
309 badGroups << " " << groupName;
313 // choose a TElem2IDMap
314 TElem2IDMap* elem2IDMap = 0;
315 if ( smdsEntity == SMDSEntity_Quadrangle && nbOkElems != myMesh->NbFaces() )
316 elem2IDMap = & quad2IDMap;
317 else if ( smdsEntity == SMDSEntity_Triangle && nbOkElems != myMesh->NbFaces() )
318 elem2IDMap = & tria2IDMap;
319 else if ( smdsEntity == SMDSEntity_Edge && nbOkElems != myMesh->NbEdges() )
320 elem2IDMap = & edge2IDMap;
323 GmfSetKwd( meshID, gmfKwd, nbOkElems );
324 elemIt = group->GetElements();
326 for ( ; elemIt->more(); )
328 const SMDS_MeshElement* elem = elemIt->next();
329 if ( elem->GetEntityType() == smdsEntity )
330 GmfSetLin( meshID, gmfKwd, (*elem2IDMap)[ elem ] );
333 for ( int gmfID = 1; elemIt->more(); ++gmfID)
335 const SMDS_MeshElement* elem = elemIt->next();
336 if ( elem->GetEntityType() == smdsEntity )
337 GmfSetLin( meshID, gmfKwd, gmfID );
342 if ( !badGroups.empty() )
343 addMessage( SMESH_Comment("Groups of elements of inappropriate geometry:")
344 << badGroups, /*fatal=*/false );
350 Driver_Mesh::Status DriverGMF_Write::PerformSizeMap( const std::vector<ControlPnt>& points )
352 // const int dim = 3, version = sizeof(long) == 4 ? 2 : 3;
353 const int dim = 3, version = 2; // Version 3 not supported by mg-hexa
356 int verticesFileID = GmfOpenMesh( myVerticesFile.c_str(), GmfWrite, version, dim );
357 int solFileID = GmfOpenMesh( mySolFile.c_str(), GmfWrite, version, dim );
359 int pointsNumber = points.size();
362 GmfSetKwd( verticesFileID, GmfVertices, pointsNumber );
363 // SolAtVertices Keyword
364 int TypTab[] = {GmfSca};
365 GmfSetKwd(solFileID, GmfSolAtVertices, pointsNumber, 1, TypTab);
367 // Read the control points information from the vector and write it into the files
368 std::vector<ControlPnt>::const_iterator points_it;
369 for (points_it = points.begin(); points_it != points.end(); points_it++ )
371 GmfSetLin( verticesFileID, GmfVertices, points_it->X(), points_it->Y(), points_it->Z(), 0 );
372 double ValTab[] = {points_it->Size()};
373 GmfSetLin( solFileID, GmfSolAtVertices, ValTab);
377 GmfCloseMesh( verticesFileID );
378 GmfCloseMesh( solFileID );
383 std::vector<std::string> DriverGMF_Write::GetSizeMapFiles()
385 std::vector<std::string> files;
386 files.push_back(myVerticesFile);
387 files.push_back(mySolFile);
391 //================================================================================
393 * \brief Returns an iterator on elements of a certain type
395 //================================================================================
397 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_ElementType type)
399 return myMesh->elementsIterator(type);
401 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_EntityType type)
403 return myMesh->elementEntityIterator(type);
405 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_GeometryType type)
407 return myMesh->elementGeomIterator(type);