1 // Copyright (C) 2007-2020 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_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 int totalNbElems = myMesh->GetMeshInfo().NbElements( SMDSGeom ); \
61 int 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 const int dim = 3, version = sizeof(double) < 8 ? 1 : 2;
105 int meshID = GmfOpenMesh( myFile.c_str(), GmfWrite, version, dim );
108 if ( DriverGMF::isExtensionCorrect( myFile ))
109 return addMessage( SMESH_Comment("Can't open for writing ") << myFile, /*fatal=*/true );
111 return addMessage( SMESH_Comment("Not '.mesh' or '.meshb' extension of file ") << myFile, /*fatal=*/true );
114 DriverGMF::MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction
117 std::map< const SMDS_MeshNode* , int > node2IdMap;
118 int iN = 0, nbNodes = myMesh->NbNodes();
119 GmfSetKwd( meshID, GmfVertices, nbNodes );
121 SMDS_NodeIteratorPtr nodeIt = myMesh->nodesIterator();
122 while ( nodeIt->more() )
124 const SMDS_MeshNode* n = nodeIt->next();
126 GmfSetLin( meshID, GmfVertices, xyz[0], xyz[1], xyz[2], n->getshapeId() );
127 node2IdMap.insert( node2IdMap.end(), std::make_pair( n, ++iN ));
130 return addMessage("Wrong nb of nodes returned by nodesIterator", /*fatal=*/true);
133 SMDS_ElemIteratorPtr elemIt;
134 typedef std::map< const SMDS_MeshElement*, size_t, TIDCompare > TElem2IDMap;
137 TElem2IDMap edge2IDMap;
138 BEGIN_ELEM_WRITE( SMDSGeom_EDGE, GmfEdges, edge )
139 node2IdMap[ edge->GetNode( 0 )],
140 node2IdMap[ edge->GetNode( 1 )],
141 END_ELEM_WRITE_ADD_TO_MAP( edge, edge2IDMap );
143 // nodes of quadratic edges
144 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_EDGE, SMDSEntity_Edge,
145 GmfExtraVerticesAtEdges, edge )
146 node2IdMap[ edge->GetNode( 2 )]
147 END_EXTRA_VERTICES_WRITE();
150 TElem2IDMap tria2IDMap;
151 BEGIN_ELEM_WRITE( SMDSGeom_TRIANGLE, GmfTriangles, tria )
152 node2IdMap[ tria->GetNode( 0 )],
153 node2IdMap[ tria->GetNode( 1 )],
154 node2IdMap[ tria->GetNode( 2 )],
155 END_ELEM_WRITE_ADD_TO_MAP( tria, tria2IDMap );
157 // nodes of quadratic triangles
158 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_TRIANGLE, SMDSEntity_Triangle,
159 GmfExtraVerticesAtTriangles, tria )
160 node2IdMap[ tria->GetNode( 3 )],
161 node2IdMap[ tria->GetNode( 4 )],
162 node2IdMap[ tria->GetNode( 5 )],
163 node2IdMap[ tria->GetNodeWrap( 6 )] // for TRIA7
164 END_EXTRA_VERTICES_WRITE();
167 TElem2IDMap quad2IDMap;
168 BEGIN_ELEM_WRITE( SMDSGeom_QUADRANGLE, GmfQuadrilaterals, quad )
169 node2IdMap[ quad->GetNode( 0 )],
170 node2IdMap[ quad->GetNode( 1 )],
171 node2IdMap[ quad->GetNode( 2 )],
172 node2IdMap[ quad->GetNode( 3 )],
173 END_ELEM_WRITE_ADD_TO_MAP( quad, quad2IDMap );
175 // nodes of quadratic quadrangles
176 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_QUADRANGLE, SMDSEntity_Quadrangle,
177 GmfExtraVerticesAtQuadrilaterals, quad )
178 node2IdMap[ quad->GetNode( 4 )],
179 node2IdMap[ quad->GetNode( 5 )],
180 node2IdMap[ quad->GetNode( 6 )],
181 node2IdMap[ quad->GetNode( 7 )],
182 node2IdMap[ quad->GetNodeWrap( 8 )] // for QUAD9
183 END_EXTRA_VERTICES_WRITE();
186 BEGIN_ELEM_WRITE( SMDSGeom_TETRA, GmfTetrahedra, tetra )
187 node2IdMap[ tetra->GetNode( 0 )],
188 node2IdMap[ tetra->GetNode( 2 )],
189 node2IdMap[ tetra->GetNode( 1 )],
190 node2IdMap[ tetra->GetNode( 3 )],
191 END_ELEM_WRITE( tetra );
193 // nodes of quadratic terahedra
194 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_TETRA, SMDSEntity_Tetra,
195 GmfExtraVerticesAtTetrahedra, tetra )
196 node2IdMap[ tetra->GetNode( 6 )],
197 node2IdMap[ tetra->GetNode( 5 )],
198 node2IdMap[ tetra->GetNode( 4 )],
199 node2IdMap[ tetra->GetNode( 7 )],
200 node2IdMap[ tetra->GetNode( 9 )],
201 node2IdMap[ tetra->GetNode( 8 )]
202 //node2IdMap[ tetra->GetNodeWrap( 10 )], // for TETRA11
203 END_EXTRA_VERTICES_WRITE();
206 BEGIN_ELEM_WRITE( SMDSEntity_Pyramid, GmfPyramids, pyra )
207 node2IdMap[ pyra->GetNode( 3 )],
208 node2IdMap[ pyra->GetNode( 2 )],
209 node2IdMap[ pyra->GetNode( 1 )],
210 node2IdMap[ pyra->GetNode( 0 )],
211 node2IdMap[ pyra->GetNode( 4 )],
212 END_ELEM_WRITE( pyra );
215 BEGIN_ELEM_WRITE( SMDSGeom_HEXA, GmfHexahedra, hexa )
216 node2IdMap[ hexa->GetNode( 0 )],
217 node2IdMap[ hexa->GetNode( 3 )],
218 node2IdMap[ hexa->GetNode( 2 )],
219 node2IdMap[ hexa->GetNode( 1 )],
220 node2IdMap[ hexa->GetNode( 4 )],
221 node2IdMap[ hexa->GetNode( 7 )],
222 node2IdMap[ hexa->GetNode( 6 )],
223 node2IdMap[ hexa->GetNode( 5 )],
224 END_ELEM_WRITE( hexa );
226 // nodes of quadratic hexahedra
227 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_HEXA, SMDSEntity_Hexa,
228 GmfExtraVerticesAtHexahedra, hexa )
229 node2IdMap[ hexa->GetNode( 11 )], // HEXA20
230 node2IdMap[ hexa->GetNode( 10 )],
231 node2IdMap[ hexa->GetNode( 9 )],
232 node2IdMap[ hexa->GetNode( 8 )],
233 node2IdMap[ hexa->GetNode( 15 )],
234 node2IdMap[ hexa->GetNode( 14 )],
235 node2IdMap[ hexa->GetNode( 13 )],
236 node2IdMap[ hexa->GetNode( 12 )],
237 node2IdMap[ hexa->GetNode( 16 )],
238 node2IdMap[ hexa->GetNode( 19 )],
239 node2IdMap[ hexa->GetNodeWrap( 18 )], // + HEXA27
240 node2IdMap[ hexa->GetNodeWrap( 17 )],
241 node2IdMap[ hexa->GetNodeWrap( 20 )],
242 node2IdMap[ hexa->GetNodeWrap( 24 )],
243 node2IdMap[ hexa->GetNodeWrap( 23 )],
244 node2IdMap[ hexa->GetNodeWrap( 22 )],
245 node2IdMap[ hexa->GetNodeWrap( 21 )],
246 node2IdMap[ hexa->GetNodeWrap( 25 )],
247 node2IdMap[ hexa->GetNodeWrap( 26 )]
248 END_EXTRA_VERTICES_WRITE();
251 BEGIN_ELEM_WRITE( SMDSEntity_Penta, GmfPrisms, prism )
252 node2IdMap[ prism->GetNode( 0 )],
253 node2IdMap[ prism->GetNode( 2 )],
254 node2IdMap[ prism->GetNode( 1 )],
255 node2IdMap[ prism->GetNode( 3 )],
256 node2IdMap[ prism->GetNode( 5 )],
257 node2IdMap[ prism->GetNode( 4 )],
258 END_ELEM_WRITE( prism );
261 if ( _exportRequiredGroups )
264 SMESH_Comment badGroups;
265 const std::set<SMESHDS_GroupBase*>& groupSet = myMesh->GetGroups();
266 std::set<SMESHDS_GroupBase*>::const_iterator grIt = groupSet.begin();
267 for ( ; grIt != groupSet.end(); ++grIt )
269 const SMESHDS_GroupBase* group = *grIt;
270 std::string groupName = group->GetStoreName();
271 std::string::size_type pos = groupName.find( "_required_" );
272 if ( pos == std::string::npos ) continue;
275 SMDSAbs_EntityType smdsEntity;
276 std::string entity = groupName.substr( pos + strlen("_required_"));
277 if ( entity == "Vertices" ) {
278 gmfKwd = GmfRequiredVertices;
279 smdsEntity = SMDSEntity_Node;
281 else if ( entity == "Edges" ) {
282 gmfKwd = GmfRequiredEdges;
283 smdsEntity = SMDSEntity_Edge;
285 else if ( entity == "Triangles" ) {
286 gmfKwd = GmfRequiredTriangles;
287 smdsEntity = SMDSEntity_Triangle;
289 else if ( entity == "Quadrilaterals" ) {
290 gmfKwd = GmfRequiredQuadrilaterals;
291 smdsEntity = SMDSEntity_Quadrangle;
294 addMessage( SMESH_Comment("Invalig gmf entity name: ") << entity, /*fatal=*/false );
298 // check elem type in the group
300 SMDS_ElemIteratorPtr elemIt = group->GetElements();
301 while ( elemIt->more() )
302 nbOkElems += ( elemIt->next()->GetEntityType() == smdsEntity );
304 if ( nbOkElems != group->Extent() && nbOkElems == 0 )
306 badGroups << " " << groupName;
310 // choose a TElem2IDMap
311 TElem2IDMap* elem2IDMap = 0;
312 if ( smdsEntity == SMDSEntity_Quadrangle && nbOkElems != myMesh->NbFaces() )
313 elem2IDMap = & quad2IDMap;
314 else if ( smdsEntity == SMDSEntity_Triangle && nbOkElems != myMesh->NbFaces() )
315 elem2IDMap = & tria2IDMap;
316 else if ( smdsEntity == SMDSEntity_Edge && nbOkElems != myMesh->NbEdges() )
317 elem2IDMap = & edge2IDMap;
320 GmfSetKwd( meshID, gmfKwd, nbOkElems );
321 elemIt = group->GetElements();
323 for ( ; elemIt->more(); )
325 const SMDS_MeshElement* elem = elemIt->next();
326 if ( elem->GetEntityType() == smdsEntity )
327 GmfSetLin( meshID, gmfKwd, (*elem2IDMap)[ elem ] );
330 for ( int gmfID = 1; elemIt->more(); ++gmfID)
332 const SMDS_MeshElement* elem = elemIt->next();
333 if ( elem->GetEntityType() == smdsEntity )
334 GmfSetLin( meshID, gmfKwd, gmfID );
339 if ( !badGroups.empty() )
340 addMessage( SMESH_Comment("Groups of elements of inappropriate geometry:")
341 << badGroups, /*fatal=*/false );
347 Driver_Mesh::Status DriverGMF_Write::PerformSizeMap( const std::vector<ControlPnt>& points )
349 // const int dim = 3, version = sizeof(long) == 4 ? 2 : 3;
350 const int dim = 3, version = 2; // Version 3 not supported by mg-hexa
353 int verticesFileID = GmfOpenMesh( myVerticesFile.c_str(), GmfWrite, version, dim );
354 int solFileID = GmfOpenMesh( mySolFile.c_str(), GmfWrite, version, dim );
356 int pointsNumber = points.size();
359 GmfSetKwd( verticesFileID, GmfVertices, pointsNumber );
360 // SolAtVertices Keyword
361 int TypTab[] = {GmfSca};
362 GmfSetKwd(solFileID, GmfSolAtVertices, pointsNumber, 1, TypTab);
364 // Read the control points information from the vector and write it into the files
365 std::vector<ControlPnt>::const_iterator points_it;
366 for (points_it = points.begin(); points_it != points.end(); points_it++ )
368 GmfSetLin( verticesFileID, GmfVertices, points_it->X(), points_it->Y(), points_it->Z(), 0 );
369 double ValTab[] = {points_it->Size()};
370 GmfSetLin( solFileID, GmfSolAtVertices, ValTab);
374 GmfCloseMesh( verticesFileID );
375 GmfCloseMesh( solFileID );
380 std::vector<std::string> DriverGMF_Write::GetSizeMapFiles()
382 std::vector<std::string> files;
383 files.push_back(myVerticesFile);
384 files.push_back(mySolFile);
388 //================================================================================
390 * \brief Returns an iterator on elements of a certain type
392 //================================================================================
394 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_ElementType type)
396 return myMesh->elementsIterator(type);
398 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_EntityType type)
400 return myMesh->elementEntityIterator(type);
402 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_GeometryType type)
404 return myMesh->elementGeomIterator(type);