GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_stltoworld.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
5  http://glc-lib.sourceforge.net
6 
7  GLC-lib is free software; you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  GLC-lib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GLC-lib; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21 *****************************************************************************/
22 
24 
25 #include "glc_stltoworld.h"
26 #include "../sceneGraph/glc_world.h"
27 #include "../glc_fileformatexception.h"
28 #include "../sceneGraph/glc_structreference.h"
29 #include "../sceneGraph/glc_structinstance.h"
30 #include "../sceneGraph/glc_structoccurence.h"
31 
32 #include <QTextStream>
33 #include <QFileInfo>
34 #include <QGLContext>
35 #include <QDataStream>
36 
38 : QObject()
39 , m_pWorld(NULL)
40 , m_FileName()
41 , m_CurrentLineNumber(0)
42 , m_StlStream()
43 , m_pCurrentMesh(NULL)
44 , m_CurrentFace()
45 , m_VertexBulk()
46 , m_NormalBulk()
47 , m_CurrentIndex(0)
48 {
49 
50 }
51 
53 {
54  clear();
55 }
56 
58 // Set Functions
60 
61 // Create an GLC_World from an input STL File
63 {
64  clear();
65  m_FileName= file.fileName();
67  // Test if the file exist and can be opened
69  if (!file.open(QIODevice::ReadOnly))
70  {
71  QString message(QString("GLC_StlToWorld::CreateWorldFromStl File ") + m_FileName + QString(" doesn't exist"));
73  throw(fileFormatException);
74  }
76  // Init member
78  m_pWorld= new GLC_World;
79 
80  // Create Working variables
81  int currentQuantumValue= 0;
82  int previousQuantumValue= 0;
83  int numberOfLine= 0;
84 
85  // Attach the stream to the file
86  m_StlStream.setDevice(&file);
87 
88  // QString buffer
89  QString lineBuff;
90 
92  // Count the number of lines of the STL file
94  while (!m_StlStream.atEnd())
95  {
96  ++numberOfLine;
97  m_StlStream.readLine();
98  }
99 
101  // Reset the stream
103  m_StlStream.resetStatus();
104  m_StlStream.seek(0);
106  // Read Buffer and create the world
108 
109  emit currentQuantum(currentQuantumValue);
111  // Search Object section in the STL
112 
113  // Test if the STL File is ASCII or Binary
115  lineBuff= m_StlStream.readLine();
116  lineBuff= lineBuff.trimmed().toLower();
117  if (!lineBuff.startsWith("solid"))
118  {
119  // The STL File is not ASCII trying to load Binary STL File
120  m_pCurrentMesh= new GLC_Mesh();
121  file.reset();
122  LoadBinariStl(file);
124  m_CurrentFace.clear();
126  m_VertexBulk.clear();
128  m_NormalBulk.clear();
130  GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
131  m_pCurrentMesh= NULL;
133  }
134  else
135  {
136  // The STL File is ASCII
137  lineBuff.remove(0, 5);
138  lineBuff= lineBuff.trimmed();
139  m_pCurrentMesh= new GLC_Mesh();
140  m_pCurrentMesh->setName(lineBuff);
141  // Read the mesh facet
142  while (!m_StlStream.atEnd())
143  {
144  scanFacet();
145 
146  currentQuantumValue = static_cast<int>((static_cast<double>(m_CurrentLineNumber) / numberOfLine) * 100);
147  if (currentQuantumValue > previousQuantumValue)
148  {
149  emit currentQuantum(currentQuantumValue);
150  }
151  previousQuantumValue= currentQuantumValue;
152  }
153  }
154  file.close();
155 
156  return m_pWorld;
157 }
158 
160 // Private services Functions
162 
163 // clear stlToWorld allocate memmory and reset member
165 {
166  if (NULL != m_pCurrentMesh)
167  {
168  delete m_pCurrentMesh;
169  m_pCurrentMesh= NULL;
170  }
171  m_pWorld= NULL;
172  m_FileName.clear();
174  m_pCurrentMesh= NULL;
175  m_CurrentFace.clear();
176 }
177 
178 // Scan a line previously extracted from STL file
180 {
183  QString lineBuff(m_StlStream.readLine());
184  lineBuff= lineBuff.trimmed().toLower();
185  // Test if this is the end of current solid
186  if (lineBuff.startsWith("endsolid") || lineBuff.startsWith("end solid"))
187  {
189  m_CurrentFace.clear();
191  m_VertexBulk.clear();
193  m_NormalBulk.clear();
194 
196  GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
197  m_pCurrentMesh= NULL;
199  return;
200  }
201  // Test if this is the start of new solid
202  if (lineBuff.startsWith("solid"))
203  {
204  // The STL File is ASCII
205  lineBuff.remove(0, 5);
206  lineBuff= lineBuff.trimmed();
207  m_pCurrentMesh= new GLC_Mesh();
208  m_pCurrentMesh->setName(lineBuff);
209  return;
210  }
211 
213  // lineBuff Must begin with "facet normal"
214  if (!lineBuff.startsWith("facet normal"))
215  {
216  QString message= "GLC_StlToWorld::scanFacet : \"facet normal\" not found!";
217  message.append("\nAt line : ");
218  message.append(QString::number(m_CurrentLineNumber));
220  clear();
221  throw(fileFormatException);
222  }
223  lineBuff.remove(0,12); // Remove first 12 chars
224  lineBuff= lineBuff.trimmed().toLower();
225  GLC_Vector3df cur3dVect= extract3dVect(lineBuff);
226  for (int i= 0; i < 3; ++i)
227  {
228  m_NormalBulk.append(cur3dVect.x());
229  m_NormalBulk.append(cur3dVect.y());
230  m_NormalBulk.append(cur3dVect.z());
231  }
232 
235  lineBuff= m_StlStream.readLine();
236  lineBuff= lineBuff.trimmed().toLower();
237  // lineBuff Must begin with "outer loop"
238  if (!lineBuff.startsWith("outer loop"))
239  {
240  QString message= "GLC_StlToWorld::scanFacet : \"outer loop\" not found!";
241  message.append("\nAt line : ");
242  message.append(QString::number(m_CurrentLineNumber));
244  clear();
245  throw(fileFormatException);
246  }
247 
249 
250  for (int i= 0; i < 3; ++i)
251  {
253  lineBuff= m_StlStream.readLine();
254  lineBuff= lineBuff.trimmed().toLower();
255  // lineBuff Must begin with "vertex"
256  if (!lineBuff.startsWith("vertex"))
257  {
258  QString message= "GLC_StlToWorld::scanFacet : \"vertex\" not found!";
259  message.append("\nAt line : ");
260  message.append(QString::number(m_CurrentLineNumber));
262  clear();
263  throw(fileFormatException);
264  }
265  lineBuff.remove(0,6); // Remove first 6 chars
266  lineBuff= lineBuff.trimmed();
267 
268  cur3dVect= extract3dVect(lineBuff);
269  m_VertexBulk.append(cur3dVect.x());
270  m_VertexBulk.append(cur3dVect.y());
271  m_VertexBulk.append(cur3dVect.z());
272 
274  ++m_CurrentIndex;
275  }
276 
279  lineBuff= m_StlStream.readLine();
280  lineBuff= lineBuff.trimmed().toLower();
281  // lineBuff Must begin with "endloop"
282  if (!lineBuff.startsWith("endloop"))
283  {
284  QString message= "GLC_StlToWorld::scanFacet : \"endloop\" not found!";
285  message.append("\nAt line : ");
286  message.append(QString::number(m_CurrentLineNumber));
288  clear();
289  throw(fileFormatException);
290  }
291 
294  lineBuff= m_StlStream.readLine();
295  lineBuff= lineBuff.trimmed().toLower();
296  // lineBuff Must begin with "endfacet"
297  if (!lineBuff.startsWith("endfacet"))
298  {
299  QString message= "GLC_StlToWorld::scanFacet : \"endfacet\" not found!";
300  message.append("\nAt line : ");
301  message.append(QString::number(m_CurrentLineNumber));
303  clear();
304  throw(fileFormatException);
305  }
306 
307 }
308 
309 // Extract a Vector from a string
311 {
312  float x=0.0f;
313  float y=0.0f;
314  float z=0.0f;
315 
316  GLC_Vector3df vectResult;
317  QTextStream stringVecteur(&line);
318 
319  QString xString, yString, zString;
320 
321  if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
322  {
323  bool xOk, yOk, zOk;
324  x= xString.toFloat(&xOk);
325  y= yString.toFloat(&yOk);
326  z= zString.toFloat(&zOk);
327  if (!(xOk && yOk && zOk))
328  {
329  QString message= "GLC_StlToWorld::extract3dVect : failed to convert vector component to float";
330  message.append("\nAt ligne : ");
331  message.append(QString::number(m_CurrentLineNumber));
333  clear();
334  throw(fileFormatException);
335  }
336  else
337  {
338  vectResult.setVect(x, y, z);
339  }
340  }
341 
342  return vectResult;
343 
344 }
345 // Load Binarie STL File
347 {
348  // Create Working variables
349  int currentQuantumValue= 0;
350  int previousQuantumValue= 0;
351 
352  QDataStream stlBinFile(&file);
353  stlBinFile.setVersion(QDataStream::Qt_4_6);
354  stlBinFile.setFloatingPointPrecision(QDataStream::SinglePrecision);
355  stlBinFile.setByteOrder(QDataStream::LittleEndian);
356 
357  // Skip 80 Bytes STL header
358  int SkipedData= stlBinFile.skipRawData(80);
359  // Check if an error occur
360  if (-1 == SkipedData)
361  {
362  QString message= "GLC_StlToWorld::LoadBinariStl : Failed to skip Header of binary STL";
364  clear();
365  throw(fileFormatException);
366  }
367  // Read the number of facet
368  quint32 numberOfFacet= 0;
369  stlBinFile >> numberOfFacet;
370  // Check if an error occur
371  if (QDataStream::Ok != stlBinFile.status())
372  {
373  QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the number of facets of binary STL";
375  clear();
376  throw(fileFormatException);
377  }
378  for (quint32 i= 0; i < numberOfFacet; ++i)
379  {
380  // Extract the facet normal
381  float nx, ny, nz;
382  stlBinFile >> nx >> ny >> nz;
383  // Check if an error occur
384  if (QDataStream::Ok != stlBinFile.status())
385  {
386  QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the Normal of binary STL";
388  clear();
389  throw(fileFormatException);
390  }
391 
392  // Extract the 3 Vertexs
393  for (int j= 0; j < 3; ++j)
394  {
395  float x, y, z;
396  stlBinFile >> x >> y >> z;
397  // Check if an error occur
398  if (QDataStream::Ok != stlBinFile.status())
399  {
400  QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the Vertex of binary STL";
402  clear();
403  throw(fileFormatException);
404  }
405  m_VertexBulk.append(x);
406  m_VertexBulk.append(y);
407  m_VertexBulk.append(z);
408 
409  m_NormalBulk.append(nx);
410  m_NormalBulk.append(ny);
411  m_NormalBulk.append(nz);
412 
414  ++m_CurrentIndex;
415  }
416  currentQuantumValue = static_cast<int>((static_cast<double>(i + 1) / numberOfFacet) * 100);
417  if (currentQuantumValue > previousQuantumValue)
418  {
419  emit currentQuantum(currentQuantumValue);
420  }
421  previousQuantumValue= currentQuantumValue;
422 
423  // Skip 2 fill-bytes not needed !!!!
424  stlBinFile.skipRawData(2);
425 
426  }
427 }
428 

©2005-2013 Laurent Ribon