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