Salome HOME
Merge with version on tag OCC-V2_1_0d
[modules/smesh.git] / src / DriverSTL / DriverSTL_W_SMDS_Mesh.cxx
1 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
3 // 
4 //  This library is free software; you can redistribute it and/or 
5 //  modify it under the terms of the GNU Lesser General Public 
6 //  License as published by the Free Software Foundation; either 
7 //  version 2.1 of the License. 
8 // 
9 //  This library is distributed in the hope that it will be useful, 
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 //  Lesser General Public License for more details. 
13 // 
14 //  You should have received a copy of the GNU Lesser General Public 
15 //  License along with this library; if not, write to the Free Software 
16 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
17 // 
18 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
19
20 #include <stdio.h>
21
22 #include "DriverSTL_W_SMDS_Mesh.h"
23
24 #include "SMDS_Mesh.hxx"
25 #include "SMDS_MeshElement.hxx"
26 #include "SMDS_MeshNode.hxx"
27 #include <gp_XYZ.hxx>
28 #include <OSD_Path.hxx>
29 #include <OSD_File.hxx>
30 #include <OSD_FromWhere.hxx>
31 #include <OSD_Protection.hxx>
32 #include <OSD_SingleProtection.hxx>
33 #include <TCollection_AsciiString.hxx>
34 #include <TColgp_Array1OfXYZ.hxx>
35
36 #include "utilities.h"
37
38 //using namespace std;
39
40 // definition des constantes 
41 static const int LABEL_SIZE = 80;
42
43 DriverSTL_W_SMDS_Mesh::DriverSTL_W_SMDS_Mesh()
44 {
45   myIsAscii = false;
46 }
47
48 void DriverSTL_W_SMDS_Mesh::SetIsAscii( const bool theIsAscii )
49 {
50   myIsAscii = theIsAscii;
51 }
52
53 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::Perform()
54 {
55   Status aResult = DRS_OK;
56
57   if ( !myMesh ) {
58     fprintf(stderr, ">> ERROR : Mesh is null \n");
59     return DRS_FAIL;
60   }
61   if ( myIsAscii )
62     aResult = writeAscii();
63   else
64     aResult = writeBinary();
65
66   return aResult;
67 }
68
69 // static methods
70
71 static void writeInteger( const Standard_Integer& theVal,
72                          OSD_File& ofile )
73 {
74   union {
75     Standard_Integer i;
76     char c[4];
77   }u;
78
79   u.i = theVal;
80
81   Standard_Integer entier;
82   entier  =  u.c[0] & 0xFF;
83   entier |= (u.c[1] & 0xFF) << 0x08;
84   entier |= (u.c[2] & 0xFF) << 0x10;
85   entier |= (u.c[3] & 0xFF) << 0x18;
86
87   ofile.Write((char *)&entier,sizeof(u.c));
88 }
89
90 static void writeFloat  ( const Standard_ShortReal& theVal,
91                          OSD_File& ofile)
92 {
93   union {
94     Standard_ShortReal f;
95     char c[4]; 
96   }u;
97
98   u.f = theVal;
99
100   Standard_Integer entier;
101
102   entier  =  u.c[0] & 0xFF;
103   entier |= (u.c[1] & 0xFF) << 0x08;
104   entier |= (u.c[2] & 0xFF) << 0x10;
105   entier |= (u.c[3] & 0xFF) << 0x18;
106
107   ofile.Write((char *)&entier,sizeof(u.c));
108 }
109
110 static gp_XYZ getNormale( const SMDS_MeshFace* theFace )
111 {
112   gp_XYZ n;
113   int aNbNode = theFace->NbNodes();
114   TColgp_Array1OfXYZ anArrOfXYZ(1,4);
115   gp_XYZ p1, p2, p3, p4;
116   SMDS_ElemIteratorPtr aNodeItr = theFace->nodesIterator();
117   int i = 1;
118   for ( ; aNodeItr->more() && i <= 4; i++ )
119   {
120     SMDS_MeshNode* aNode = (SMDS_MeshNode*)aNodeItr->next();
121     anArrOfXYZ.SetValue(i, gp_XYZ( aNode->X(), aNode->Y(), aNode->Z() ) );
122   }
123   
124   gp_XYZ q1 = anArrOfXYZ.Value(2) - anArrOfXYZ.Value(1);
125   gp_XYZ q2 = anArrOfXYZ.Value(3) - anArrOfXYZ.Value(1);
126   n  = q1 ^ q2;
127   if ( aNbNode > 3 )
128   {
129     gp_XYZ q3 = anArrOfXYZ.Value(4) - anArrOfXYZ.Value(1);
130     n += q2 ^ q3;
131   }
132   double len = n.Modulus();
133   if ( len > 0 )
134     n /= len;
135
136   return n;
137 }
138
139 // private methods
140
141 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeAscii() const
142 {
143   Status aResult = DRS_OK;
144   TCollection_AsciiString aFileName( (char *)myFile.c_str() );
145   if ( aFileName.IsEmpty() ) {
146     fprintf(stderr, ">> ERREOR : invalid file name \n");
147     return DRS_FAIL;
148   }
149
150   OSD_File aFile = OSD_File(OSD_Path(aFileName));
151   aFile.Build(OSD_WriteOnly,OSD_Protection());
152   TCollection_AsciiString buf = TCollection_AsciiString ("solid\n");
153   aFile.Write (buf,buf.Length());buf.Clear();
154   char sval[16];
155
156   SMDS_FaceIteratorPtr itFaces = myMesh->facesIterator();
157   
158   for (; itFaces->more() ;) {
159     SMDS_MeshFace* aFace = (SMDS_MeshFace*)itFaces->next();
160     
161     if (aFace->NbNodes() == 3) {
162       gp_XYZ normale = getNormale( aFace );
163
164       buf += " facet normal "; 
165       sprintf (sval,"% 12e",normale.X());
166       buf += sval;
167       buf += " "; 
168       sprintf (sval,"% 12e",normale.Y());
169       buf += sval;
170       buf += " "; 
171       sprintf (sval,"% 12e",normale.Z());
172       buf += sval;
173       buf += '\n';
174       aFile.Write (buf,buf.Length());buf.Clear();
175       buf += "   outer loop\n"; 
176       aFile.Write (buf,buf.Length());buf.Clear();
177       
178       SMDS_ElemIteratorPtr aNodeIter = aFace->nodesIterator();
179       for (; aNodeIter->more(); ) {
180         SMDS_MeshNode* node = (SMDS_MeshNode*)aNodeIter->next();
181         buf += "     vertex "; 
182         sprintf (sval,"% 12e",node->X());
183         buf += sval;
184         buf += " "; 
185         sprintf (sval,"% 12e",node->Y());
186         buf += sval;
187         buf += " "; 
188         sprintf (sval,"% 12e",node->Z());
189         buf += sval;
190         buf += '\n';
191         aFile.Write (buf,buf.Length());buf.Clear();
192       }
193       buf += "   endloop\n"; 
194       aFile.Write (buf,buf.Length());buf.Clear();
195       buf += " endfacet\n"; 
196       aFile.Write (buf,buf.Length());buf.Clear();
197     } 
198   }
199   buf += "endsolid\n";
200   aFile.Write (buf,buf.Length());buf.Clear();
201   
202   aFile.Close ();
203
204   return aResult;
205 }
206
207 Driver_Mesh::Status DriverSTL_W_SMDS_Mesh::writeBinary() const
208 {
209   Status aResult = DRS_OK;
210   TCollection_AsciiString aFileName( (char *)myFile.c_str() );
211   if ( aFileName.IsEmpty() ) {
212     fprintf(stderr, ">> ERREOR : invalid filename \n");
213     return DRS_FAIL;
214   }
215
216   OSD_File aFile = OSD_File(OSD_Path(aFileName));
217   aFile.Build(OSD_WriteOnly,OSD_Protection());
218
219   char sval[80];
220   Standard_Integer nbTri = 0;
221   SMDS_FaceIteratorPtr itFaces = myMesh->facesIterator();
222
223   // we first count the number of triangles
224   for (;itFaces->more();) {
225     SMDS_MeshFace* aFace = (SMDS_MeshFace*)itFaces->next();
226     if (aFace->NbNodes() == 3)
227       nbTri++;
228   }
229
230   // write number of triangles
231   unsigned int NBT = nbTri;
232   aFile.Write((Standard_Address)sval,LABEL_SIZE);
233   writeInteger(nbTri,aFile);  
234
235   // loop writing nodes. take face iterator again
236   int dum=0;
237   itFaces = myMesh->facesIterator();
238   
239   for (;itFaces->more();) {
240     SMDS_MeshFace* aFace = (SMDS_MeshFace*)itFaces->next();
241     
242     if (aFace->NbNodes() == 3) {
243       gp_XYZ aNorm = getNormale( aFace );
244       writeFloat(aNorm.X(),aFile);
245       writeFloat(aNorm.Y(),aFile);
246       writeFloat(aNorm.Z(),aFile);
247
248       SMDS_ElemIteratorPtr aNodeIter = aFace->nodesIterator();
249       for (; aNodeIter->more(); ) {
250         SMDS_MeshNode* node = (SMDS_MeshNode*)aNodeIter->next();
251         writeFloat(node->X(),aFile);
252         writeFloat(node->Y(),aFile);
253         writeFloat(node->Z(),aFile);
254       }
255       aFile.Write (&dum,2);
256     } 
257   }
258   aFile.Close ();
259
260   return aResult;
261 }