1 // Copyright (C) 2007-2014 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"
44 #define BEGIN_ELEM_WRITE( SMDSEntity, GmfKwd, elem ) \
45 elemIt = elementIterator( SMDSEntity ); \
46 if ( elemIt->more() ) \
48 GmfSetKwd(meshID, GmfKwd, myMesh->GetMeshInfo().NbElements( SMDSEntity )); \
49 for ( int gmfID = 1; elemIt->more(); ++gmfID ) \
51 const SMDS_MeshElement* elem = elemIt->next(); \
52 GmfSetLin(meshID, GmfKwd,
54 #define BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom, LinType, GmfKwd, elem ) \
55 elemIt = elementIterator( SMDSGeom ); \
56 if ( elemIt->more() ) \
58 int totalNbElems = myMesh->GetMeshInfo().NbElements( SMDSGeom ); \
59 int nbLinearElems = myMesh->GetMeshInfo().NbElements( LinType ); \
60 if ( totalNbElems - nbLinearElems > 0 ) \
62 GmfSetKwd(meshID, GmfKwd, totalNbElems - nbLinearElems); \
63 for ( int gmfID = 1; elemIt->more(); ++gmfID ) \
65 const SMDS_MeshElement* elem = elemIt->next(); \
66 if ( elem->IsQuadratic() ) { \
67 GmfSetLin(meshID, GmfKwd, gmfID, elem->NbNodes() - elem->NbCornerNodes(),
69 #define END_ELEM_WRITE( elem ) \
70 elem->getshapeId() ); \
73 #define END_ELEM_WRITE_ADD_TO_MAP( elem, e2id ) \
74 elem->getshapeId() ); \
75 e2id.insert( e2id.end(), make_pair( elem, gmfID )); \
78 #define END_EXTRA_VERTICES_WRITE() \
83 Control_Pnt::Control_Pnt(): gp_Pnt()
87 Control_Pnt::Control_Pnt( const gp_Pnt& aPnt,
88 double theSize): gp_Pnt( aPnt )
92 Control_Pnt::Control_Pnt(double theX,
94 double theZ): gp_Pnt(theX, theY, theZ)
98 Control_Pnt::Control_Pnt(double theX,
101 double theSize): gp_Pnt(theX, theY, theZ)
106 DriverGMF_Write::DriverGMF_Write():
107 Driver_SMESHDS_Mesh(), _exportRequiredGroups( true )
110 DriverGMF_Write::~DriverGMF_Write()
114 //================================================================================
116 * \brief Reads a GMF file
118 //================================================================================
120 Driver_Mesh::Status DriverGMF_Write::Perform()
122 Kernel_Utils::Localizer loc;
124 const int dim = 3, version = sizeof(long) == 4 ? 2 : 3;
126 int meshID = GmfOpenMesh( myFile.c_str(), GmfWrite, version, dim );
129 if ( DriverGMF::isExtensionCorrect( myFile ))
130 return addMessage( SMESH_Comment("Can't open for writing ") << myFile, /*fatal=*/true );
132 return addMessage( SMESH_Comment("Not '.mesh' or '.meshb' extension of file ") << myFile, /*fatal=*/true );
135 DriverGMF::MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction
138 std::map< const SMDS_MeshNode* , int > node2IdMap;
139 int iN = 0, nbNodes = myMesh->NbNodes();
140 GmfSetKwd( meshID, GmfVertices, nbNodes );
142 SMDS_NodeIteratorPtr nodeIt = myMesh->nodesIterator();
143 while ( nodeIt->more() )
145 const SMDS_MeshNode* n = nodeIt->next();
147 GmfSetLin( meshID, GmfVertices, xyz[0], xyz[1], xyz[2], n->getshapeId() );
148 node2IdMap.insert( node2IdMap.end(), make_pair( n, ++iN ));
151 return addMessage("Wrong nb of nodes returned by nodesIterator", /*fatal=*/true);
154 SMDS_ElemIteratorPtr elemIt;
155 typedef std::map< const SMDS_MeshElement*, size_t, TIDCompare > TElem2IDMap;
158 TElem2IDMap edge2IDMap;
159 BEGIN_ELEM_WRITE( SMDSGeom_EDGE, GmfEdges, edge )
160 node2IdMap[ edge->GetNode( 0 )],
161 node2IdMap[ edge->GetNode( 1 )],
162 END_ELEM_WRITE_ADD_TO_MAP( edge, edge2IDMap );
164 // nodes of quadratic edges
165 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_EDGE, SMDSEntity_Edge,
166 GmfExtraVerticesAtEdges, edge )
167 node2IdMap[ edge->GetNode( 2 )]
168 END_EXTRA_VERTICES_WRITE();
171 TElem2IDMap tria2IDMap;
172 BEGIN_ELEM_WRITE( SMDSGeom_TRIANGLE, GmfTriangles, tria )
173 node2IdMap[ tria->GetNode( 0 )],
174 node2IdMap[ tria->GetNode( 1 )],
175 node2IdMap[ tria->GetNode( 2 )],
176 END_ELEM_WRITE_ADD_TO_MAP( tria, tria2IDMap );
178 // nodes of quadratic triangles
179 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_TRIANGLE, SMDSEntity_Triangle,
180 GmfExtraVerticesAtTriangles, tria )
181 node2IdMap[ tria->GetNode( 3 )],
182 node2IdMap[ tria->GetNode( 4 )],
183 node2IdMap[ tria->GetNode( 5 )],
184 node2IdMap[ tria->GetNodeWrap( 6 )] // for TRIA7
185 END_EXTRA_VERTICES_WRITE();
188 TElem2IDMap quad2IDMap;
189 BEGIN_ELEM_WRITE( SMDSGeom_QUADRANGLE, GmfQuadrilaterals, quad )
190 node2IdMap[ quad->GetNode( 0 )],
191 node2IdMap[ quad->GetNode( 1 )],
192 node2IdMap[ quad->GetNode( 2 )],
193 node2IdMap[ quad->GetNode( 3 )],
194 END_ELEM_WRITE_ADD_TO_MAP( quad, quad2IDMap );
196 // nodes of quadratic quadrangles
197 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_QUADRANGLE, SMDSEntity_Quadrangle,
198 GmfExtraVerticesAtQuadrilaterals, quad )
199 node2IdMap[ quad->GetNode( 4 )],
200 node2IdMap[ quad->GetNode( 5 )],
201 node2IdMap[ quad->GetNode( 6 )],
202 node2IdMap[ quad->GetNode( 7 )],
203 node2IdMap[ quad->GetNodeWrap( 8 )] // for QUAD9
204 END_EXTRA_VERTICES_WRITE();
207 BEGIN_ELEM_WRITE( SMDSGeom_TETRA, GmfTetrahedra, tetra )
208 node2IdMap[ tetra->GetNode( 0 )],
209 node2IdMap[ tetra->GetNode( 2 )],
210 node2IdMap[ tetra->GetNode( 1 )],
211 node2IdMap[ tetra->GetNode( 3 )],
212 END_ELEM_WRITE( tetra );
214 // nodes of quadratic terahedra
215 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_TETRA, SMDSEntity_Tetra,
216 GmfExtraVerticesAtTetrahedra, tetra )
217 node2IdMap[ tetra->GetNode( 6 )],
218 node2IdMap[ tetra->GetNode( 5 )],
219 node2IdMap[ tetra->GetNode( 4 )],
220 node2IdMap[ tetra->GetNode( 7 )],
221 node2IdMap[ tetra->GetNode( 9 )],
222 node2IdMap[ tetra->GetNode( 8 )]
223 //node2IdMap[ tetra->GetNodeWrap( 10 )], // for TETRA11
224 END_EXTRA_VERTICES_WRITE();
227 BEGIN_ELEM_WRITE( SMDSEntity_Pyramid, GmfPyramids, pyra )
228 node2IdMap[ pyra->GetNode( 0 )],
229 node2IdMap[ pyra->GetNode( 2 )],
230 node2IdMap[ pyra->GetNode( 1 )],
231 node2IdMap[ pyra->GetNode( 3 )],
232 node2IdMap[ pyra->GetNode( 4 )],
233 END_ELEM_WRITE( pyra );
236 BEGIN_ELEM_WRITE( SMDSGeom_HEXA, GmfHexahedra, hexa )
237 node2IdMap[ hexa->GetNode( 0 )],
238 node2IdMap[ hexa->GetNode( 3 )],
239 node2IdMap[ hexa->GetNode( 2 )],
240 node2IdMap[ hexa->GetNode( 1 )],
241 node2IdMap[ hexa->GetNode( 4 )],
242 node2IdMap[ hexa->GetNode( 7 )],
243 node2IdMap[ hexa->GetNode( 6 )],
244 node2IdMap[ hexa->GetNode( 5 )],
245 END_ELEM_WRITE( hexa );
247 // nodes of quadratic hexahedra
248 BEGIN_EXTRA_VERTICES_WRITE( SMDSGeom_HEXA, SMDSEntity_Hexa,
249 GmfExtraVerticesAtHexahedra, hexa )
250 node2IdMap[ hexa->GetNode( 11 )], // HEXA20
251 node2IdMap[ hexa->GetNode( 10 )],
252 node2IdMap[ hexa->GetNode( 9 )],
253 node2IdMap[ hexa->GetNode( 8 )],
254 node2IdMap[ hexa->GetNode( 15 )],
255 node2IdMap[ hexa->GetNode( 14 )],
256 node2IdMap[ hexa->GetNode( 13 )],
257 node2IdMap[ hexa->GetNode( 12 )],
258 node2IdMap[ hexa->GetNode( 16 )],
259 node2IdMap[ hexa->GetNode( 19 )],
260 node2IdMap[ hexa->GetNodeWrap( 18 )], // + HEXA27
261 node2IdMap[ hexa->GetNodeWrap( 17 )],
262 node2IdMap[ hexa->GetNodeWrap( 20 )],
263 node2IdMap[ hexa->GetNodeWrap( 24 )],
264 node2IdMap[ hexa->GetNodeWrap( 23 )],
265 node2IdMap[ hexa->GetNodeWrap( 22 )],
266 node2IdMap[ hexa->GetNodeWrap( 21 )],
267 node2IdMap[ hexa->GetNodeWrap( 25 )],
268 node2IdMap[ hexa->GetNodeWrap( 26 )]
269 END_EXTRA_VERTICES_WRITE();
272 BEGIN_ELEM_WRITE( SMDSEntity_Penta, GmfPrisms, prism )
273 node2IdMap[ prism->GetNode( 0 )],
274 node2IdMap[ prism->GetNode( 2 )],
275 node2IdMap[ prism->GetNode( 1 )],
276 node2IdMap[ prism->GetNode( 3 )],
277 node2IdMap[ prism->GetNode( 5 )],
278 node2IdMap[ prism->GetNode( 4 )],
279 END_ELEM_WRITE( prism );
282 if ( _exportRequiredGroups )
285 SMESH_Comment badGroups;
286 const std::set<SMESHDS_GroupBase*>& groupSet = myMesh->GetGroups();
287 std::set<SMESHDS_GroupBase*>::const_iterator grIt = groupSet.begin();
288 for ( ; grIt != groupSet.end(); ++grIt )
290 const SMESHDS_GroupBase* group = *grIt;
291 std::string groupName = group->GetStoreName();
292 std::string::size_type pos = groupName.find( "_required_" );
293 if ( pos == std::string::npos ) continue;
296 SMDSAbs_EntityType smdsEntity;
297 std::string entity = groupName.substr( pos + strlen("_required_"));
298 if ( entity == "Vertices" ) {
299 gmfKwd = GmfRequiredVertices;
300 smdsEntity = SMDSEntity_Node;
302 else if ( entity == "Edges" ) {
303 gmfKwd = GmfRequiredEdges;
304 smdsEntity = SMDSEntity_Edge;
306 else if ( entity == "Triangles" ) {
307 gmfKwd = GmfRequiredTriangles;
308 smdsEntity = SMDSEntity_Triangle;
310 else if ( entity == "Quadrilaterals" ) {
311 gmfKwd = GmfRequiredQuadrilaterals;
312 smdsEntity = SMDSEntity_Quadrangle;
315 addMessage( SMESH_Comment("Invalig gmf entity name: ") << entity, /*fatal=*/false );
319 // check elem type in the group
321 SMDS_ElemIteratorPtr elemIt = group->GetElements();
322 while ( elemIt->more() )
323 nbOkElems += ( elemIt->next()->GetEntityType() == smdsEntity );
325 if ( nbOkElems != group->Extent() && nbOkElems == 0 )
327 badGroups << " " << groupName;
331 // choose a TElem2IDMap
332 TElem2IDMap* elem2IDMap = 0;
333 if ( smdsEntity == SMDSEntity_Quadrangle && nbOkElems != myMesh->NbFaces() )
334 elem2IDMap = & quad2IDMap;
335 else if ( smdsEntity == SMDSEntity_Triangle && nbOkElems != myMesh->NbFaces() )
336 elem2IDMap = & tria2IDMap;
337 else if ( smdsEntity == SMDSEntity_Edge && nbOkElems != myMesh->NbEdges() )
338 elem2IDMap = & edge2IDMap;
341 GmfSetKwd( meshID, gmfKwd, nbOkElems );
342 elemIt = group->GetElements();
344 for ( ; elemIt->more(); )
346 const SMDS_MeshElement* elem = elemIt->next();
347 if ( elem->GetEntityType() == smdsEntity )
348 GmfSetLin( meshID, gmfKwd, (*elem2IDMap)[ elem ] );
351 for ( int gmfID = 1; elemIt->more(); ++gmfID)
353 const SMDS_MeshElement* elem = elemIt->next();
354 if ( elem->GetEntityType() == smdsEntity )
355 GmfSetLin( meshID, gmfKwd, gmfID );
360 if ( !badGroups.empty() )
361 addMessage( SMESH_Comment("Groups of elements of inappropriate geometry:")
362 << badGroups, /*fatal=*/false );
368 Driver_Mesh::Status DriverGMF_Write::PerformSizeMap( const std::vector<Control_Pnt>& points )
370 // const int dim = 3, version = sizeof(long) == 4 ? 2 : 3;
371 const int dim = 3, version = 2; // Version 3 not supported by mg-hexa
374 int verticesFileID = GmfOpenMesh( myVerticesFile.c_str(), GmfWrite, version, dim );
375 int solFileID = GmfOpenMesh( mySolFile.c_str(), GmfWrite, version, dim );
377 int pointsNumber = points.size();
380 GmfSetKwd( verticesFileID, GmfVertices, pointsNumber );
381 // SolAtVertices Keyword
382 int TypTab[] = {GmfSca};
383 GmfSetKwd(solFileID, GmfSolAtVertices, pointsNumber, 1, TypTab);
385 // Read the control points information from the vector and write it into the files
386 std::vector<Control_Pnt>::const_iterator points_it;
387 for (points_it = points.begin(); points_it != points.end(); points_it++ )
389 GmfSetLin( verticesFileID, GmfVertices, points_it->X(), points_it->Y(), points_it->Z(), 0 );
390 double ValTab[] = {points_it->Size()};
391 GmfSetLin( solFileID, GmfSolAtVertices, ValTab);
395 GmfCloseMesh( verticesFileID );
396 GmfCloseMesh( solFileID );
401 std::vector<std::string> DriverGMF_Write::GetSizeMapFiles()
403 std::vector<std::string> files;
404 files.push_back(myVerticesFile);
405 files.push_back(mySolFile);
409 //================================================================================
411 * \brief Returns an iterator on elements of a certain type
413 //================================================================================
415 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_ElementType type)
417 return myMesh->elementsIterator(type);
419 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_EntityType type)
421 return myMesh->elementEntityIterator(type);
423 SMDS_ElemIteratorPtr DriverGMF_Write::elementIterator(SMDSAbs_GeometryType type)
425 return myMesh->elementGeomIterator(type);