1 // Copyright (C) 2007-2012 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.
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
25 #include <Basics_Utils.hxx>
27 //=======================================================================
30 //=======================================================================
31 inline Standard_Integer HashCode
32 (const gp_Pnt& point, Standard_Integer Upper)
37 Standard_Integer I[6];
40 point.Coord(U.R[0],U.R[1],U.R[2]);
42 return ::HashCode(U.I[0]/23+U.I[1]/19+U.I[2]/17+U.I[3]/13+U.I[4]/11+U.I[5]/7,Upper);
44 static Standard_Real tab1[3];
45 static Standard_Real tab2[3];
46 //=======================================================================
49 //=======================================================================
50 inline Standard_Boolean IsEqual
51 (const gp_Pnt& point1, const gp_Pnt& point2)
53 point1.Coord(tab1[0],tab1[1],tab1[2]);
54 point2.Coord(tab2[0],tab2[1],tab2[2]);
55 return (memcmp(tab1,tab2,sizeof(tab1)) == 0);
57 #include "DriverSTL_R_SMDS_Mesh.h"
59 #include "SMDS_Mesh.hxx"
60 #include "SMDS_MeshElement.hxx"
61 #include "SMDS_MeshNode.hxx"
63 #include <OSD_Path.hxx>
64 #include <OSD_File.hxx>
65 #include <OSD_FromWhere.hxx>
66 #include <OSD_Protection.hxx>
67 #include <OSD_SingleProtection.hxx>
68 #include <Standard_NoMoreObject.hxx>
70 #include "utilities.h"
72 static const int HEADER_SIZE = 84;
73 static const int SIZEOF_STL_FACET = 50;
74 //static const int STL_MIN_FILE_SIZE = 284;
75 static const int ASCII_LINES_PER_FACET = 7;
78 //typedef NCollection_BaseCollection<SMDS_MeshNodePtr> DriverSTL_ColOfNodePtr;
81 #include <NCollection_DataMap.hxx>
82 typedef NCollection_DataMap<gp_Pnt,SMDS_MeshNode*> DriverSTL_DataMapOfPntNodePtr;
83 //=======================================================================
84 //function : DriverSTL_R_SMDS_Mesh
86 //=======================================================================
88 DriverSTL_R_SMDS_Mesh::DriverSTL_R_SMDS_Mesh()
90 myIsCreateFaces = true;
91 myIsAscii = Standard_True;
94 //=======================================================================
95 //function : SetIsCreateFaces
97 //=======================================================================
99 void DriverSTL_R_SMDS_Mesh::SetIsCreateFaces( const bool theIsCreate )
100 { myIsCreateFaces = theIsCreate; }
102 //=======================================================================
105 //=======================================================================
107 Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::Perform()
109 Kernel_Utils::Localizer loc;
111 Status aResult = DRS_OK;
113 TCollection_AsciiString aFileName( (char *)myFile.c_str() );
114 if ( aFileName.IsEmpty() ) {
115 fprintf(stderr, ">> ERREOR : invalid file name \n");
120 Standard_IStream is(&fic);
121 if (!fic.open(aFileName.ToCString(),ios::in)) {
122 fprintf(stderr, ">> ERROR : cannot open file %s \n", aFileName.ToCString());
127 OSD_Path aPath( aFileName );
128 OSD_File file = OSD_File( aPath );
129 file.Open(OSD_ReadOnly,OSD_Protection(OSD_RWD,OSD_RWD,OSD_RWD,OSD_RWD));
130 unsigned char str[128];
131 Standard_Integer lread,i;
132 Standard_Address ach;
133 ach = (Standard_Address)str;
134 // we skip the header which is in Ascii for both modes
135 file.Read(ach,HEADER_SIZE,lread);
137 // we read 128 characters to detect if we have a non-ascii char
138 file.Read(ach,sizeof(str),lread);
140 myIsAscii = Standard_True;
141 for (i = 0; i < lread; ++i) {
143 myIsAscii = Standard_False;
151 fprintf(stderr, ">> ERREOR : cannot create mesh \n");
156 aResult = readAscii();
158 aResult = readBinary();
165 static Standard_Real readFloat(OSD_File& theFile)
169 Standard_ShortReal f;
173 Standard_Address adr;
174 adr = (Standard_Address)c;
175 Standard_Integer lread;
176 theFile.Read(adr,4,lread);
178 u.i |= (c[1] & 0xFF) << 0x08;
179 u.i |= (c[2] & 0xFF) << 0x10;
180 u.i |= (c[3] & 0xFF) << 0x18;
185 static SMDS_MeshNode* addNode(const gp_Pnt& P,
186 DriverSTL_DataMapOfPntNodePtr& uniqnodes,
189 SMDS_MeshNode* node = 0;
190 if ( uniqnodes.IsBound(P) ) {
191 node = uniqnodes.Find(P);
193 node = theMesh->AddNode(P.X(), P.Y(), P.Z() );
194 uniqnodes.Bind(P,node);
200 static SMDS_MeshNode* readNode(FILE* file,
201 DriverSTL_DataMapOfPntNodePtr& uniqnodes,
204 Standard_ShortReal coord[3];
206 fscanf(file,"%*s %f %f %f\n",&coord[0],&coord[1],&coord[2]);
208 gp_Pnt P(coord[0],coord[1],coord[2]);
209 return addNode( P, uniqnodes, theMesh );
212 static SMDS_MeshNode* readNode(OSD_File& theFile,
213 DriverSTL_DataMapOfPntNodePtr& uniqnodes,
216 Standard_ShortReal coord[3];
217 coord[0] = readFloat(theFile);
218 coord[1] = readFloat(theFile);
219 coord[2] = readFloat(theFile);
221 gp_Pnt P(coord[0],coord[1],coord[2]);
222 return addNode( P, uniqnodes, theMesh );
225 //=======================================================================
226 //function : readAscii
228 //=======================================================================
230 Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readAscii() const
232 Status aResult = DRS_OK;
234 Standard_Integer nbLines = 0;
237 TCollection_AsciiString aFileName( (char *)myFile.c_str() );
238 FILE* file = fopen(aFileName.ToCString(),"r");
239 fseek(file,0L,SEEK_END);
241 long filesize = ftell(file);
243 file = fopen(aFileName.ToCString(),"r");
245 // count the number of lines
246 for (ipos = 0; ipos < filesize; ++ipos) {
247 if (getc(file) == '\n')
251 // go back to the beginning of the file
253 // file = fopen(aFileName.ToCString(),"r");
256 Standard_Integer nbTri = (nbLines / ASCII_LINES_PER_FACET);
258 DriverSTL_DataMapOfPntNodePtr uniqnodes;
260 while (getc(file) != '\n');
263 for (Standard_Integer iTri = 0; iTri < nbTri; ++iTri) {
265 // skipping the facet normal
266 Standard_ShortReal normal[3];
267 fscanf(file,"%*s %*s %f %f %f\n",&normal[0],&normal[1],&normal[2]);
269 // skip the keywords "outer loop"
270 fscanf(file,"%*s %*s");
273 SMDS_MeshNode* node1 = readNode( file, uniqnodes, myMesh );
274 SMDS_MeshNode* node2 = readNode( file, uniqnodes, myMesh );
275 SMDS_MeshNode* node3 = readNode( file, uniqnodes, myMesh );
278 myMesh->AddFace(node1,node2,node3);
280 // skip the keywords "endloop"
283 // skip the keywords "endfacet"
291 //=======================================================================
292 //function : readBinary
294 //=======================================================================
296 Driver_Mesh::Status DriverSTL_R_SMDS_Mesh::readBinary() const
298 Status aResult = DRS_OK;
301 Standard_Address adr;
302 adr = (Standard_Address)buftest;
304 TCollection_AsciiString aFileName( (char *)myFile.c_str() );
305 OSD_File aFile = OSD_File(OSD_Path( aFileName ));
306 aFile.Open(OSD_ReadOnly,OSD_Protection(OSD_RWD,OSD_RWD,OSD_RWD,OSD_RWD));
308 // the size of the file (minus the header size)
309 // must be a multiple of SIZEOF_STL_FACET
312 Standard_Integer filesize = aFile.Size();
314 if ( (filesize - HEADER_SIZE) % SIZEOF_STL_FACET !=0
315 // Commented to allow reading small files (ex: 1 face)
316 /*|| (filesize < STL_MIN_FILE_SIZE)*/) {
317 Standard_NoMoreObject::Raise("DriverSTL_R_SMDS_MESH::readBinary (wrong file size)");
320 // don't trust the number of triangles which is coded in the file
321 // sometimes it is wrong, and with this technique we don't need to swap endians for integer
322 Standard_Integer nbTri = ((filesize - HEADER_SIZE) / SIZEOF_STL_FACET);
325 aFile.Seek(HEADER_SIZE,OSD_FromBeginning);
327 DriverSTL_DataMapOfPntNodePtr uniqnodes;
328 Standard_Integer lread;
330 for (Standard_Integer iTri = 0; iTri < nbTri; ++iTri) {
338 SMDS_MeshNode* node1 = readNode( aFile, uniqnodes, myMesh );
339 SMDS_MeshNode* node2 = readNode( aFile, uniqnodes, myMesh );
340 SMDS_MeshNode* node3 = readNode( aFile, uniqnodes, myMesh );
343 myMesh->AddFace(node1,node2,node3);
346 aFile.Read(adr,2,lread);