Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / DriverSTL / DriverSTL_W_SMDS_Mesh.cxx
1 //  Copyright (C) 2007-2008  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 #include <stdio.h>
23
24 #include "DriverSTL_W_SMDS_Mesh.h"
25
26 #include "SMDS_Mesh.hxx"
27 #include "SMDS_MeshElement.hxx"
28 #include "SMDS_MeshNode.hxx"
29 #include <gp_XYZ.hxx>
30 #include <OSD_Path.hxx>
31 #include <OSD_File.hxx>
32 #include <OSD_FromWhere.hxx>
33 #include <OSD_Protection.hxx>
34 #include <OSD_SingleProtection.hxx>
35 #include <TCollection_AsciiString.hxx>
36 #include <TColgp_Array1OfXYZ.hxx>
37
38 #include "utilities.h"
39
40 //using namespace std;
41
42 // definition des constantes 
43 static const int LABEL_SIZE = 80;
44
45 DriverSTL_W_SMDS_Mesh::DriverSTL_W_SMDS_Mesh()
46 {
47   myIsAscii = false;
48 }
49
50 void DriverSTL_W_SMDS_Mesh::SetIsAscii( const bool theIsAscii )
51 {
52   myIsAscii = theIsAscii;
53 }
54
55 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::Perform()
56 {
57   Status aResult = DRS_OK;
58
59   if ( !myMesh ) {
60     fprintf(stderr, ">> ERROR : Mesh is null \n");
61     return DRS_FAIL;
62   }
63   if ( myIsAscii )
64     aResult = writeAscii();
65   else
66     aResult = writeBinary();
67
68   return aResult;
69 }
70
71 // static methods
72
73 static void writeInteger( const Standard_Integer& theVal,
74                          OSD_File& ofile )
75 {
76   union {
77     Standard_Integer i;
78     char c[4];
79   }u;
80
81   u.i = theVal;
82
83   Standard_Integer entier;
84   entier  =  u.c[0] & 0xFF;
85   entier |= (u.c[1] & 0xFF) << 0x08;
86   entier |= (u.c[2] & 0xFF) << 0x10;
87   entier |= (u.c[3] & 0xFF) << 0x18;
88
89   ofile.Write((char *)&entier,sizeof(u.c));
90 }
91
92 static void writeFloat  ( const Standard_ShortReal& theVal,
93                          OSD_File& ofile)
94 {
95   union {
96     Standard_ShortReal f;
97     char c[4]; 
98   }u;
99
100   u.f = theVal;
101
102   Standard_Integer entier;
103
104   entier  =  u.c[0] & 0xFF;
105   entier |= (u.c[1] & 0xFF) << 0x08;
106   entier |= (u.c[2] & 0xFF) << 0x10;
107   entier |= (u.c[3] & 0xFF) << 0x18;
108
109   ofile.Write((char *)&entier,sizeof(u.c));
110 }
111
112 static gp_XYZ getNormale( const SMDS_MeshFace* theFace )
113 {
114   gp_XYZ n;
115   int aNbNode = theFace->NbNodes();
116   TColgp_Array1OfXYZ anArrOfXYZ(1,4);
117   gp_XYZ p1, p2, p3, p4;
118   SMDS_ElemIteratorPtr aNodeItr = theFace->nodesIterator();
119   int i = 1;
120   for ( ; aNodeItr->more() && i <= 4; i++ )
121   {
122     SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next();
123     anArrOfXYZ.SetValue(i, gp_XYZ( aNode->X(), aNode->Y(), aNode->Z() ) );
124   }
125   
126   gp_XYZ q1 = anArrOfXYZ.Value(2) - anArrOfXYZ.Value(1);
127   gp_XYZ q2 = anArrOfXYZ.Value(3) - anArrOfXYZ.Value(1);
128   n  = q1 ^ q2;
129   if ( aNbNode > 3 )
130   {
131     gp_XYZ q3 = anArrOfXYZ.Value(4) - anArrOfXYZ.Value(1);
132     n += q2 ^ q3;
133   }
134   double len = n.Modulus();
135   if ( len > 0 )
136     n /= len;
137
138   return n;
139 }
140
141 // private methods
142
143 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const
144 {
145   Status aResult = DRS_OK;
146   TCollection_AsciiString aFileName( (char *)myFile.c_str() );
147   if ( aFileName.IsEmpty() ) {
148     fprintf(stderr, ">> ERREOR : invalid file name \n");
149     return DRS_FAIL;
150   }
151
152   OSD_File aFile = OSD_File(OSD_Path(aFileName));
153   aFile.Build(OSD_WriteOnly,OSD_Protection());
154   TCollection_AsciiString buf = TCollection_AsciiString ("solid\n");
155   aFile.Write (buf,buf.Length());buf.Clear();
156   char sval[16];
157
158   SMDS_FaceIteratorPtr itFaces = myMesh->facesIterator();
159   
160   for (; itFaces->more() ;) {
161     SMDS_MeshFace* aFace = (SMDS_MeshFace*)itFaces->next();
162     
163     if (aFace->NbNodes() == 3) {
164       gp_XYZ normale = getNormale( aFace );
165
166       buf += " facet normal "; 
167       sprintf (sval,"% 12e",normale.X());
168       buf += sval;
169       buf += " "; 
170       sprintf (sval,"% 12e",normale.Y());
171       buf += sval;
172       buf += " "; 
173       sprintf (sval,"% 12e",normale.Z());
174       buf += sval;
175       buf += '\n';
176       aFile.Write (buf,buf.Length());buf.Clear();
177       buf += "   outer loop\n"; 
178       aFile.Write (buf,buf.Length());buf.Clear();
179       
180       SMDS_ElemIteratorPtr aNodeIter = aFace->nodesIterator();
181       for (; aNodeIter->more(); ) {
182         SMDS_MeshNode* node = (SMDS_MeshNode*)aNodeIter->next();
183         buf += "     vertex "; 
184         sprintf (sval,"% 12e",node->X());
185         buf += sval;
186         buf += " "; 
187         sprintf (sval,"% 12e",node->Y());
188         buf += sval;
189         buf += " "; 
190         sprintf (sval,"% 12e",node->Z());
191         buf += sval;
192         buf += '\n';
193         aFile.Write (buf,buf.Length());buf.Clear();
194       }
195       buf += "   endloop\n"; 
196       aFile.Write (buf,buf.Length());buf.Clear();
197       buf += " endfacet\n"; 
198       aFile.Write (buf,buf.Length());buf.Clear();
199     } 
200   }
201   buf += "endsolid\n";
202   aFile.Write (buf,buf.Length());buf.Clear();
203   
204   aFile.Close ();
205
206   return aResult;
207 }
208
209 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const
210 {
211   Status aResult = DRS_OK;
212   TCollection_AsciiString aFileName( (char *)myFile.c_str() );
213   if ( aFileName.IsEmpty() ) {
214     fprintf(stderr, ">> ERREOR : invalid filename \n");
215     return DRS_FAIL;
216   }
217
218   OSD_File aFile = OSD_File(OSD_Path(aFileName));
219   aFile.Build(OSD_WriteOnly,OSD_Protection());
220
221   char sval[80];
222   Standard_Integer nbTri = 0;
223   SMDS_FaceIteratorPtr itFaces = myMesh->facesIterator();
224
225   // we first count the number of triangles
226   for (;itFaces->more();) {
227     SMDS_MeshFace* aFace = (SMDS_MeshFace*)itFaces->next();
228     if (aFace->NbNodes() == 3)
229       nbTri++;
230   }
231
232   // write number of triangles
233   //unsigned int NBT = nbTri;
234   aFile.Write((Standard_Address)sval,LABEL_SIZE);
235   writeInteger(nbTri,aFile);  
236
237   // loop writing nodes. take face iterator again
238   int dum=0;
239   itFaces = myMesh->facesIterator();
240   
241   for (;itFaces->more();) {
242     SMDS_MeshFace* aFace = (SMDS_MeshFace*)itFaces->next();
243     
244     if (aFace->NbNodes() == 3) {
245       gp_XYZ aNorm = getNormale( aFace );
246       writeFloat(aNorm.X(),aFile);
247       writeFloat(aNorm.Y(),aFile);
248       writeFloat(aNorm.Z(),aFile);
249
250       SMDS_ElemIteratorPtr aNodeIter = aFace->nodesIterator();
251       for (; aNodeIter->more(); ) {
252         SMDS_MeshNode* node = (SMDS_MeshNode*)aNodeIter->next();
253         writeFloat(node->X(),aFile);
254         writeFloat(node->Y(),aFile);
255         writeFloat(node->Z(),aFile);
256       }
257       aFile.Write (&dum,2);
258     } 
259   }
260   aFile.Close ();
261
262   return aResult;
263 }