glc_stltoworld.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  http://glc-lib.sourceforge.net
00006 
00007  GLC-lib is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU Lesser General Public License as published by
00009  the Free Software Foundation; either version 3 of the License, or
00010  (at your option) any later version.
00011 
00012  GLC-lib is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU Lesser General Public License for more details.
00016 
00017  You should have received a copy of the GNU Lesser General Public License
00018  along with GLC-lib; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 *****************************************************************************/
00022 
00024 
00025 #include "glc_stltoworld.h"
00026 #include "../sceneGraph/glc_world.h"
00027 #include "../glc_fileformatexception.h"
00028 #include "../sceneGraph/glc_structreference.h"
00029 #include "../sceneGraph/glc_structinstance.h"
00030 #include "../sceneGraph/glc_structoccurence.h"
00031 
00032 #include <QTextStream>
00033 #include <QFileInfo>
00034 #include <QGLContext>
00035 #include <QDataStream>
00036 
00037 GLC_StlToWorld::GLC_StlToWorld()
00038 : QObject()
00039 , m_pWorld(NULL)
00040 , m_FileName()
00041 , m_CurrentLineNumber(0)
00042 , m_StlStream()
00043 , m_pCurrentMesh(NULL)
00044 , m_CurrentFace()
00045 , m_VertexBulk()
00046 , m_NormalBulk()
00047 , m_CurrentIndex(0)
00048 {
00049 
00050 }
00051 
00052 GLC_StlToWorld::~GLC_StlToWorld()
00053 {
00054         clear();
00055 }
00056 
00058 // Set Functions
00060 
00061 // Create an GLC_World from an input STL File
00062 GLC_World* GLC_StlToWorld::CreateWorldFromStl(QFile &file)
00063 {
00064         clear();
00065         m_FileName= file.fileName();
00067         // Test if the file exist and can be opened
00069         if (!file.open(QIODevice::ReadOnly))
00070         {
00071                 QString message(QString("GLC_StlToWorld::CreateWorldFromStl File ") + m_FileName + QString(" doesn't exist"));
00072                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00073                 throw(fileFormatException);
00074         }
00076         // Init member
00078         m_pWorld= new GLC_World;
00079 
00080         // Create Working variables
00081         int currentQuantumValue= 0;
00082         int previousQuantumValue= 0;
00083         int numberOfLine= 0;
00084 
00085         // Attach the stream to the file
00086         m_StlStream.setDevice(&file);
00087 
00088         // QString buffer
00089         QString lineBuff;
00090 
00092         // Count the number of lines of the STL file
00094         while (!m_StlStream.atEnd())
00095         {
00096                 ++numberOfLine;
00097                 m_StlStream.readLine();
00098         }
00099 
00101         // Reset the stream
00103         m_StlStream.resetStatus();
00104         m_StlStream.seek(0);
00106         // Read Buffer and create the world
00108 
00109         emit currentQuantum(currentQuantumValue);
00110         m_CurrentLineNumber= 0;
00111         // Search Object section in the STL
00112 
00113         // Test if the STL File is ASCII or Binary
00114         ++m_CurrentLineNumber;
00115         lineBuff= m_StlStream.readLine();
00116         lineBuff= lineBuff.trimmed().toLower();
00117         if (!lineBuff.startsWith("solid"))
00118         {
00119                 // The STL File is not ASCII trying to load Binary STL File
00120                 m_pCurrentMesh= new GLC_Mesh();
00121                 file.reset();
00122                 LoadBinariStl(file);
00123                 m_pCurrentMesh->addTriangles(NULL, m_CurrentFace);
00124                 m_CurrentFace.clear();
00125                 m_pCurrentMesh->addVertice(m_VertexBulk.toVector());
00126                 m_VertexBulk.clear();
00127                 m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00128                 m_NormalBulk.clear();
00129                 m_pCurrentMesh->finish();
00130                 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00131                 m_pCurrentMesh= NULL;
00132                 m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00133         }
00134         else
00135         {
00136                 // The STL File is ASCII
00137                 lineBuff.remove(0, 5);
00138                 lineBuff= lineBuff.trimmed();
00139                 m_pCurrentMesh= new GLC_Mesh();
00140                 m_pCurrentMesh->setName(lineBuff);
00141                 // Read the mesh facet
00142                 while (!m_StlStream.atEnd())
00143                 {
00144                         scanFacet();
00145 
00146                         currentQuantumValue = static_cast<int>((static_cast<double>(m_CurrentLineNumber) / numberOfLine) * 100);
00147                         if (currentQuantumValue > previousQuantumValue)
00148                         {
00149                                 emit currentQuantum(currentQuantumValue);
00150                         }
00151                         previousQuantumValue= currentQuantumValue;
00152                 }
00153         }
00154         file.close();
00155 
00156         return m_pWorld;
00157 }
00158 
00160 // Private services Functions
00162 
00163 // clear stlToWorld allocate memmory and reset member
00164 void GLC_StlToWorld::clear()
00165 {
00166         if (NULL != m_pCurrentMesh)
00167         {
00168                 delete m_pCurrentMesh;
00169                 m_pCurrentMesh= NULL;
00170         }
00171         m_pWorld= NULL;
00172         m_FileName.clear();
00173         m_CurrentLineNumber= 0;
00174         m_pCurrentMesh= NULL;
00175         m_CurrentFace.clear();
00176 }
00177 
00178 // Scan a line previously extracted from STL file
00179 void GLC_StlToWorld::scanFacet()
00180 {
00182         ++m_CurrentLineNumber;
00183         QString lineBuff(m_StlStream.readLine());
00184         lineBuff= lineBuff.trimmed().toLower();
00185         // Test if this is the end of current solid
00186         if (lineBuff.startsWith("endsolid") || lineBuff.startsWith("end solid"))
00187         {
00188                 m_pCurrentMesh->addTriangles(NULL, m_CurrentFace);
00189                 m_CurrentFace.clear();
00190                 m_pCurrentMesh->addVertice(m_VertexBulk.toVector());
00191                 m_VertexBulk.clear();
00192                 m_pCurrentMesh->addNormals(m_NormalBulk.toVector());
00193                 m_NormalBulk.clear();
00194 
00195                 m_pCurrentMesh->finish();
00196                 GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
00197                 m_pCurrentMesh= NULL;
00198                 m_pWorld->rootOccurence()->addChild(new GLC_StructOccurence(pRep));
00199                 return;
00200         }
00201         // Test if this is the start of new solid
00202         if (lineBuff.startsWith("solid"))
00203         {
00204                 // The STL File is ASCII
00205                 lineBuff.remove(0, 5);
00206                 lineBuff= lineBuff.trimmed();
00207                 m_pCurrentMesh= new GLC_Mesh();
00208                 m_pCurrentMesh->setName(lineBuff);
00209                 return;
00210         }
00211 
00213         // lineBuff Must begin with "facet normal"
00214         if (!lineBuff.startsWith("facet normal"))
00215         {
00216                 QString message= "GLC_StlToWorld::scanFacet : \"facet normal\" not found!";
00217                 message.append("\nAt line : ");
00218                 message.append(QString::number(m_CurrentLineNumber));
00219                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00220                 clear();
00221                 throw(fileFormatException);
00222         }
00223         lineBuff.remove(0,12); // Remove first 12 chars
00224         lineBuff= lineBuff.trimmed().toLower();
00225         GLC_Vector3df cur3dVect= extract3dVect(lineBuff);
00226         for (int i= 0; i < 3; ++i)
00227         {
00228                 m_NormalBulk.append(cur3dVect.x());
00229                 m_NormalBulk.append(cur3dVect.y());
00230                 m_NormalBulk.append(cur3dVect.z());
00231         }
00232 
00234         ++m_CurrentLineNumber;
00235         lineBuff= m_StlStream.readLine();
00236         lineBuff= lineBuff.trimmed().toLower();
00237         // lineBuff Must begin with "outer loop"
00238         if (!lineBuff.startsWith("outer loop"))
00239         {
00240                 QString message= "GLC_StlToWorld::scanFacet : \"outer loop\" not found!";
00241                 message.append("\nAt line : ");
00242                 message.append(QString::number(m_CurrentLineNumber));
00243                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00244                 clear();
00245                 throw(fileFormatException);
00246         }
00247 
00249 
00250         for (int i= 0; i < 3; ++i)
00251         {
00252                 ++m_CurrentLineNumber;
00253                 lineBuff= m_StlStream.readLine();
00254                 lineBuff= lineBuff.trimmed().toLower();
00255                 // lineBuff Must begin with "vertex"
00256                 if (!lineBuff.startsWith("vertex"))
00257                 {
00258                         QString message= "GLC_StlToWorld::scanFacet : \"vertex\" not found!";
00259                         message.append("\nAt line : ");
00260                         message.append(QString::number(m_CurrentLineNumber));
00261                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00262                         clear();
00263                         throw(fileFormatException);
00264                 }
00265                 lineBuff.remove(0,6); // Remove first 6 chars
00266                 lineBuff= lineBuff.trimmed();
00267 
00268                 cur3dVect= extract3dVect(lineBuff);
00269                 m_VertexBulk.append(cur3dVect.x());
00270                 m_VertexBulk.append(cur3dVect.y());
00271                 m_VertexBulk.append(cur3dVect.z());
00272 
00273                 m_CurrentFace.append(m_CurrentIndex);
00274                 ++m_CurrentIndex;
00275         }
00276 
00278         ++m_CurrentLineNumber;
00279         lineBuff= m_StlStream.readLine();
00280         lineBuff= lineBuff.trimmed().toLower();
00281         // lineBuff Must begin with "endloop"
00282         if (!lineBuff.startsWith("endloop"))
00283         {
00284                 QString message= "GLC_StlToWorld::scanFacet : \"endloop\" not found!";
00285                 message.append("\nAt line : ");
00286                 message.append(QString::number(m_CurrentLineNumber));
00287                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00288                 clear();
00289                 throw(fileFormatException);
00290         }
00291 
00293         ++m_CurrentLineNumber;
00294         lineBuff= m_StlStream.readLine();
00295         lineBuff= lineBuff.trimmed().toLower();
00296         // lineBuff Must begin with "endfacet"
00297         if (!lineBuff.startsWith("endfacet"))
00298         {
00299                 QString message= "GLC_StlToWorld::scanFacet : \"endfacet\" not found!";
00300                 message.append("\nAt line : ");
00301                 message.append(QString::number(m_CurrentLineNumber));
00302                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00303                 clear();
00304                 throw(fileFormatException);
00305         }
00306 
00307 }
00308 
00309 // Extract a Vector from a string
00310 GLC_Vector3df GLC_StlToWorld::extract3dVect(QString &line)
00311 {
00312         float x=0.0f;
00313         float y=0.0f;
00314         float z=0.0f;
00315 
00316         GLC_Vector3df vectResult;
00317         QTextStream stringVecteur(&line);
00318 
00319         QString xString, yString, zString;
00320 
00321         if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
00322         {
00323                 bool xOk, yOk, zOk;
00324                 x= xString.toFloat(&xOk);
00325                 y= yString.toFloat(&yOk);
00326                 z= zString.toFloat(&zOk);
00327                 if (!(xOk && yOk && zOk))
00328                 {
00329                         QString message= "GLC_StlToWorld::extract3dVect : failed to convert vector component to float";
00330                         message.append("\nAt ligne : ");
00331                         message.append(QString::number(m_CurrentLineNumber));
00332                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00333                         clear();
00334                         throw(fileFormatException);
00335                 }
00336                 else
00337                 {
00338                         vectResult.setVect(x, y, z);
00339                 }
00340         }
00341 
00342         return vectResult;
00343 
00344 }
00345 // Load Binarie STL File
00346 void GLC_StlToWorld::LoadBinariStl(QFile &file)
00347 {
00348         // Create Working variables
00349         int currentQuantumValue= 0;
00350         int previousQuantumValue= 0;
00351 
00352         QDataStream stlBinFile(&file);
00353         stlBinFile.setVersion(QDataStream::Qt_4_6);
00354         stlBinFile.setFloatingPointPrecision(QDataStream::SinglePrecision);
00355         stlBinFile.setByteOrder(QDataStream::LittleEndian);
00356 
00357         // Skip 80 Bytes STL header
00358         int SkipedData= stlBinFile.skipRawData(80);
00359         // Check if an error occur
00360         if (-1 == SkipedData)
00361         {
00362                 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to skip Header of binary STL";
00363                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00364                 clear();
00365                 throw(fileFormatException);
00366         }
00367         // Read the number of facet
00368         quint32 numberOfFacet= 0;
00369         stlBinFile >> numberOfFacet;
00370         // Check if an error occur
00371         if (QDataStream::Ok != stlBinFile.status())
00372         {
00373                 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the number of facets of binary STL";
00374                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00375                 clear();
00376                 throw(fileFormatException);
00377         }
00378         for (quint32 i= 0; i < numberOfFacet; ++i)
00379         {
00380                 // Extract the facet normal
00381                 float nx, ny, nz;
00382                 stlBinFile >> nx >> ny >> nz;
00383                 // Check if an error occur
00384                 if (QDataStream::Ok != stlBinFile.status())
00385                 {
00386                         QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the Normal of binary STL";
00387                         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00388                         clear();
00389                         throw(fileFormatException);
00390                 }
00391 
00392                 // Extract the 3 Vertexs
00393                 for (int j= 0; j < 3; ++j)
00394                 {
00395                         float x, y, z;
00396                         stlBinFile >> x >> y >> z;
00397                         // Check if an error occur
00398                         if (QDataStream::Ok != stlBinFile.status())
00399                         {
00400                                 QString message= "GLC_StlToWorld::LoadBinariStl : Failed to read the Vertex of binary STL";
00401                                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00402                                 clear();
00403                                 throw(fileFormatException);
00404                         }
00405                         m_VertexBulk.append(x);
00406                         m_VertexBulk.append(y);
00407                         m_VertexBulk.append(z);
00408 
00409                         m_NormalBulk.append(nx);
00410                         m_NormalBulk.append(ny);
00411                         m_NormalBulk.append(nz);
00412 
00413                         m_CurrentFace.append(m_CurrentIndex);
00414                         ++m_CurrentIndex;
00415                 }
00416                 currentQuantumValue = static_cast<int>((static_cast<double>(i + 1) / numberOfFacet) * 100);
00417                 if (currentQuantumValue > previousQuantumValue)
00418                 {
00419                         emit currentQuantum(currentQuantumValue);
00420                 }
00421                 previousQuantumValue= currentQuantumValue;
00422 
00423                 // Skip 2 fill-bytes not needed !!!!
00424                 stlBinFile.skipRawData(2);
00425 
00426         }
00427 }
00428 

SourceForge.net Logo

©2005-2011 Laurent Ribon