Salome HOME
cdddd629d11af0c0ba9f1c03ccef63eb5b2f5d95
[modules/smesh.git] / src / DriverGMF / DriverGMF_Write.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, write 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_Write.cxx
23 // Created   : Mon Sep 17 17:03:02 2012
24 // Author    : Edward AGAPOV (eap)
25
26 #include "DriverGMF_Write.hxx"
27
28 #include "SMESHDS_GroupBase.hxx"
29 #include "SMESHDS_Mesh.hxx"
30 #include "SMESH_Comment.hxx"
31
32 extern "C"
33 {
34 #include "libmesh5.h"
35 }
36
37 #include <vector>
38
39 #define BEGIN_ELEM_WRITE( SMDSEntity, GmfKwd, elem )                    \
40   elemIt = myMesh->elementEntityIterator( SMDSEntity );                 \
41   if ( elemIt->more() )                                                 \
42   {                                                                     \
43   GmfSetKwd(meshID, GmfKwd, myMesh->GetMeshInfo().NbEntities( SMDSEntity )); \
44   for ( int gmfID = 1; elemIt->more(); ++gmfID )                        \
45   {                                                                     \
46   const SMDS_MeshElement* elem = elemIt->next();                        \
47   GmfSetLin(meshID, GmfKwd,
48
49 #define END_ELEM_WRITE( elem )                  \
50   elem->getshapeId() );                         \
51   }}                                            \
52
53 #define END_ELEM_WRITE_ADD_TO_MAP( elem, e2id )         \
54   elem->getshapeId() );                                 \
55   e2id.insert( e2id.end(), make_pair( elem, gmfID ));   \
56   }}                                                    \
57
58
59 DriverGMF_Write::DriverGMF_Write():
60   Driver_SMESHDS_Mesh()
61 {
62 }
63 DriverGMF_Write::~DriverGMF_Write()
64 {
65 }
66
67 Driver_Mesh::Status DriverGMF_Write::Perform()
68 {
69   const int dim = 3, version = 3;
70
71   int meshID = GmfOpenMesh( myFile.c_str(), GmfWrite, version, dim );
72   if ( !meshID )
73     return addMessage( SMESH_Comment("Can't open for writing ") << myFile, /*fatal=*/true );
74
75   DriverGMF_MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction
76
77   // nodes
78   std::map< const SMDS_MeshNode* , int > node2IdMap;
79   int iN = 0, nbNodes = myMesh->NbNodes();
80   GmfSetKwd( meshID, GmfVertices, nbNodes );
81   double xyz[3];
82   SMDS_NodeIteratorPtr nodeIt = myMesh->nodesIterator();
83   while ( nodeIt->more() )
84   {
85     const SMDS_MeshNode* n = nodeIt->next();
86     n->GetXYZ( xyz );
87     GmfSetLin( meshID, GmfVertices, xyz[0], xyz[1], xyz[2], n->getshapeId() );
88     node2IdMap.insert( node2IdMap.end(), make_pair( n, ++iN ));
89   }
90   if ( iN != nbNodes )
91     return addMessage("Wrong nb of nodes returned by nodesIterator", /*fatal=*/true);
92
93
94   SMDS_ElemIteratorPtr elemIt;
95   typedef std::map< const SMDS_MeshElement*, size_t, TIDCompare > TElem2IDMap;
96
97   // edges
98   TElem2IDMap edge2IDMap;
99   BEGIN_ELEM_WRITE( SMDSEntity_Edge, GmfEdges, edge )
100     node2IdMap[ edge->GetNode( 0 )],
101     node2IdMap[ edge->GetNode( 1 )],
102     END_ELEM_WRITE_ADD_TO_MAP( edge, edge2IDMap );
103     
104   // quadratic edges
105   BEGIN_ELEM_WRITE( SMDSEntity_Quad_Edge, GmfEdgesP2, edge )
106     node2IdMap[ edge->GetNode( 0 )],
107     node2IdMap[ edge->GetNode( 1 )],
108     node2IdMap[ edge->GetNode( 2 )],
109     END_ELEM_WRITE( edge );
110     
111   // triangles
112   TElem2IDMap tria2IDMap;
113   BEGIN_ELEM_WRITE( SMDSEntity_Triangle, GmfTriangles, tria )
114     node2IdMap[ tria->GetNode( 0 )],
115     node2IdMap[ tria->GetNode( 1 )],
116     node2IdMap[ tria->GetNode( 2 )],
117     END_ELEM_WRITE_ADD_TO_MAP( tria, tria2IDMap );
118     
119   // quadratic triangles
120   BEGIN_ELEM_WRITE( SMDSEntity_Quad_Triangle, GmfTrianglesP2, tria )
121     node2IdMap[ tria->GetNode( 0 )],
122     node2IdMap[ tria->GetNode( 1 )],
123     node2IdMap[ tria->GetNode( 2 )],
124     node2IdMap[ tria->GetNode( 3 )],
125     node2IdMap[ tria->GetNode( 4 )],
126     node2IdMap[ tria->GetNode( 5 )],
127     END_ELEM_WRITE( tria );
128     
129   // quadrangles
130   TElem2IDMap quad2IDMap;
131   BEGIN_ELEM_WRITE( SMDSEntity_Quadrangle, GmfQuadrilaterals, quad )
132     node2IdMap[ quad->GetNode( 0 )],
133     node2IdMap[ quad->GetNode( 1 )],
134     node2IdMap[ quad->GetNode( 2 )],
135     node2IdMap[ quad->GetNode( 3 )],
136     END_ELEM_WRITE_ADD_TO_MAP( quad, quad2IDMap );
137
138   // bi-quadratic quadrangles
139   BEGIN_ELEM_WRITE( SMDSEntity_BiQuad_Quadrangle, GmfQuadrilateralsQ2, quad )
140     node2IdMap[ quad->GetNode( 0 )],
141     node2IdMap[ quad->GetNode( 3 )],
142     node2IdMap[ quad->GetNode( 2 )],
143     node2IdMap[ quad->GetNode( 1 )],
144     node2IdMap[ quad->GetNode( 7 )],
145     node2IdMap[ quad->GetNode( 6 )],
146     node2IdMap[ quad->GetNode( 5 )],
147     node2IdMap[ quad->GetNode( 4 )],
148     node2IdMap[ quad->GetNode( 8 )],
149     END_ELEM_WRITE( quad );
150     
151   // terahedra
152   BEGIN_ELEM_WRITE( SMDSEntity_Tetra, GmfTetrahedra, tetra )
153     node2IdMap[ tetra->GetNode( 0 )],
154     node2IdMap[ tetra->GetNode( 2 )],
155     node2IdMap[ tetra->GetNode( 1 )],
156     node2IdMap[ tetra->GetNode( 3 )],
157     END_ELEM_WRITE( tetra );
158     
159   // quadratic terahedra
160   BEGIN_ELEM_WRITE( SMDSEntity_Quad_Tetra, GmfTetrahedraP2, tetra )
161     node2IdMap[ tetra->GetNode( 0 )],
162     node2IdMap[ tetra->GetNode( 2 )],
163     node2IdMap[ tetra->GetNode( 1 )],
164     node2IdMap[ tetra->GetNode( 3 )],
165     node2IdMap[ tetra->GetNode( 6 )],
166     node2IdMap[ tetra->GetNode( 5 )],
167     node2IdMap[ tetra->GetNode( 4 )],
168     node2IdMap[ tetra->GetNode( 7 )],
169     node2IdMap[ tetra->GetNode( 9 )],
170     node2IdMap[ tetra->GetNode( 8 )],
171     END_ELEM_WRITE( tetra );
172     
173   // pyramids
174   BEGIN_ELEM_WRITE( SMDSEntity_Pyramid, GmfPyramids, pyra )
175     node2IdMap[ pyra->GetNode( 0 )],
176     node2IdMap[ pyra->GetNode( 2 )],
177     node2IdMap[ pyra->GetNode( 1 )],
178     node2IdMap[ pyra->GetNode( 3 )],
179     node2IdMap[ pyra->GetNode( 4 )],
180     END_ELEM_WRITE( pyra );
181
182   // hexahedra
183   BEGIN_ELEM_WRITE( SMDSEntity_Hexa, GmfHexahedra, hexa )
184     node2IdMap[ hexa->GetNode( 0 )],
185     node2IdMap[ hexa->GetNode( 3 )],
186     node2IdMap[ hexa->GetNode( 2 )],
187     node2IdMap[ hexa->GetNode( 1 )],
188     node2IdMap[ hexa->GetNode( 4 )],
189     node2IdMap[ hexa->GetNode( 7 )],
190     node2IdMap[ hexa->GetNode( 6 )],
191     node2IdMap[ hexa->GetNode( 5 )],
192     END_ELEM_WRITE( hexa );
193
194   // tri-quadratic hexahedra
195   BEGIN_ELEM_WRITE( SMDSEntity_TriQuad_Hexa, GmfHexahedraQ2, hexa )
196     node2IdMap[ hexa->GetNode( 0 )],
197     node2IdMap[ hexa->GetNode( 3 )],
198     node2IdMap[ hexa->GetNode( 2 )],
199     node2IdMap[ hexa->GetNode( 1 )],
200     node2IdMap[ hexa->GetNode( 4 )],
201     node2IdMap[ hexa->GetNode( 7 )],
202     node2IdMap[ hexa->GetNode( 6 )],
203     node2IdMap[ hexa->GetNode( 5 )],
204     node2IdMap[ hexa->GetNode( 11 )],
205     node2IdMap[ hexa->GetNode( 10 )],
206     node2IdMap[ hexa->GetNode( 9 )],
207     node2IdMap[ hexa->GetNode( 8 )],
208     node2IdMap[ hexa->GetNode( 12 )],
209     node2IdMap[ hexa->GetNode( 15 )],
210     node2IdMap[ hexa->GetNode( 14 )],
211     node2IdMap[ hexa->GetNode( 13 )],
212     node2IdMap[ hexa->GetNode( 19 )],
213     node2IdMap[ hexa->GetNode( 18 )],
214     node2IdMap[ hexa->GetNode( 17 )],
215     node2IdMap[ hexa->GetNode( 16 )],
216     node2IdMap[ hexa->GetNode( 20 )],
217     node2IdMap[ hexa->GetNode( 24 )],
218     node2IdMap[ hexa->GetNode( 23 )],
219     node2IdMap[ hexa->GetNode( 22 )],
220     node2IdMap[ hexa->GetNode( 21 )],
221     node2IdMap[ hexa->GetNode( 25 )],
222     node2IdMap[ hexa->GetNode( 26 )],
223     END_ELEM_WRITE( hexa );
224
225   // prism
226   BEGIN_ELEM_WRITE( SMDSEntity_Penta, GmfPrisms, prism )
227     node2IdMap[ prism->GetNode( 0 )],
228     node2IdMap[ prism->GetNode( 2 )],
229     node2IdMap[ prism->GetNode( 1 )],
230     node2IdMap[ prism->GetNode( 3 )],
231     node2IdMap[ prism->GetNode( 5 )],
232     node2IdMap[ prism->GetNode( 4 )],
233     END_ELEM_WRITE( prism );
234
235
236   // required entities
237   SMESH_Comment badGroups;
238   const std::set<SMESHDS_GroupBase*>&      groupSet = myMesh->GetGroups();
239   std::set<SMESHDS_GroupBase*>::const_iterator grIt = groupSet.begin();
240   for ( ; grIt != groupSet.end(); ++grIt )
241   {
242     const SMESHDS_GroupBase* group = *grIt;
243     std::string          groupName = group->GetStoreName();
244     std::string::size_type     pos = groupName.find( "_required_" );
245     if ( pos == std::string::npos ) continue;
246
247     int                    gmfKwd;
248     SMDSAbs_EntityType smdsEntity;
249     std::string entity = groupName.substr( pos + strlen("_required_"));
250     if      ( entity == "Vertices" ) {
251       gmfKwd   = GmfRequiredVertices;
252       smdsEntity = SMDSEntity_Node;
253     }
254     else if ( entity == "Edges" ) {
255       gmfKwd   = GmfRequiredEdges;
256       smdsEntity = SMDSEntity_Edge;
257     }
258     else if ( entity == "Triangles" ) {
259       gmfKwd   = GmfRequiredTriangles;
260       smdsEntity = SMDSEntity_Triangle;
261     }
262     else if ( entity == "Quadrilaterals" ) {
263       gmfKwd   = GmfRequiredQuadrilaterals;
264       smdsEntity = SMDSEntity_Quadrangle;
265     }
266     else {
267       addMessage( SMESH_Comment("Invalig gmf entity name: ") << entity, /*fatal=*/false );
268       continue;
269     }
270
271     // check elem type in the group
272     int nbOkElems = 0;
273     SMDS_ElemIteratorPtr elemIt = group->GetElements();
274     while ( elemIt->more() )
275       nbOkElems += ( elemIt->next()->GetEntityType() == smdsEntity );
276
277     if ( nbOkElems != group->Extent() && nbOkElems == 0 )
278     {
279       badGroups << " " << groupName;
280       continue;
281     }
282
283     // choose a TElem2IDMap
284     TElem2IDMap* elem2IDMap = 0;
285     if ( smdsEntity == SMDSEntity_Quadrangle && nbOkElems != myMesh->NbFaces() )
286       elem2IDMap = & quad2IDMap;
287     else if ( smdsEntity == SMDSEntity_Triangle && nbOkElems != myMesh->NbFaces() )
288       elem2IDMap = & tria2IDMap;
289     else if ( smdsEntity == SMDSEntity_Edge && nbOkElems != myMesh->NbEdges() )
290       elem2IDMap = & edge2IDMap;
291
292     // write the group
293     GmfSetKwd( meshID, gmfKwd, nbOkElems );
294     elemIt = group->GetElements();
295     if ( elem2IDMap )
296       for ( ; elemIt->more(); )
297       {
298         const SMDS_MeshElement* elem = elemIt->next();
299         if ( elem->GetEntityType() == smdsEntity )
300           GmfSetLin( meshID, gmfKwd, (*elem2IDMap)[ elem ] );
301       }
302     else
303       for ( int gmfID = 1; elemIt->more(); ++gmfID)
304       {
305         const SMDS_MeshElement* elem = elemIt->next();
306         if ( elem->GetEntityType() == smdsEntity )
307           GmfSetLin( meshID, gmfKwd, gmfID );
308       }
309
310   } // loop on groups
311
312   if ( !badGroups.empty() )
313     addMessage( SMESH_Comment("Groups of elements of inappropriate geometry:")
314                 << badGroups, /*fatal=*/false );
315
316   return DRS_OK;
317 }